@aglyn/plugins-crm 1.0.0-beta.177 → 1.0.0-beta.179

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +13 -13
  2. package/src/lib/components/contact-detail-page.js +1 -0
  3. package/src/lib/components/contact-detail-page.js.map +1 -1
  4. package/src/lib/components/contact-properties-card.d.ts +6 -0
  5. package/src/lib/components/contact-properties-card.js +25 -2
  6. package/src/lib/components/contact-properties-card.js.map +1 -1
  7. package/src/lib/components/csv-import-drawer.d.ts +7 -0
  8. package/src/lib/components/csv-import-drawer.js +7 -0
  9. package/src/lib/components/csv-import-drawer.js.map +1 -1
  10. package/src/lib/components/fields-section.js +6 -0
  11. package/src/lib/components/fields-section.js.map +1 -1
  12. package/src/lib/components/lead-import-drawer.d.ts +3 -0
  13. package/src/lib/components/lead-import-drawer.js +29 -6
  14. package/src/lib/components/lead-import-drawer.js.map +1 -1
  15. package/src/lib/components/lead-properties-card.js +10 -12
  16. package/src/lib/components/lead-properties-card.js.map +1 -1
  17. package/src/lib/components/lead-source-select.d.ts +30 -0
  18. package/src/lib/components/lead-source-select.js +96 -0
  19. package/src/lib/components/lead-source-select.js.map +1 -0
  20. package/src/lib/components/lead-source-values-card.d.ts +27 -0
  21. package/src/lib/components/lead-source-values-card.js +606 -0
  22. package/src/lib/components/lead-source-values-card.js.map +1 -0
  23. package/src/lib/components/leads-section.js +100 -4
  24. package/src/lib/components/leads-section.js.map +1 -1
  25. package/src/lib/components/new-lead-drawer.js +27 -11
  26. package/src/lib/components/new-lead-drawer.js.map +1 -1
  27. package/src/lib/hooks/use-lead-source-picklist.d.ts +23 -0
  28. package/src/lib/hooks/use-lead-source-picklist.js +50 -0
  29. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -0
  30. package/src/lib/model/contact-record.d.ts +2 -0
  31. package/src/lib/model/contact-record.js +2 -1
  32. package/src/lib/model/contact-record.js.map +1 -1
  33. package/src/lib/model/contact-update.d.ts +6 -0
  34. package/src/lib/model/contact-update.js +1 -0
  35. package/src/lib/model/contact-update.js.map +1 -1
  36. package/src/lib/model/crm-lead-import.d.ts +10 -2
  37. package/src/lib/model/crm-lead-import.js +19 -1
  38. package/src/lib/model/crm-lead-import.js.map +1 -1
  39. package/src/lib/model/lead-filters.d.ts +13 -0
  40. package/src/lib/model/lead-filters.js +17 -1
  41. package/src/lib/model/lead-filters.js.map +1 -1
  42. package/src/lib/model/lead-source-values.d.ts +82 -0
  43. package/src/lib/model/lead-source-values.js +149 -0
  44. package/src/lib/model/lead-source-values.js.map +1 -0
  45. package/src/lib/server/contact-update.js +25 -2
  46. package/src/lib/server/contact-update.js.map +1 -1
  47. package/src/lib/server/lead-create.js +19 -0
  48. package/src/lib/server/lead-create.js.map +1 -1
  49. package/src/lib/server/lead-source-picklist.d.ts +42 -0
  50. package/src/lib/server/lead-source-picklist.js +52 -0
  51. package/src/lib/server/lead-source-picklist.js.map +1 -0
  52. package/src/lib/server/lead-source-values.d.ts +50 -0
  53. package/src/lib/server/lead-source-values.js +187 -0
  54. package/src/lib/server/lead-source-values.js.map +1 -0
  55. package/src/lib/server/leads-import.js +31 -2
  56. package/src/lib/server/leads-import.js.map +1 -1
  57. package/src/lib/server.js +5 -0
  58. package/src/lib/server.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-source-values-card.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n CRM_COLLECTIONS,\n CRM_LEAD_SOURCE_PICKLIST,\n CRM_LEAD_TEXT_MAX,\n type CrmPicklist,\n type CrmPicklistValue,\n crmPicklistActiveValues,\n newResourceScopeFields,\n ORG_SCOPE_TOKEN,\n} from '@aglyn/aglyn'\nimport {\n mdiArrowDown,\n mdiArrowUp,\n mdiDeleteOutline,\n mdiDragVertical,\n mdiEyeOffOutline,\n mdiEyeOutline,\n mdiPencilOutline,\n mdiStarOutline,\n} from '@aglyn/shared-data-mdi'\nimport { MdiIcon, SrOnly } from '@aglyn/shared-ui-jsx'\nimport RowActionsMenu, {\n type RowActionsMenuItem,\n} from '@aglyn/shared-ui-jsx/components/row-actions-menu.component'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n useFirestore,\n useUser,\n writeGuardedBySeed,\n} from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n IconButton,\n MenuItem,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport { doc, serverTimestamp, setDoc } from 'firebase/firestore'\nimport { useCallback, useState } from 'react'\nimport { useLeadSourcePicklist } from '../hooks/use-lead-source-picklist'\nimport {\n addPicklistValue,\n crmLeadSourceValuesRouteUrl,\n type LeadSourceValuesRequest,\n type LeadSourceValuesResponse,\n movePicklistValue,\n setPicklistDefault,\n setPicklistValueActive,\n sortPicklistValues,\n} from '../model/lead-source-values'\nimport { crmTaskCallScope } from '../model/task-routes'\n\nexport interface LeadSourceValuesCardProps {\n /** The mounted site, or `null` at the organization level. */\n hostId: string | null\n /** The org whose list this is; `null` while it settles. */\n orgId: string | null\n /** The site a newly written list records as its definer — the Fields page's own. */\n createHostId: string | null\n}\n\n/** The add and rename dialog's state: which value, if any, is being renamed. */\ntype NameDialog = { mode: 'add' } | { mode: 'rename'; value: CrmPicklistValue } | null\n\n/**\n * THE LEAD SOURCE VALUES (AGL-3298) — Salesforce's Lead Source picklist,\n * managed where the org's lead fields are.\n *\n * Every move that touches only the LIST — add, reorder by drag or arrows,\n * sort A–Z, activate, deactivate, default — is one client write of the\n * whole document, guarded against a cached read like every seeded save on\n * the Fields page. The two that change RECORDS — rename, and delete with a\n * replacement — go to `crm/lead-source-values`, which rewrites the list and\n * every lead and contact holding the old label together; see that route.\n *\n * An org that has never edited its list reads the starter set, and the\n * first move here writes it down as the org's own.\n */\nexport function LeadSourceValuesCard(props: LeadSourceValuesCardProps) {\n const { hostId, orgId, createHostId } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const { picklist, stored, ready, fromCache } = useLeadSourcePicklist(orgId)\n const [busy, setBusy] = useState(false)\n const [nameDialog, setNameDialog] = useState<NameDialog>(null)\n const [draftName, setDraftName] = useState('')\n const [nameError, setNameError] = useState('')\n const [deleting, setDeleting] = useState<CrmPicklistValue | null>(null)\n const [replaceWith, setReplaceWith] = useState('')\n const [dragFrom, setDragFrom] = useState<number | null>(null)\n\n /** Write the whole list — the list-only moves above. */\n const save = useCallback(\n async (next: CrmPicklist, done: string) => {\n if (!orgId || busy) return\n setBusy(true)\n try {\n const verdict = await writeGuardedBySeed({ subject: 'lead source list', fromCache }, () =>\n setDoc(\n doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.picklists, CRM_LEAD_SOURCE_PICKLIST),\n {\n values: next.values,\n defaultValueId: next.defaultValueId,\n updatedAt: serverTimestamp(),\n // The org-wide stamp the rules require of a new CRM document,\n // the same one a field definition carries.\n ...(stored\n ? {}\n : {\n hostId: createHostId,\n createdAt: serverTimestamp(),\n ...newResourceScopeFields([ORG_SCOPE_TOKEN]),\n }),\n },\n { merge: true },\n ),\n )\n if (!verdict.ok) {\n enqueueSnackbar(verdict.message, { variant: 'warning', persist: false })\n return\n }\n enqueueSnackbar(done, { variant: 'success', persist: false })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('The lead sources could not be saved.', { variant: 'error', allowDuplicate: true })\n } finally {\n setBusy(false)\n }\n },\n [orgId, busy, fromCache, firestore, stored, createHostId, enqueueSnackbar],\n )\n\n /** A rename or a delete — the moves that change records too. */\n const post = useCallback(\n async (request: LeadSourceValuesRequest): Promise<LeadSourceValuesResponse | null> => {\n const scope = crmTaskCallScope(hostId, orgId)\n if (!scope || busy) return null\n setBusy(true)\n try {\n const response = await authorizedFetch(user, crmLeadSourceValuesRouteUrl(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...request, ...scope }),\n })\n const payload = (await response.json().catch(() => ({}))) as { error?: string }\n if (!response.ok) {\n enqueueSnackbar(payload.error || 'The lead sources could not be saved.', {\n variant: 'warning',\n persist: false,\n })\n return null\n }\n return payload as LeadSourceValuesResponse\n } catch (error) {\n console.error(error)\n enqueueSnackbar('The lead sources could not be saved.', { variant: 'error', allowDuplicate: true })\n return null\n } finally {\n setBusy(false)\n }\n },\n [hostId, orgId, busy, user, enqueueSnackbar],\n )\n\n const moved = (result: LeadSourceValuesResponse) => {\n const records = result.leads + result.contacts\n return records\n ? ` — ${result.leads.toLocaleString()} lead${result.leads === 1 ? '' : 's'} and ` +\n `${result.contacts.toLocaleString()} contact${result.contacts === 1 ? '' : 's'} updated`\n : ''\n }\n\n const openAdd = () => {\n setDraftName('')\n setNameError('')\n setNameDialog({ mode: 'add' })\n }\n const openRename = (value: CrmPicklistValue) => {\n setDraftName(value.label)\n setNameError('')\n setNameDialog({ mode: 'rename', value })\n }\n\n const submitName = async () => {\n if (!nameDialog) return\n if (nameDialog.mode === 'add') {\n const move = addPicklistValue(picklist, draftName)\n if (move.ok === false) return void setNameError(move.error)\n setNameDialog(null)\n await save(move.picklist, `“${draftName.trim()}” added`)\n return\n }\n const result = await post({ action: 'rename', valueId: nameDialog.value.id, label: draftName })\n if (!result) return\n setNameDialog(null)\n enqueueSnackbar(`Renamed${moved(result)}`, { variant: 'success', persist: false })\n }\n\n const openDelete = (value: CrmPicklistValue) => {\n setReplaceWith('')\n setDeleting(value)\n }\n const submitDelete = async () => {\n if (!deleting) return\n const result = await post({\n action: 'delete',\n valueId: deleting.id,\n replaceWith: replaceWith || null,\n })\n if (!result) return\n setDeleting(null)\n enqueueSnackbar(`“${deleting.label}” deleted${moved(result)}`, {\n variant: 'success',\n persist: false,\n })\n }\n\n const move = (from: number, to: number) =>\n void save(movePicklistValue(picklist, from, to), 'Order saved')\n\n const rowActions = (value: CrmPicklistValue): RowActionsMenuItem[] => {\n const isDefault = picklist.defaultValueId === value.id\n return [\n {\n key: 'rename',\n label: 'Rename',\n icon: <MdiIcon path={mdiPencilOutline.path} size={0.8} />,\n disabled: busy,\n onClick: () => openRename(value),\n },\n {\n key: 'default',\n label: isDefault ? 'Clear default' : 'Make default',\n icon: <MdiIcon path={mdiStarOutline.path} size={0.8} />,\n disabled: busy || (!isDefault && !value.active),\n disabledReason: !value.active ? 'An inactive value cannot be the default' : undefined,\n onClick: () =>\n void save(\n setPicklistDefault(picklist, isDefault ? null : value.id),\n isDefault ? 'Default cleared' : `New leads start as “${value.label}”`,\n ),\n },\n {\n key: 'active',\n label: value.active ? 'Deactivate' : 'Activate',\n icon: (\n <MdiIcon path={value.active ? mdiEyeOffOutline.path : mdiEyeOutline.path} size={0.8} />\n ),\n disabled: busy,\n onClick: () =>\n void save(\n setPicklistValueActive(picklist, value.id, !value.active),\n value.active ? `“${value.label}” deactivated` : `“${value.label}” activated`,\n ),\n },\n {\n key: 'delete',\n label: 'Delete…',\n icon: <MdiIcon path={mdiDeleteOutline.path} size={0.8} />,\n destructive: true,\n disabled: busy,\n onClick: () => openDelete(value),\n },\n ]\n }\n\n const replacements = crmPicklistActiveValues(picklist).filter(\n (value) => value.id !== deleting?.id,\n )\n\n return (\n <Stack spacing={1.5}>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ justifyContent: 'space-between', alignItems: { sm: 'center' } }}\n >\n <Stack spacing={0.25}>\n <Typography variant=\"subtitle1\">{'Lead source values'}</Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'The choices in every lead’s Lead source select, in this order. ' +\n 'An import or an API write naming anything else is refused. ' +\n 'A deactivated value stays on the records that hold it.'}\n </Typography>\n </Stack>\n {orgId ? (\n <Stack direction=\"row\" spacing={1} sx={{ flexShrink: 0 }}>\n <Button\n size=\"small\"\n disabled={busy || picklist.values.length < 2}\n onClick={() => void save(sortPicklistValues(picklist), 'Sorted A–Z')}\n >\n {'Sort A–Z'}\n </Button>\n <Button size=\"small\" variant=\"outlined\" disabled={busy} onClick={openAdd}>\n {'Add value'}\n </Button>\n </Stack>\n ) : null}\n </Stack>\n {!ready ? null : (\n <ScrollTable size=\"small\" aria-label=\"Lead source values\">\n <TableHead>\n <TableRow>\n <TableCell sx={{ width: 120 }}>{'Order'}</TableCell>\n <TableCell>{'Value'}</TableCell>\n <TableCell>{'Status'}</TableCell>\n <TableCell align=\"right\" />\n </TableRow>\n </TableHead>\n <TableBody>\n {picklist.values.length === 0 ? (\n <TableRow>\n <TableCell colSpan={4}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No values yet. Add one, and every lead can be given it.'}\n </Typography>\n </TableCell>\n </TableRow>\n ) : null}\n {picklist.values.map((value, index) => (\n <TableRow\n key={value.id}\n hover\n // Native drag and drop for a pointer; the arrows beside the\n // handle are the same move for a keyboard or a touch screen.\n draggable={!busy}\n onDragStart={(event) => {\n setDragFrom(index)\n event.dataTransfer.effectAllowed = 'move'\n }}\n onDragOver={(event) => {\n if (dragFrom === null) return\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n }}\n onDrop={(event) => {\n event.preventDefault()\n if (dragFrom !== null && dragFrom !== index) move(dragFrom, index)\n setDragFrom(null)\n }}\n onDragEnd={() => setDragFrom(null)}\n sx={{\n ...(value.active ? {} : { opacity: 0.6 }),\n ...(dragFrom === index ? { outline: 1, outlineColor: 'primary.main' } : {}),\n }}\n >\n <TableCell>\n <Stack direction=\"row\" spacing={0} sx={{ alignItems: 'center' }}>\n <MdiIcon\n path={mdiDragVertical.path}\n size={0.8}\n style={{ cursor: busy ? 'default' : 'grab' }}\n aria-hidden\n />\n <IconButton\n size=\"small\"\n disabled={index === 0 || busy}\n onClick={() => move(index, index - 1)}\n >\n <MdiIcon path={mdiArrowUp.path} size={0.7} />\n <SrOnly>{`Move ${value.label} up`}</SrOnly>\n </IconButton>\n <IconButton\n size=\"small\"\n disabled={index === picklist.values.length - 1 || busy}\n onClick={() => move(index, index + 1)}\n >\n <MdiIcon path={mdiArrowDown.path} size={0.7} />\n <SrOnly>{`Move ${value.label} down`}</SrOnly>\n </IconButton>\n </Stack>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\">{value.label}</Typography>\n </TableCell>\n <TableCell>\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap', alignItems: 'center' }}>\n {value.active ? null : (\n <Chip size=\"small\" variant=\"outlined\" color=\"warning\" label=\"Inactive\" />\n )}\n {picklist.defaultValueId === value.id ? (\n <Chip size=\"small\" variant=\"outlined\" color=\"primary\" label=\"Default\" />\n ) : null}\n {value.active && picklist.defaultValueId !== value.id ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Active'}\n </Typography>\n ) : null}\n </Stack>\n </TableCell>\n <TableCell align=\"right\" sx={{ width: 56 }}>\n <RowActionsMenu label={value.label} items={rowActions(value)} />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </ScrollTable>\n )}\n {ready && !stored ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'This is the starter list. Your first change here makes it your organization’s own.'}\n </Typography>\n ) : null}\n\n <Dialog open={nameDialog !== null} onClose={() => setNameDialog(null)} fullWidth maxWidth=\"xs\">\n <DialogTitle>\n {nameDialog?.mode === 'rename' ? `Rename “${nameDialog.value.label}”` : 'Add a lead source'}\n </DialogTitle>\n <DialogContent>\n <Stack spacing={1.5} sx={{ pt: 1 }}>\n {nameDialog?.mode === 'rename' ? (\n <DialogContentText variant=\"body2\">\n {'Every lead and contact holding this value is updated to the new name.'}\n </DialogContentText>\n ) : null}\n <TextField\n size=\"small\"\n label=\"Value\"\n value={draftName}\n onChange={(event) => {\n setDraftName(event.target.value)\n setNameError('')\n }}\n onKeyDown={(event) => {\n if (event.key === 'Enter') void submitName()\n }}\n error={Boolean(nameError)}\n helperText={nameError || ' '}\n slotProps={{ htmlInput: { maxLength: CRM_LEAD_TEXT_MAX } }}\n autoFocus\n fullWidth\n />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setNameDialog(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n disabled={busy || !draftName.trim()}\n onClick={() => void submitName()}\n >\n {nameDialog?.mode === 'rename' ? 'Rename' : 'Add'}\n </Button>\n </DialogActions>\n </Dialog>\n\n <Dialog open={deleting !== null} onClose={() => setDeleting(null)} fullWidth maxWidth=\"xs\">\n <DialogTitle>{`Delete “${deleting?.label ?? ''}”?`}</DialogTitle>\n <DialogContent>\n <Stack spacing={1.5} sx={{ pt: 1 }}>\n <DialogContentText variant=\"body2\">\n {'The value leaves the list for good. Leads and contacts that hold it ' +\n 'are moved to the value you pick here, or cleared. To keep it on ' +\n 'those records instead, deactivate it.'}\n </DialogContentText>\n <TextField\n select\n size=\"small\"\n label=\"Replace it on existing records with\"\n value={replaceWith}\n onChange={(event) => setReplaceWith(String(event.target.value))}\n fullWidth\n slotProps={{ select: { displayEmpty: true }, inputLabel: { shrink: true } }}\n >\n <MenuItem value=\"\">{'None — clear it'}</MenuItem>\n {replacements.map((value) => (\n <MenuItem key={value.id} value={value.label}>\n {value.label}\n </MenuItem>\n ))}\n </TextField>\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDeleting(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n color=\"error\"\n disabled={busy}\n onClick={() => void submitDelete()}\n >\n {'Delete value'}\n </Button>\n </DialogActions>\n </Dialog>\n </Stack>\n )\n}\nLeadSourceValuesCard.displayName = 'LeadSourceValuesCard'\n\nexport default LeadSourceValuesCard\n"],"names":["CRM_COLLECTIONS","CRM_LEAD_SOURCE_PICKLIST","CRM_LEAD_TEXT_MAX","crmPicklistActiveValues","newResourceScopeFields","ORG_SCOPE_TOKEN","mdiArrowDown","mdiArrowUp","mdiDeleteOutline","mdiDragVertical","mdiEyeOffOutline","mdiEyeOutline","mdiPencilOutline","mdiStarOutline","MdiIcon","SrOnly","RowActionsMenu","ScrollTable","useSnackbar","authorizedFetch","useFirestore","useUser","writeGuardedBySeed","Button","Chip","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","IconButton","MenuItem","Stack","TableBody","TableCell","TableHead","TableRow","TextField","Typography","doc","serverTimestamp","setDoc","useCallback","useState","useLeadSourcePicklist","addPicklistValue","crmLeadSourceValuesRouteUrl","movePicklistValue","setPicklistDefault","setPicklistValueActive","sortPicklistValues","crmTaskCallScope","LeadSourceValuesCard","props","hostId","orgId","createHostId","firestore","data","user","enqueueSnackbar","picklist","stored","ready","fromCache","busy","setBusy","nameDialog","setNameDialog","draftName","setDraftName","nameError","setNameError","deleting","setDeleting","replaceWith","setReplaceWith","dragFrom","setDragFrom","save","next","done","verdict","subject","picklists","values","defaultValueId","updatedAt","createdAt","merge","ok","message","variant","persist","error","console","allowDuplicate","post","request","scope","response","method","headers","body","JSON","stringify","payload","json","catch","moved","result","records","leads","contacts","toLocaleString","openAdd","mode","openRename","value","label","submitName","move","trim","action","valueId","id","openDelete","submitDelete","from","to","rowActions","isDefault","key","icon","path","size","disabled","onClick","active","disabledReason","undefined","destructive","replacements","filter","spacing","direction","xs","sm","sx","justifyContent","alignItems","color","flexShrink","length","aria-label","width","align","colSpan","map","index","hover","draggable","onDragStart","event","dataTransfer","effectAllowed","onDragOver","preventDefault","dropEffect","onDrop","onDragEnd","opacity","outline","outlineColor","style","cursor","aria-hidden","flexWrap","items","open","onClose","fullWidth","maxWidth","pt","onChange","target","onKeyDown","Boolean","helperText","slotProps","htmlInput","maxLength","autoFocus","select","String","displayEmpty","inputLabel","shrink","displayName"],"mappings":"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"}
@@ -44,7 +44,8 @@ import { useRouter } from "next/navigation";
44
44
  import { useCallback, useEffect, useId, useMemo, useState } from "react";
45
45
  import { downloadTextFile } from "../model/contacts-csv.js";
46
46
  import { crmRoutes } from "../model/crm-routes.js";
47
- import { LEAD_FILTER_LABELS, LEAD_EMAIL_FILTER_LABELS, LEAD_EMAIL_FILTERS, LEAD_FILTERS, leadMatchesCampaignFilter, leadMatchesEmailFilter, leadMatchesFilter, leadMatchesSearch } from "../model/lead-filters.js";
47
+ import { LEAD_FILTER_LABELS, LEAD_EMAIL_FILTER_LABELS, LEAD_EMAIL_FILTERS, LEAD_FILTERS, leadMatchesCampaignFilter, leadMatchesEmailFilter, leadMatchesFilter, leadMatchesLeadSourceFilter, leadMatchesSearch, LEAD_SOURCE_FILTER_NONE } from "../model/lead-filters.js";
48
+ import { useLeadSourcePicklist } from "../hooks/use-lead-source-picklist.js";
48
49
  import { leadsCsv } from "../model/leads-csv.js";
49
50
  import { LeadConvertDialog } from "./lead-convert-dialog.js";
50
51
  import { leadSourceLabel, leadSources, leadTimeLabel } from "./lead-history-card.js";
@@ -111,6 +112,9 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
111
112
  const roster = useOrgMemberOptions(orgId);
112
113
  // The org's lead fields, for the optional columns below (AGL-3272).
113
114
  const leadFields = useContactFieldDefinitions(orgId, 'lead');
115
+ // The org's lead source values (AGL-3298): the filter's menu and the
116
+ // column's sort order.
117
+ const leadSourceList = useLeadSourcePicklist(orgId);
114
118
  const routes = crmRoutes(basePath != null ? basePath : '');
115
119
  /*
116
120
  * Under a site: the ORG collection, narrowed to what this site may see
@@ -235,6 +239,37 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
235
239
  views.setFilters,
236
240
  views.state.filters
237
241
  ]);
242
+ /*
243
+ * The `Lead source` filter (AGL-3298) is the view's too: an `equals`
244
+ * clause naming the label records store, or an `isEmpty` one for the
245
+ * leads that hold none.
246
+ */ const leadSourceFilter = useMemo(()=>{
247
+ var _clause_value;
248
+ const clause = views.state.filters.find((entry)=>entry.field === 'leadSource');
249
+ if (!clause) return '';
250
+ return clause.op === 'isEmpty' ? LEAD_SOURCE_FILTER_NONE : String((_clause_value = clause.value) != null ? _clause_value : '');
251
+ }, [
252
+ views.state.filters
253
+ ]);
254
+ const setLeadSourceFilter = useCallback((next)=>views.setFilters([
255
+ ...views.state.filters.filter((clause)=>clause.field !== 'leadSource'),
256
+ ...next === LEAD_SOURCE_FILTER_NONE ? [
257
+ {
258
+ field: 'leadSource',
259
+ op: 'isEmpty',
260
+ value: ''
261
+ }
262
+ ] : next ? [
263
+ {
264
+ field: 'leadSource',
265
+ op: 'equals',
266
+ value: next
267
+ }
268
+ ] : []
269
+ ]), [
270
+ views.setFilters,
271
+ views.state.filters
272
+ ]);
238
273
  const campaigns = useCrmCampaigns({
239
274
  hostId,
240
275
  orgId
@@ -253,6 +288,7 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
253
288
  const filterLabelId = useId();
254
289
  const emailFilterLabelId = useId();
255
290
  const campaignFilterLabelId = useId();
291
+ const leadSourceFilterLabelId = useId();
256
292
  /*
257
293
  * The search box is the SECTION'S, not the grid's (AGL-3246). The grid's
258
294
  * quick filter runs over the rows the grid holds, and the grid holds one
@@ -262,11 +298,12 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
262
298
  * before the footer's count and the page slice, over the fields a person
263
299
  * types to find a lead: name, email, company, title and tags.
264
300
  */ const [search, setSearch] = useState('');
265
- const rows = useMemo(()=>window.filter((lead)=>leadMatchesFilter(lead, filter) && leadMatchesEmailFilter(lead, emailFilter) && leadMatchesCampaignFilter(lead, campaignFilter) && leadMatchesSearch(lead, search)), [
301
+ const rows = useMemo(()=>window.filter((lead)=>leadMatchesFilter(lead, filter) && leadMatchesEmailFilter(lead, emailFilter) && leadMatchesCampaignFilter(lead, campaignFilter) && leadMatchesLeadSourceFilter(lead, leadSourceFilter) && leadMatchesSearch(lead, search)), [
266
302
  window,
267
303
  filter,
268
304
  emailFilter,
269
305
  campaignFilter,
306
+ leadSourceFilter,
270
307
  search
271
308
  ]);
272
309
  const [page, setPage] = useState(0);
@@ -280,6 +317,7 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
280
317
  filter,
281
318
  emailFilter,
282
319
  campaignFilter,
320
+ leadSourceFilter,
283
321
  search
284
322
  ]);
285
323
  const pageRows = useMemo(()=>rows.slice(page * pageSize, (page + 1) * pageSize), [
@@ -297,6 +335,7 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
297
335
  filter,
298
336
  emailFilter,
299
337
  campaignFilter,
338
+ leadSourceFilter,
300
339
  search
301
340
  ]);
302
341
  // How the file names the owner and, at the org level, the site.
@@ -547,6 +586,22 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
547
586
  minWidth: 140,
548
587
  valueGetter: (_value, row)=>leadSources(row).map(leadSourceLabel).join(', ')
549
588
  },
589
+ /*
590
+ * Salesforce's Lead Source (AGL-3298), beside the surfaces that
591
+ * captured the person. Sorted in the order the org keeps its values,
592
+ * as a picklist sorts, with a value the list does not hold after
593
+ * every listed one and a lead with none last.
594
+ */ {
595
+ field: 'leadSource',
596
+ headerName: 'Lead source',
597
+ flex: 1,
598
+ minWidth: 150,
599
+ valueGetter: (_value, row)=>{
600
+ var _row_leadSource;
601
+ return String((_row_leadSource = row.leadSource) != null ? _row_leadSource : '');
602
+ },
603
+ sortComparator: (a, b)=>Aglyn.crmPicklistRank(leadSourceList.picklist, a) - Aglyn.crmPicklistRank(leadSourceList.picklist, b) || String(a != null ? a : '').localeCompare(String(b != null ? b : ''))
604
+ },
550
605
  {
551
606
  field: 'tags',
552
607
  headerName: 'Tags',
@@ -660,7 +715,8 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
660
715
  hostId,
661
716
  mount,
662
717
  campaignName,
663
- leadFields.active
718
+ leadFields.active,
719
+ leadSourceList.picklist
664
720
  ]);
665
721
  /* The column and sort models are the view's (AGL-2617). */ const grid = useCrmViewGrid(views, columns);
666
722
  return /*#__PURE__*/ _jsxs(_Fragment, {
@@ -760,6 +816,45 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
760
816
  })
761
817
  ]
762
818
  }),
819
+ /*#__PURE__*/ _jsxs(FormControl, {
820
+ size: "small",
821
+ sx: {
822
+ minWidth: 180
823
+ },
824
+ children: [
825
+ /*#__PURE__*/ _jsx(InputLabel, {
826
+ id: leadSourceFilterLabelId,
827
+ shrink: true,
828
+ children: 'Lead source'
829
+ }),
830
+ /*#__PURE__*/ _jsxs(Select, {
831
+ labelId: leadSourceFilterLabelId,
832
+ label: "Lead source",
833
+ notched: true,
834
+ value: leadSourceFilter,
835
+ onChange: (event)=>setLeadSourceFilter(String(event.target.value)),
836
+ displayEmpty: true,
837
+ children: [
838
+ /*#__PURE__*/ _jsx(MenuItem, {
839
+ value: "",
840
+ children: 'Any lead source'
841
+ }),
842
+ leadSourceList.picklist.values.map((value)=>/*#__PURE__*/ _jsx(MenuItem, {
843
+ value: value.label,
844
+ children: value.active ? value.label : `${value.label} (inactive)`
845
+ }, value.id)),
846
+ /*#__PURE__*/ _jsx(MenuItem, {
847
+ value: LEAD_SOURCE_FILTER_NONE,
848
+ children: 'No lead source'
849
+ }),
850
+ leadSourceFilter && leadSourceFilter !== LEAD_SOURCE_FILTER_NONE && !Aglyn.crmPicklistValueByLabel(leadSourceList.picklist, leadSourceFilter) ? /*#__PURE__*/ _jsx(MenuItem, {
851
+ value: leadSourceFilter,
852
+ children: leadSourceFilter
853
+ }) : null
854
+ ]
855
+ })
856
+ ]
857
+ }),
763
858
  /*#__PURE__*/ _jsx(TextField, {
764
859
  size: "small",
765
860
  value: search,
@@ -785,7 +880,8 @@ import OrgLeadSurfacesNote from "./org-lead-surfaces-note.js";
785
880
  }
786
881
  }),
787
882
  /*#__PURE__*/ _jsx(LeadImportButton, {
788
- hostId: hostId
883
+ hostId: hostId,
884
+ orgId: orgId
789
885
  }),
790
886
  /*#__PURE__*/ _jsx(Button, {
791
887
  size: "small",