Complete recipient search and delivery evidence
This commit is contained in:
@@ -24,7 +24,7 @@ import { DismissibleAlert } from "@govoplan/core-webui";
|
||||
import { Dialog } from "@govoplan/core-webui";
|
||||
import { SegmentedControl } from "@govoplan/core-webui";
|
||||
import { TableActionGroup } from "@govoplan/core-webui";
|
||||
import { DataGrid, DataGridEmptyAction, DataGridRowActions, type DataGridColumn } from "@govoplan/core-webui";
|
||||
import { DataGrid, DataGridEmptyAction, DataGridRowActions, type DataGridColumn, type DataGridQueryState } from "@govoplan/core-webui";
|
||||
import { useCampaignWorkspaceData } from "./hooks/useCampaignWorkspaceData";
|
||||
import { useCampaignDraftEditor } from "./hooks/useCampaignDraftEditor";
|
||||
import { asArray, asRecord, isAuditLockedVersion } from "./utils/campaignView";
|
||||
@@ -124,6 +124,7 @@ export default function RecipientDataPage({ settings, campaignId }: {settings: A
|
||||
const [addressSources, setAddressSources] = useState<CampaignRecipientAddressSource[]>([]);
|
||||
const [recipientProfilesPage, setRecipientProfilesPage] = useState(1);
|
||||
const [recipientProfilesPageSize, setRecipientProfilesPageSize] = useState(10);
|
||||
const [recipientProfilesQuery, setRecipientProfilesQuery] = useState<DataGridQueryState>({ sort: null, filters: {} });
|
||||
const [recipientAddressEditorIndex, setRecipientAddressEditorIndex] = useState<number | null>(null);
|
||||
const [postboxTargetEditorIndex, setPostboxTargetEditorIndex] = useState<number | null>(null);
|
||||
const [postboxCatalog, setPostboxCatalog] = useState<CampaignPostboxCatalog>({
|
||||
@@ -526,6 +527,7 @@ export default function RecipientDataPage({ settings, campaignId }: {settings: A
|
||||
fieldDefinitions,
|
||||
individualAttachmentBasePaths,
|
||||
zipConfig,
|
||||
addressFilter: recipientProfilesQuery.filters.recipients ?? "",
|
||||
translateText,
|
||||
openAddressEditor: setRecipientAddressEditorIndex,
|
||||
openPostboxTargetEditor: setPostboxTargetEditorIndex,
|
||||
@@ -549,7 +551,8 @@ export default function RecipientDataPage({ settings, campaignId }: {settings: A
|
||||
setRecipientProfilesPageSize(pageSize);
|
||||
setRecipientProfilesPage(1);
|
||||
}
|
||||
}} />
|
||||
}}
|
||||
onQueryChange={setRecipientProfilesQuery} />
|
||||
|
||||
</div>
|
||||
}
|
||||
@@ -1735,6 +1738,7 @@ type RecipientProfileColumnContext = {
|
||||
fieldDefinitions: ReturnType<typeof getDraftFields>;
|
||||
individualAttachmentBasePaths: ReturnType<typeof getIndividualAttachmentBasePaths>;
|
||||
zipConfig: AttachmentZipCollection;
|
||||
addressFilter: string;
|
||||
translateText: (value: string) => string;
|
||||
openAddressEditor: (index: number) => void;
|
||||
openPostboxTargetEditor: (index: number) => void;
|
||||
@@ -1746,7 +1750,7 @@ type RecipientProfileColumnContext = {
|
||||
removeEntry: (index: number) => void;
|
||||
};
|
||||
|
||||
function recipientProfileColumns({ settings, campaignId, draft, locked, filesModuleInstalled, postboxModuleInstalled, postboxCatalog, entries, fieldDefinitions, individualAttachmentBasePaths, zipConfig, translateText, openAddressEditor, openPostboxTargetEditor, updateEntry, updateEntryAttachments, updateEntryField, addRecipient, moveEntry, removeEntry }: RecipientProfileColumnContext): DataGridColumn<Record<string, unknown>>[] {
|
||||
function recipientProfileColumns({ settings, campaignId, draft, locked, filesModuleInstalled, postboxModuleInstalled, postboxCatalog, entries, fieldDefinitions, individualAttachmentBasePaths, zipConfig, addressFilter, translateText, openAddressEditor, openPostboxTargetEditor, updateEntry, updateEntryAttachments, updateEntryField, addRecipient, moveEntry, removeEntry }: RecipientProfileColumnContext): DataGridColumn<Record<string, unknown>>[] {
|
||||
return [
|
||||
{
|
||||
id: "number",
|
||||
@@ -1770,6 +1774,7 @@ function recipientProfileColumns({ settings, campaignId, draft, locked, filesMod
|
||||
filterable: true,
|
||||
render: (entry, index) => {
|
||||
const summary = recipientAddressSummary(entry, translateText);
|
||||
const hiddenMatch = hiddenRecipientAddressMatch(entry, addressFilter);
|
||||
const content = (
|
||||
<>
|
||||
<span className="recipient-address-editor-main">
|
||||
@@ -1777,6 +1782,11 @@ function recipientProfileColumns({ settings, campaignId, draft, locked, filesMod
|
||||
{summary.badges.map((badge) =>
|
||||
<span className="recipient-extra-bubble" key={badge}>{badge}</span>
|
||||
)}
|
||||
{hiddenMatch &&
|
||||
<span className="recipient-hidden-address-match">
|
||||
Matched in {hiddenMatch.label}: {hiddenMatch.address}
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
{!locked && <Pencil aria-hidden="true" />}
|
||||
</>
|
||||
@@ -1936,6 +1946,32 @@ function recipientAddressFilterValue(entry: Record<string, unknown>): string {
|
||||
join(", ");
|
||||
}
|
||||
|
||||
function hiddenRecipientAddressMatch(
|
||||
entry: Record<string, unknown>,
|
||||
filterValue: string
|
||||
): {label: string;address: string;} | null {
|
||||
const query = filterValue.trim().toLowerCase();
|
||||
if (!query) return null;
|
||||
|
||||
const primary = getEntryAddresses(entry, "to")[0];
|
||||
if (primary && formatMailboxAddress(primary).toLowerCase().includes(query)) return null;
|
||||
|
||||
const labels: Record<AddressFieldKey, string> = {
|
||||
from: "From",
|
||||
reply_to: "Reply-To",
|
||||
to: "To",
|
||||
cc: "CC",
|
||||
bcc: "BCC"
|
||||
};
|
||||
for (const column of recipientAddressOverlayColumns) {
|
||||
const addresses = getEntryAddresses(entry, column.key);
|
||||
const hiddenAddresses = column.key === "to" ? addresses.slice(1) : addresses;
|
||||
const match = hiddenAddresses.find((address) => formatMailboxAddress(address).toLowerCase().includes(query));
|
||||
if (match) return { label: labels[column.key], address: formatMailboxAddress(match) };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function addressCountBadge(count: number, label: string): string | null {
|
||||
if (count <= 0) return null;
|
||||
return `+${count} ${label}`;
|
||||
|
||||
Reference in New Issue
Block a user