diff --git a/webui/src/features/campaigns/CampaignAuditPage.tsx b/webui/src/features/campaigns/CampaignAuditPage.tsx index 8d21e48..561a5e5 100644 --- a/webui/src/features/campaigns/CampaignAuditPage.tsx +++ b/webui/src/features/campaigns/CampaignAuditPage.tsx @@ -19,7 +19,7 @@ export default function CampaignAuditPage({ settings, campaignId }: {settings: A
- +
@@ -32,4 +32,4 @@ export default function CampaignAuditPage({ settings, campaignId }: {settings: A ); -} \ No newline at end of file +} diff --git a/webui/src/features/campaigns/CampaignFieldsPage.tsx b/webui/src/features/campaigns/CampaignFieldsPage.tsx index 75a230e..4787825 100644 --- a/webui/src/features/campaigns/CampaignFieldsPage.tsx +++ b/webui/src/features/campaigns/CampaignFieldsPage.tsx @@ -22,7 +22,7 @@ export default function CampaignFieldsPage({ settings, campaignId }: {settings: const version = data.currentVersion; const locked = isAuditLockedVersion(version, data.campaign?.current_version_id); - const { draft, setDraft, displayDraft, dirty, saveState, setSaveState, localError, setLocalError, markDirty, saveDraft } = useCampaignDraftEditor({ + const { draft, setDraft, displayDraft, dirty, saveState, setSaveState, localError, setLocalError, markDirty, discardDraft, saveDraft } = useCampaignDraftEditor({ settings, campaignId, version, @@ -157,7 +157,7 @@ export default function CampaignFieldsPage({ settings, campaignId }: {settings:
- +
diff --git a/webui/src/features/campaigns/CampaignJsonView.tsx b/webui/src/features/campaigns/CampaignJsonView.tsx index 40b6eef..7d7edd3 100644 --- a/webui/src/features/campaigns/CampaignJsonView.tsx +++ b/webui/src/features/campaigns/CampaignJsonView.tsx @@ -24,7 +24,7 @@ export default function CampaignJsonView({ settings, campaignId }: {settings: Ap
- +
@@ -36,4 +36,4 @@ export default function CampaignJsonView({ settings, campaignId }: {settings: Ap ); -} \ No newline at end of file +} diff --git a/webui/src/features/campaigns/CampaignListPage.tsx b/webui/src/features/campaigns/CampaignListPage.tsx index 47d96d5..f2b8e11 100644 --- a/webui/src/features/campaigns/CampaignListPage.tsx +++ b/webui/src/features/campaigns/CampaignListPage.tsx @@ -149,7 +149,7 @@ export default function CampaignListPage({ settings }: {settings: ApiSettings;})

{lastLoadedAt ? i18nMessage("i18n:govoplan-campaign.last_loaded_value.35ef046a", { value0: lastLoadedAt }) : "i18n:govoplan-campaign.not_loaded_yet.9968c191"}

- + diff --git a/webui/src/features/campaigns/CampaignOverviewPage.tsx b/webui/src/features/campaigns/CampaignOverviewPage.tsx index e5f816c..a90d51b 100644 --- a/webui/src/features/campaigns/CampaignOverviewPage.tsx +++ b/webui/src/features/campaigns/CampaignOverviewPage.tsx @@ -131,6 +131,19 @@ export default function CampaignOverviewPage({ settings, campaignId }: {settings } } + async function discardOverview() { + if (campaign) { + setIdentity({ + external_id: campaign.external_id ?? "", + name: campaign.name ?? "", + status: campaign.status ?? "", + description: campaign.description ?? "" + }); + setIdentityDirty(false); + } + await reload({ force: true }); + } + return (
@@ -139,8 +152,7 @@ export default function CampaignOverviewPage({ settings, campaignId }: {settings

i18n:govoplan-campaign.campaign_overview_version_independent_identity_a.ebaf1113

- - +
@@ -149,13 +161,6 @@ export default function CampaignOverviewPage({ settings, campaignId }: {settings {message && {message}} -
- - - - -
-
@@ -163,23 +168,10 @@ export default function CampaignOverviewPage({ settings, campaignId }: {settings
- - - i18n:govoplan-campaign.open.cf9b7706 - }> -
- - - - -
-
- - + }>
patchIdentity("external_id", event.target.value)} /> @@ -198,8 +190,27 @@ export default function CampaignOverviewPage({ settings, campaignId }: {settings
- -
+ + + i18n:govoplan-campaign.open.cf9b7706 + }> +
+ + + + +
+
+ + + + +
+
span:first-child { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.recipient-address-header-summary.is-empty { + color: var(--muted); + font-style: italic; +} +.recipient-address-inline-button { + width: 28px; + height: 28px; +} +.recipient-address-inline-button svg { + width: 16px; + height: 16px; +} .recipient-add-row td { background: var(--panel-soft); } @@ -922,13 +969,160 @@ /* Recipient/profile split pages. */ .recipient-address-table th:nth-child(1), -.recipient-address-table td:nth-child(1) { width: 42px; } +.recipient-address-table td:nth-child(1) { width: 72px; } .recipient-address-table th:last-child, -.recipient-address-table td:last-child { width: 123px; } -.recipient-address-table td { vertical-align: top; } -.recipient-address-table .email-address-input { min-width: 220px; } +.recipient-address-table td:last-child { width: 180px; } +.recipient-address-table td { vertical-align: middle; } .recipient-address-table .toggle-switch { white-space: nowrap; } +.recipient-address-editor-trigger { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + width: 100%; + min-height: 34px; + border: var(--border-line); + border-radius: var(--radius-sm); + background: var(--panel); + color: var(--text); + cursor: pointer; + font: inherit; + padding: 5px 8px; + text-align: left; +} + +.recipient-address-editor-trigger:hover, +.recipient-address-editor-trigger:focus-visible { + border-color: var(--accent); + background: var(--surface-subtle); + outline: none; +} + +.recipient-address-editor-trigger.is-readonly { + cursor: default; + opacity: .78; +} + +.recipient-address-editor-trigger.is-readonly:hover { + border-color: var(--line); + background: var(--panel); +} + +.recipient-address-editor-trigger svg { + flex: 0 0 auto; + width: 16px; + height: 16px; + color: var(--muted); +} + +.recipient-address-editor-main { + display: flex; + align-items: center; + gap: 6px; + min-width: 0; + flex-wrap: wrap; +} + +.recipient-data-address.is-empty { + color: var(--muted); + font-style: italic; +} + +.recipient-address-editor-modal { + width: min(900px, calc(100vw - 32px)); +} + +.recipient-address-editor-body { + max-height: min(72vh, 760px); + overflow: auto; +} + +.recipient-address-editor { + display: grid; + gap: 12px; +} + +.recipient-address-category { + display: grid; + gap: 10px; + min-width: 0; + border: var(--border-line); + border-radius: var(--radius-sm); + background: var(--panel); + padding: 10px; +} + +.recipient-address-category-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.recipient-address-category-header h3 { + margin: 0; + font-size: 15px; + color: var(--text-strong); +} + +.recipient-address-category-controls { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + justify-content: flex-end; +} + +.recipient-address-mode-static { + display: inline-flex; + align-items: center; + min-height: 32px; + border: var(--border-line); + border-radius: var(--radius-sm); + background: var(--panel-soft); + color: var(--muted); + font-size: 12px; + font-weight: 700; + padding: 0 10px; +} + +.recipient-address-lines { + display: grid; + gap: 8px; +} + +.recipient-address-empty-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 8px; + align-items: center; +} + +.recipient-address-empty { + margin: 0; +} + +.recipient-address-edit-line { + display: grid; + grid-template-columns: minmax(150px, .7fr) minmax(220px, 1fr) auto; + gap: 8px; + align-items: center; +} + +.recipient-address-edit-line input { + min-width: 0; +} + +.recipient-address-line-actions { + width: auto; + justify-content: end; +} + +.recipient-merged-data-table .recipient-field-input { + min-width: 150px; +} + .recipient-data-table td { vertical-align: top; } .recipient-data-identity-cell { white-space: normal !important; } .recipient-data-identity { @@ -973,6 +1167,18 @@ .recipient-data-table td:nth-child(3) { min-width: 192px; } .recipient-index-cell { white-space: nowrap; } +@media (max-width: 720px) { + .recipient-address-empty-row, + .recipient-address-edit-line { + grid-template-columns: 1fr; + } + + .recipient-address-category-header { + align-items: flex-start; + flex-direction: column; + } +} + .locked-version-notice .alert-message { display: flex; align-items: center; @@ -1067,6 +1273,12 @@ } /* Overview version history refinements. */ +.version-history-table-surface { + margin-top: 14px; + max-height: 420px; + overflow: auto; +} + .version-history-table .current-version-row td { font-weight: 700; } @@ -1128,6 +1340,10 @@ min-height: 68px; } +.message-preview-modal .modal-footer > .button-row { + margin-right: auto; +} + .message-preview-modal .message-display-body, .message-preview-modal .message-display-html-frame { height: clamp(280px, 45vh, 520px); @@ -1247,7 +1463,7 @@ } /* Review & Send workflow page. */ .review-send-page { - --review-flow-purple: var(--review-flow-purple); + --review-flow-partial: var(--review-flow-purple, #9b86c7); } .review-flow-navigation { @@ -1344,7 +1560,11 @@ height: 2px; margin: 21px 2px 0; flex: 0 0 auto; - background: linear-gradient(to right, var(--review-nav-color), var(--review-nav-next-color)); + background: linear-gradient( + to right, + var(--review-nav-line-color, var(--review-nav-color)), + var(--review-nav-line-next-color, var(--review-nav-next-color, var(--review-nav-color))) + ); opacity: .82; } @@ -1395,7 +1615,11 @@ min-height: 54px; margin: 4px 0 -14px; border-radius: 999px; - background: linear-gradient(to bottom, var(--review-stage-color), var(--review-next-stage-color)); + background: linear-gradient( + to bottom, + var(--review-stage-line-color, var(--review-stage-color)), + var(--review-next-stage-line-color, var(--review-next-stage-color, var(--review-stage-color))) + ); opacity: .82; } @@ -1452,12 +1676,132 @@ .review-flow-state-badge[data-state="active"], .review-flow-state-badge[data-state="running"] { --review-badge-color: var(--blue); } .review-flow-state-badge[data-state="partial"], -.review-flow-state-badge[data-state="stale"] { --review-badge-color: var(--review-flow-purple); } +.review-flow-state-badge[data-state="stale"] { --review-badge-color: var(--review-flow-partial); } .review-flow-stage-content { min-height: 150px; } +.attachment-linking-preview { + margin-top: 14px; +} + +.attachment-linking-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; +} + +.attachment-linking-header h3 { + margin: 0 0 4px; +} + +.attachment-linking-file-list { + display: grid; + gap: 6px; + margin: 10px 0 0; + padding: 0; + list-style: none; +} + +.attachment-linking-file-list.is-compact { + max-height: min(240px, 32vh); + overflow: auto; + padding-right: 4px; + scrollbar-gutter: stable; +} + +.attachment-linking-file-list:focus-visible { + border-radius: var(--radius-sm); + outline: 2px solid var(--accent); + outline-offset: 3px; +} + +.attachment-linking-file-list li { + display: grid; + grid-template-columns: 22px minmax(0, 1fr); + gap: 8px; + align-items: flex-start; + padding: 7px 8px; + border: var(--border-line); + border-radius: var(--radius-sm); + background: var(--surface); +} + +.attachment-linking-file-list li > svg { + width: 18px; + height: 18px; + margin-top: 1px; + color: var(--green); +} + +.attachment-linking-file-list li[data-linked="false"] > svg { + color: var(--red); +} + +.attachment-linking-file-list li > span { + display: grid; + gap: 2px; + min-width: 0; +} + +.attachment-linking-file-list strong, +.attachment-linking-file-list small { + min-width: 0; + overflow-wrap: anywhere; +} + +.attachment-linking-file-list strong { + color: var(--text-strong); +} + +.attachment-linking-file-list small { + color: var(--muted); + font-size: 12px; +} + +.review-flow-fact-detail-button { + border: 0; + border-bottom: 1px solid currentColor; + background: transparent; + color: inherit; + cursor: pointer; + font: inherit; + font-weight: inherit; + padding: 0; +} + +.review-flow-fact-detail-button:hover, +.review-flow-fact-detail-button:focus-visible { + color: var(--accent); + outline: none; +} + +.attachment-linking-detail-modal { + width: min(760px, calc(100vw - 48px)); + height: min(680px, calc(100dvh - 48px)); +} + +.attachment-linking-detail-body { + display: grid; + grid-template-rows: auto minmax(0, 1fr); + gap: 12px; + overflow: hidden; +} + +.attachment-linking-detail-body > .small-note { + margin: 0; +} + +.attachment-linking-file-list.is-detail { + min-height: 0; + margin: 0; + overflow: auto; + padding-right: 4px; + scrollbar-gutter: stable; +} + .review-flow-stage-card.is-locked .review-flow-stage-header { opacity: .58; filter: grayscale(.25); @@ -1587,8 +1931,8 @@ background: color-mix(in srgb, var(--red) 10%, var(--surface)); } .review-flow-inline-note.is-stale { - border-left-color: var(--review-flow-purple); - background: color-mix(in srgb, var(--review-flow-purple) 11%, var(--surface)); + border-left-color: var(--review-flow-partial); + background: color-mix(in srgb, var(--review-flow-partial) 11%, var(--surface)); } .review-flow-result-line { @@ -1693,6 +2037,15 @@ .review-flow-data-section > .data-grid-shell { max-height: 420px; + display: flex; + flex-direction: column; +} + +.review-flow-data-section > .data-grid-shell > .data-grid-scroll-region { + flex: 1 1 auto; + min-height: 0; + max-height: 420px; + overflow: auto; } .review-flow-data-section > .small-note { @@ -1779,6 +2132,7 @@ .attachment-zip-table-wrap .toggle-switch-row { min-height: 36px; gap: 8px; + white-space: nowrap; } .attachment-zip-table-wrap select {