@agent-native/core 0.123.0 → 0.123.1
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.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +16 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/templates-meta.ts +12 -0
- package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +177 -0
- package/corpus/templates/crm/.agents/skills/crm/SKILL.md +205 -0
- package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +220 -0
- package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +228 -0
- package/corpus/templates/crm/.agents/skills/storing-data/SKILL.md +178 -0
- package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +122 -0
- package/corpus/templates/crm/.env.example +5 -0
- package/corpus/templates/crm/AGENTS.md +82 -0
- package/corpus/templates/crm/CHANGELOG.md +25 -0
- package/corpus/templates/crm/DEVELOPING.md +66 -0
- package/corpus/templates/crm/README.md +122 -0
- package/corpus/templates/crm/_gitignore +12 -0
- package/corpus/templates/crm/actions/_crm-action-utils.ts +98 -0
- package/corpus/templates/crm/actions/_crm-attribute-utils.ts +219 -0
- package/corpus/templates/crm/actions/_crm-dashboard.ts +69 -0
- package/corpus/templates/crm/actions/_crm-data-program-actions.ts +15 -0
- package/corpus/templates/crm/actions/_crm-list-utils.ts +775 -0
- package/corpus/templates/crm/actions/_crm-signal-utils.ts +79 -0
- package/corpus/templates/crm/actions/add-crm-record-to-list.ts +164 -0
- package/corpus/templates/crm/actions/apply-crm-proposals.ts +291 -0
- package/corpus/templates/crm/actions/archive-crm-attribute.ts +69 -0
- package/corpus/templates/crm/actions/attach-call-evidence.ts +170 -0
- package/corpus/templates/crm/actions/configure-crm-connection.ts +126 -0
- package/corpus/templates/crm/actions/configure-native-crm.ts +44 -0
- package/corpus/templates/crm/actions/create-crm-attribute.ts +350 -0
- package/corpus/templates/crm/actions/create-crm-list.ts +194 -0
- package/corpus/templates/crm/actions/create-crm-record.ts +148 -0
- package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +58 -0
- package/corpus/templates/crm/actions/delete-crm-saved-view.ts +68 -0
- package/corpus/templates/crm/actions/delete-staged-dataset.ts +14 -0
- package/corpus/templates/crm/actions/estimate-crm-enrichment.ts +229 -0
- package/corpus/templates/crm/actions/find-crm-duplicates.ts +87 -0
- package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +36 -0
- package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +35 -0
- package/corpus/templates/crm/actions/get-crm-dashboard.ts +14 -0
- package/corpus/templates/crm/actions/get-crm-overview.ts +13 -0
- package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +61 -0
- package/corpus/templates/crm/actions/get-crm-record-page.ts +287 -0
- package/corpus/templates/crm/actions/get-crm-record.ts +75 -0
- package/corpus/templates/crm/actions/get-crm-workspace.ts +364 -0
- package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +81 -0
- package/corpus/templates/crm/actions/list-crm-attributes.ts +71 -0
- package/corpus/templates/crm/actions/list-crm-connections.ts +68 -0
- package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-dashboards.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-enrichment-slots.ts +28 -0
- package/corpus/templates/crm/actions/list-crm-list-entries.ts +192 -0
- package/corpus/templates/crm/actions/list-crm-lists.ts +80 -0
- package/corpus/templates/crm/actions/list-crm-proposals.ts +55 -0
- package/corpus/templates/crm/actions/list-crm-record-field-history.ts +201 -0
- package/corpus/templates/crm/actions/list-crm-record-values.ts +200 -0
- package/corpus/templates/crm/actions/list-crm-records.ts +103 -0
- package/corpus/templates/crm/actions/list-crm-saved-views.ts +66 -0
- package/corpus/templates/crm/actions/list-crm-signal-hits.ts +43 -0
- package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +32 -0
- package/corpus/templates/crm/actions/list-crm-tasks.ts +22 -0
- package/corpus/templates/crm/actions/list-staged-datasets.ts +14 -0
- package/corpus/templates/crm/actions/list-workspace-connections.ts +47 -0
- package/corpus/templates/crm/actions/manage-crm-attribute-option.ts +272 -0
- package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +87 -0
- package/corpus/templates/crm/actions/manage-crm-task.ts +132 -0
- package/corpus/templates/crm/actions/merge-crm-records.ts +691 -0
- package/corpus/templates/crm/actions/navigate.ts +54 -0
- package/corpus/templates/crm/actions/provider-api-catalog.ts +22 -0
- package/corpus/templates/crm/actions/provider-api-docs.ts +54 -0
- package/corpus/templates/crm/actions/provider-api-request.ts +92 -0
- package/corpus/templates/crm/actions/query-staged-dataset.ts +44 -0
- package/corpus/templates/crm/actions/record-crm-call-insight.ts +160 -0
- package/corpus/templates/crm/actions/record-crm-smart-signal.ts +150 -0
- package/corpus/templates/crm/actions/remove-crm-list-entry.ts +79 -0
- package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +23 -0
- package/corpus/templates/crm/actions/review-crm-signal.ts +31 -0
- package/corpus/templates/crm/actions/run-crm-attribute-fill.ts +443 -0
- package/corpus/templates/crm/actions/run-crm-enrichment.ts +647 -0
- package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +103 -0
- package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +265 -0
- package/corpus/templates/crm/actions/run.ts +7 -0
- package/corpus/templates/crm/actions/save-crm-dashboard.ts +51 -0
- package/corpus/templates/crm/actions/save-crm-saved-view.ts +296 -0
- package/corpus/templates/crm/actions/sync-crm.ts +146 -0
- package/corpus/templates/crm/actions/update-crm-attribute.ts +111 -0
- package/corpus/templates/crm/actions/update-crm-list-entry.ts +102 -0
- package/corpus/templates/crm/actions/update-crm-list.ts +97 -0
- package/corpus/templates/crm/actions/update-crm-record.ts +543 -0
- package/corpus/templates/crm/actions/view-screen.ts +324 -0
- package/corpus/templates/crm/agent-native.app-skill.json +69 -0
- package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +158 -0
- package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +78 -0
- package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +220 -0
- package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +414 -0
- package/corpus/templates/crm/app/components/crm/RecordActions.tsx +648 -0
- package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +488 -0
- package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +232 -0
- package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +93 -0
- package/corpus/templates/crm/app/components/crm/Surface.tsx +97 -0
- package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +180 -0
- package/corpus/templates/crm/app/components/crm/board/CrmBoard.tsx +988 -0
- package/corpus/templates/crm/app/components/crm/board/board-model.ts +399 -0
- package/corpus/templates/crm/app/components/crm/board/entry-filter.ts +150 -0
- package/corpus/templates/crm/app/components/crm/board/view-draft.ts +227 -0
- package/corpus/templates/crm/app/components/crm/grid/CrmGrid.tsx +1033 -0
- package/corpus/templates/crm/app/components/crm/grid/GridCell.tsx +620 -0
- package/corpus/templates/crm/app/components/crm/grid/clipboard.ts +84 -0
- package/corpus/templates/crm/app/components/crm/grid/model.ts +304 -0
- package/corpus/templates/crm/app/components/crm/grid/navigation.ts +220 -0
- package/corpus/templates/crm/app/components/crm/grid/query.ts +214 -0
- package/corpus/templates/crm/app/components/crm/record/AttributePanel.tsx +192 -0
- package/corpus/templates/crm/app/components/crm/record/FieldHistory.tsx +179 -0
- package/corpus/templates/crm/app/components/crm/record/RecordHeader.tsx +103 -0
- package/corpus/templates/crm/app/components/crm/record/RecordLists.tsx +235 -0
- package/corpus/templates/crm/app/components/crm/record/RecordTabs.tsx +206 -0
- package/corpus/templates/crm/app/components/crm/record/field-editors.tsx +245 -0
- package/corpus/templates/crm/app/components/crm/record/record-data.ts +603 -0
- package/corpus/templates/crm/app/components/crm/settings/AdvancedSettings.tsx +49 -0
- package/corpus/templates/crm/app/components/crm/settings/AttributeOptionsEditor.tsx +441 -0
- package/corpus/templates/crm/app/components/crm/settings/ConnectionSettings.tsx +169 -0
- package/corpus/templates/crm/app/components/crm/settings/FieldsSettings.tsx +935 -0
- package/corpus/templates/crm/app/components/crm/settings/ListsSettings.tsx +339 -0
- package/corpus/templates/crm/app/components/crm/settings/settings-admin.ts +377 -0
- package/corpus/templates/crm/app/components/crm/shared/AttributeValueParts.tsx +69 -0
- package/corpus/templates/crm/app/components/crm/shared/attribute-value.ts +591 -0
- package/corpus/templates/crm/app/components/layout/CrmCommandMenu.tsx +556 -0
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +130 -0
- package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +407 -0
- package/corpus/templates/crm/app/components/layout/command-palette-search.ts +126 -0
- package/corpus/templates/crm/app/components/layout/crm-ui-intents.ts +41 -0
- package/corpus/templates/crm/app/components/layout/sidebar-collapse.ts +40 -0
- package/corpus/templates/crm/app/components/layout/sidebar-lists.ts +109 -0
- package/corpus/templates/crm/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/button.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/card.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/hover-card.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/input.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/label.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/select.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/table.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/crm/app/components/ui/toolkit-provider.tsx +17 -0
- package/corpus/templates/crm/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/crm/app/design-system.ts +3 -0
- package/corpus/templates/crm/app/entry.client.tsx +19 -0
- package/corpus/templates/crm/app/entry.server.tsx +10 -0
- package/corpus/templates/crm/app/global.css +167 -0
- package/corpus/templates/crm/app/hooks/use-keyboard-shortcuts.ts +206 -0
- package/corpus/templates/crm/app/hooks/use-navigation-state.ts +48 -0
- package/corpus/templates/crm/app/i18n/en-US.ts +684 -0
- package/corpus/templates/crm/app/i18n/index.ts +34 -0
- package/corpus/templates/crm/app/lib/dashboard.ts +13 -0
- package/corpus/templates/crm/app/lib/navigation.ts +17 -0
- package/corpus/templates/crm/app/lib/tab-id.ts +1 -0
- package/corpus/templates/crm/app/lib/types.ts +172 -0
- package/corpus/templates/crm/app/lib/utils.ts +1 -0
- package/corpus/templates/crm/app/root.tsx +93 -0
- package/corpus/templates/crm/app/routes/_index.tsx +26 -0
- package/corpus/templates/crm/app/routes/accounts.tsx +41 -0
- package/corpus/templates/crm/app/routes/agent.tsx +5 -0
- package/corpus/templates/crm/app/routes/ask.tsx +53 -0
- package/corpus/templates/crm/app/routes/dashboard.tsx +118 -0
- package/corpus/templates/crm/app/routes/lists.tsx +228 -0
- package/corpus/templates/crm/app/routes/opportunities.tsx +41 -0
- package/corpus/templates/crm/app/routes/people.tsx +41 -0
- package/corpus/templates/crm/app/routes/proposals.tsx +388 -0
- package/corpus/templates/crm/app/routes/records.$recordId.tsx +53 -0
- package/corpus/templates/crm/app/routes/records.tsx +64 -0
- package/corpus/templates/crm/app/routes/settings.tsx +118 -0
- package/corpus/templates/crm/app/routes/setup.tsx +308 -0
- package/corpus/templates/crm/app/routes/tasks.tsx +252 -0
- package/corpus/templates/crm/app/routes/views.tsx +683 -0
- package/corpus/templates/crm/app/routes.ts +19 -0
- package/corpus/templates/crm/app/vite-env.d.ts +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-any-list-or-view-can-be-shown-as-a-board-grouped-by-stage-so.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-crm-now-finds-likely-duplicate-records-and-tells-you-exactly.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-enrichment-now-shows-what-a-run-will-cost-before-it-starts-g.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-lists-turn-any-set-of-records-into-a-pipeline-with-its-own-s.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-moving-a-record-or-list-entry-into-a-stage-that-was-retired-.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-opening-a-record-now-shows-one-page-with-its-fields-the-list.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-press-cmd-k-to-jump-to-any-record-list-view-or-setting-and-u.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-provider-record-edits-now-show-an-exact-before-after-diff-an.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-record-page-attribute-labels-now-read-in-full-instead-of-bei.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-records-now-use-typed-fields-currency-dates-ratings-status-s.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-retyping-a-value-on-the-record-page-now-replaces-it-instead-.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-settings-now-has-fields-and-lists-tabs-for-adding-fields-edi.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-the-proposal-review-now-shows-the-field-that-actually-change.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-26-the-record-grid-is-now-a-real-spreadsheet-filter-sort-and-pa.md +6 -0
- package/corpus/templates/crm/components.json +20 -0
- package/corpus/templates/crm/docs/architecture/crm-contract.md +214 -0
- package/corpus/templates/crm/docs/features/README.md +55 -0
- package/corpus/templates/crm/docs/features/f1-records-and-fields.mdx +52 -0
- package/corpus/templates/crm/docs/features/f2-lists-pipelines-and-views.mdx +48 -0
- package/corpus/templates/crm/docs/features/f3-work-and-record-quality.mdx +40 -0
- package/corpus/templates/crm/docs/features/f4-evidence-and-chat.mdx +47 -0
- package/corpus/templates/crm/learnings.defaults.md +5 -0
- package/corpus/templates/crm/netlify.toml +11 -0
- package/corpus/templates/crm/package.json +61 -0
- package/corpus/templates/crm/public/favicon.svg +1 -0
- package/corpus/templates/crm/public/icon-180.svg +1 -0
- package/corpus/templates/crm/public/manifest.json +11 -0
- package/corpus/templates/crm/react-router.config.ts +7 -0
- package/corpus/templates/crm/server/crm/adapter.ts +32 -0
- package/corpus/templates/crm/server/crm/crm-field-firewall.ts +64 -0
- package/corpus/templates/crm/server/crm/crm-mirror.ts +721 -0
- package/corpus/templates/crm/server/crm/field-policy-attributes.ts +48 -0
- package/corpus/templates/crm/server/crm/hubspot-adapter.ts +1146 -0
- package/corpus/templates/crm/server/crm/native-adapter.ts +1810 -0
- package/corpus/templates/crm/server/crm/provider-record-link.ts +264 -0
- package/corpus/templates/crm/server/crm/read-through.ts +207 -0
- package/corpus/templates/crm/server/crm/salesforce-adapter.ts +1255 -0
- package/corpus/templates/crm/server/db/crm-store.ts +1112 -0
- package/corpus/templates/crm/server/db/index.ts +191 -0
- package/corpus/templates/crm/server/db/schema.ts +647 -0
- package/corpus/templates/crm/server/lib/crm-query.ts +1558 -0
- package/corpus/templates/crm/server/lib/dedupe.ts +714 -0
- package/corpus/templates/crm/server/lib/enrichment-cost.ts +381 -0
- package/corpus/templates/crm/server/lib/enrichment-slots.ts +519 -0
- package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +65 -0
- package/corpus/templates/crm/server/lib/intelligence/evidence.ts +105 -0
- package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +94 -0
- package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +39 -0
- package/corpus/templates/crm/server/lib/intelligence/summary.ts +19 -0
- package/corpus/templates/crm/server/lib/lifecycle.ts +634 -0
- package/corpus/templates/crm/server/lib/provider-api.ts +64 -0
- package/corpus/templates/crm/server/middleware/auth.ts +4 -0
- package/corpus/templates/crm/server/plugins/agent-chat.ts +65 -0
- package/corpus/templates/crm/server/plugins/auth.ts +14 -0
- package/corpus/templates/crm/server/plugins/core-routes.ts +17 -0
- package/corpus/templates/crm/server/plugins/db.ts +738 -0
- package/corpus/templates/crm/server/routes/[...page].get.ts +5 -0
- package/corpus/templates/crm/shared/crm-attributes.ts +469 -0
- package/corpus/templates/crm/shared/crm-automation-recipes.ts +132 -0
- package/corpus/templates/crm/shared/crm-contract.ts +417 -0
- package/corpus/templates/crm/shared/crm-navigation.ts +190 -0
- package/corpus/templates/crm/shared/crm-sales-config.ts +63 -0
- package/corpus/templates/crm/ssr-entry.ts +11 -0
- package/corpus/templates/crm/tsconfig.json +24 -0
- package/corpus/templates/crm/vite.config.ts +15 -0
- package/corpus/templates/crm/vitest.config.ts +5 -0
- package/corpus/templates/design/app/i18n-data.ts +12 -12
- package/corpus/templates/design/changelog/2026-07-26-apply-design-updates-from-a-centered-top-toolbar-without-cov.md +6 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +12 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
- package/src/cli/templates-meta.ts +12 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useActionMutation,
|
|
3
|
+
useActionQuery,
|
|
4
|
+
} from "@agent-native/core/client/hooks";
|
|
5
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
6
|
+
import { useParams } from "react-router";
|
|
7
|
+
|
|
8
|
+
import { RecordActions } from "@/components/crm/RecordActions";
|
|
9
|
+
import { RecordWorkspace } from "@/components/crm/RecordWorkspace";
|
|
10
|
+
import { normalizeRecord, type CrmRecordDetail } from "@/lib/types";
|
|
11
|
+
|
|
12
|
+
export default function RecordRoute() {
|
|
13
|
+
const t = useT();
|
|
14
|
+
const { recordId } = useParams();
|
|
15
|
+
const query = useActionQuery<unknown>(
|
|
16
|
+
"get-crm-record" as never,
|
|
17
|
+
{ recordId } as never,
|
|
18
|
+
{ enabled: Boolean(recordId) },
|
|
19
|
+
);
|
|
20
|
+
const manageTask = useActionMutation<
|
|
21
|
+
unknown,
|
|
22
|
+
{ taskId: string; status: "done" }
|
|
23
|
+
>("manage-crm-task" as never);
|
|
24
|
+
const summary = normalizeRecord(query.data, "account");
|
|
25
|
+
const detail = summary
|
|
26
|
+
? ({ ...summary, ...(query.data as object) } as CrmRecordDetail)
|
|
27
|
+
: undefined;
|
|
28
|
+
|
|
29
|
+
// A read that failed is not a record that is gone. Rendering the "archived or
|
|
30
|
+
// no longer shared" empty state for a transport or permission error would
|
|
31
|
+
// tell the user something we do not know.
|
|
32
|
+
if (query.error)
|
|
33
|
+
return (
|
|
34
|
+
<div className="p-6">
|
|
35
|
+
<p className="text-sm font-medium">{t("record.loadFailedTitle")}</p>
|
|
36
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
37
|
+
{query.error instanceof Error
|
|
38
|
+
? query.error.message
|
|
39
|
+
: t("record.loadFailedDescription")}
|
|
40
|
+
</p>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<RecordWorkspace
|
|
46
|
+
record={detail}
|
|
47
|
+
isLoading={query.isLoading}
|
|
48
|
+
isCompletingTask={manageTask.isPending}
|
|
49
|
+
onCompleteTask={(taskId) => manageTask.mutate({ taskId, status: "done" })}
|
|
50
|
+
actions={detail ? <RecordActions record={detail} /> : undefined}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { useSearchParams } from "react-router";
|
|
3
|
+
|
|
4
|
+
import { CreateCrmRecordDialog } from "@/components/crm/CreateCrmRecordDialog";
|
|
5
|
+
import { RecordGrid } from "@/components/crm/RecordGrid";
|
|
6
|
+
import { PageHeader } from "@/components/crm/Surface";
|
|
7
|
+
import type { CrmKind } from "@/lib/types";
|
|
8
|
+
import { cn } from "@/lib/utils";
|
|
9
|
+
|
|
10
|
+
const KINDS: CrmKind[] = ["account", "person", "opportunity"];
|
|
11
|
+
|
|
12
|
+
export function meta() {
|
|
13
|
+
return [{ title: "Records · CRM" }]; // i18n-ignore
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function RecordsRoute() {
|
|
17
|
+
const t = useT();
|
|
18
|
+
const [params, setParams] = useSearchParams();
|
|
19
|
+
const raw = params.get("kind");
|
|
20
|
+
const kind: CrmKind = KINDS.includes(raw as CrmKind)
|
|
21
|
+
? (raw as CrmKind)
|
|
22
|
+
: "account";
|
|
23
|
+
|
|
24
|
+
function selectKind(next: CrmKind) {
|
|
25
|
+
const updated = new URLSearchParams(params);
|
|
26
|
+
updated.set("kind", next);
|
|
27
|
+
// A cursor and a search term belong to the kind that produced them.
|
|
28
|
+
updated.delete("q");
|
|
29
|
+
setParams(updated, { replace: true });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<>
|
|
34
|
+
<PageHeader
|
|
35
|
+
eyebrow={t("records.eyebrow")}
|
|
36
|
+
title={t("records.title")}
|
|
37
|
+
description={t("records.description")}
|
|
38
|
+
actions={<CreateCrmRecordDialog kind={kind} />}
|
|
39
|
+
/>
|
|
40
|
+
<div className="flex items-center gap-1 border-b border-border/70 px-5 py-2">
|
|
41
|
+
{KINDS.map((candidate) => (
|
|
42
|
+
<button
|
|
43
|
+
key={candidate}
|
|
44
|
+
type="button"
|
|
45
|
+
onClick={() => selectKind(candidate)}
|
|
46
|
+
className={cn(
|
|
47
|
+
"cursor-pointer rounded-full px-3 py-1 text-sm transition-colors",
|
|
48
|
+
candidate === kind
|
|
49
|
+
? "bg-primary text-primary-foreground"
|
|
50
|
+
: "text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
51
|
+
)}
|
|
52
|
+
>
|
|
53
|
+
{t(`records.kind.${candidate}`)}
|
|
54
|
+
</button>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
<RecordGrid
|
|
58
|
+
key={kind}
|
|
59
|
+
kind={kind}
|
|
60
|
+
emptyTitle={t(`records.empty.${kind}`)}
|
|
61
|
+
/>
|
|
62
|
+
</>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { ChangelogSettingsCard } from "@agent-native/core/client/changelog";
|
|
2
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
3
|
+
import {
|
|
4
|
+
SettingsTabsPage,
|
|
5
|
+
useAgentSettingsTabs,
|
|
6
|
+
type SettingsTabItem,
|
|
7
|
+
} from "@agent-native/core/client/settings";
|
|
8
|
+
import {
|
|
9
|
+
IconAdjustments,
|
|
10
|
+
IconColumns3,
|
|
11
|
+
IconListDetails,
|
|
12
|
+
IconPlugConnected,
|
|
13
|
+
IconWaveSine,
|
|
14
|
+
} from "@tabler/icons-react";
|
|
15
|
+
import { useMemo } from "react";
|
|
16
|
+
import { useLocation } from "react-router";
|
|
17
|
+
|
|
18
|
+
import { IntelligenceSettings } from "@/components/crm/IntelligenceSettings";
|
|
19
|
+
import { AdvancedSettings } from "@/components/crm/settings/AdvancedSettings";
|
|
20
|
+
import { ConnectionSettings } from "@/components/crm/settings/ConnectionSettings";
|
|
21
|
+
import { FieldsSettings } from "@/components/crm/settings/FieldsSettings";
|
|
22
|
+
import { ListsSettings } from "@/components/crm/settings/ListsSettings";
|
|
23
|
+
|
|
24
|
+
import changelog from "../../CHANGELOG.md?raw";
|
|
25
|
+
|
|
26
|
+
export function meta() {
|
|
27
|
+
return [{ title: "CRM settings" }];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* `/settings/<section>` deep links. `connections` is the shared workspace tab
|
|
32
|
+
* and `connection` is the CRM one, so the segment is matched exactly rather
|
|
33
|
+
* than by substring.
|
|
34
|
+
*/
|
|
35
|
+
const SETTINGS_SECTIONS: readonly string[] = [
|
|
36
|
+
"fields",
|
|
37
|
+
"lists",
|
|
38
|
+
"intelligence",
|
|
39
|
+
"connection",
|
|
40
|
+
"connections",
|
|
41
|
+
"advanced",
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
function sectionFromPath(pathname: string): string {
|
|
45
|
+
const section = pathname.split("/settings/")[1]?.split("/")[0] ?? "";
|
|
46
|
+
return SETTINGS_SECTIONS.includes(section) ? section : "general";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default function SettingsRoute() {
|
|
50
|
+
const t = useT();
|
|
51
|
+
const location = useLocation();
|
|
52
|
+
const agentSettingsTabs = useAgentSettingsTabs();
|
|
53
|
+
const tabs = useMemo<SettingsTabItem[]>(
|
|
54
|
+
() => [
|
|
55
|
+
{
|
|
56
|
+
id: "connection",
|
|
57
|
+
label: t("connection.tab"),
|
|
58
|
+
icon: IconPlugConnected,
|
|
59
|
+
keywords: "provider hubspot salesforce native mode mirror sync",
|
|
60
|
+
content: <ConnectionSettings />,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "fields",
|
|
64
|
+
label: t("fields.tab"),
|
|
65
|
+
icon: IconColumns3,
|
|
66
|
+
keywords:
|
|
67
|
+
"attributes schema columns slug type authority options status select stage",
|
|
68
|
+
content: <FieldsSettings />,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "lists",
|
|
72
|
+
label: t("lists.tab"),
|
|
73
|
+
icon: IconListDetails,
|
|
74
|
+
keywords: "lists entries pipeline workflow stage board",
|
|
75
|
+
content: <ListsSettings />,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "intelligence",
|
|
79
|
+
label: t("intelligence.tab"),
|
|
80
|
+
icon: IconWaveSine,
|
|
81
|
+
keywords: "signals trackers keywords smart detectors call evidence",
|
|
82
|
+
content: <IntelligenceSettings />,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "advanced",
|
|
86
|
+
label: t("advanced.tab"),
|
|
87
|
+
icon: IconAdjustments,
|
|
88
|
+
group: "workspace",
|
|
89
|
+
keywords: "danger reset reconfigure retention archive delete",
|
|
90
|
+
content: <AdvancedSettings />,
|
|
91
|
+
},
|
|
92
|
+
...agentSettingsTabs,
|
|
93
|
+
],
|
|
94
|
+
[agentSettingsTabs, t],
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<SettingsTabsPage
|
|
99
|
+
defaultTab={sectionFromPath(location.pathname)}
|
|
100
|
+
extraTabs={tabs}
|
|
101
|
+
general={
|
|
102
|
+
<div className="mx-auto w-full max-w-2xl space-y-3">
|
|
103
|
+
<h1 className="text-xl font-semibold tracking-tight">
|
|
104
|
+
{t("settings.title")}
|
|
105
|
+
</h1>
|
|
106
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
107
|
+
{t("settings.description")}
|
|
108
|
+
</p>
|
|
109
|
+
</div>
|
|
110
|
+
}
|
|
111
|
+
whatsNew={
|
|
112
|
+
<div className="mx-auto w-full max-w-2xl">
|
|
113
|
+
<ChangelogSettingsCard markdown={changelog} />
|
|
114
|
+
</div>
|
|
115
|
+
}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useActionMutation,
|
|
3
|
+
useActionQuery,
|
|
4
|
+
} from "@agent-native/core/client/hooks";
|
|
5
|
+
import { useMemo, useState } from "react";
|
|
6
|
+
import { Link, useNavigate } from "react-router";
|
|
7
|
+
import { toast } from "sonner";
|
|
8
|
+
|
|
9
|
+
import { PageHeader } from "@/components/crm/Surface";
|
|
10
|
+
import { Button } from "@/components/ui/button";
|
|
11
|
+
import { Input } from "@/components/ui/input";
|
|
12
|
+
import { Label } from "@/components/ui/label";
|
|
13
|
+
import {
|
|
14
|
+
Select,
|
|
15
|
+
SelectContent,
|
|
16
|
+
SelectItem,
|
|
17
|
+
SelectTrigger,
|
|
18
|
+
SelectValue,
|
|
19
|
+
} from "@/components/ui/select";
|
|
20
|
+
|
|
21
|
+
interface WorkspaceConnection {
|
|
22
|
+
id: string;
|
|
23
|
+
provider: "hubspot" | "salesforce";
|
|
24
|
+
label: string;
|
|
25
|
+
accountLabel?: string | null;
|
|
26
|
+
status: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default function SetupRoute() {
|
|
30
|
+
const navigate = useNavigate();
|
|
31
|
+
const connectionsQuery = useActionQuery<unknown>(
|
|
32
|
+
"list-workspace-connections" as never,
|
|
33
|
+
{ includeDisabled: false } as never,
|
|
34
|
+
);
|
|
35
|
+
const connections = useMemo(
|
|
36
|
+
() => crmConnections(connectionsQuery.data),
|
|
37
|
+
[connectionsQuery.data],
|
|
38
|
+
);
|
|
39
|
+
const [workspaceConnectionId, setWorkspaceConnectionId] = useState("");
|
|
40
|
+
const [pipelineIds, setPipelineIds] = useState("");
|
|
41
|
+
const [historyDays, setHistoryDays] = useState("90");
|
|
42
|
+
const configure = useActionMutation<
|
|
43
|
+
{ id: string },
|
|
44
|
+
{
|
|
45
|
+
workspaceConnectionId: string;
|
|
46
|
+
provider: "hubspot" | "salesforce";
|
|
47
|
+
selectedPipelineIds: string[];
|
|
48
|
+
selectedObjectTypes: string[];
|
|
49
|
+
}
|
|
50
|
+
>("configure-crm-connection" as never);
|
|
51
|
+
const configureNative = useActionMutation<
|
|
52
|
+
{ id: string },
|
|
53
|
+
Record<string, never>
|
|
54
|
+
>("configure-native-crm" as never);
|
|
55
|
+
const sync = useActionMutation<
|
|
56
|
+
unknown,
|
|
57
|
+
{
|
|
58
|
+
connectionId: string;
|
|
59
|
+
objectType: string;
|
|
60
|
+
scope: { updatedAfter: string; pipelineIds?: string[] };
|
|
61
|
+
maxPages: number;
|
|
62
|
+
}
|
|
63
|
+
>("sync-crm" as never);
|
|
64
|
+
|
|
65
|
+
const selected = connections.find(
|
|
66
|
+
(connection) => connection.id === workspaceConnectionId,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
async function syncRecentRecords() {
|
|
70
|
+
if (!selected) return;
|
|
71
|
+
const selectedPipelines = pipelineIds
|
|
72
|
+
.split(",")
|
|
73
|
+
.map((value) => value.trim())
|
|
74
|
+
.filter(Boolean)
|
|
75
|
+
.slice(0, 50);
|
|
76
|
+
const days = Math.max(
|
|
77
|
+
1,
|
|
78
|
+
Math.min(365, Number.parseInt(historyDays, 10) || 90),
|
|
79
|
+
);
|
|
80
|
+
try {
|
|
81
|
+
const connection = await configure.mutateAsync({
|
|
82
|
+
workspaceConnectionId,
|
|
83
|
+
provider: selected.provider,
|
|
84
|
+
selectedPipelineIds:
|
|
85
|
+
selected.provider === "hubspot" ? selectedPipelines : [],
|
|
86
|
+
selectedObjectTypes: objectTypesForProvider(selected.provider),
|
|
87
|
+
});
|
|
88
|
+
const updatedAfter = new Date(
|
|
89
|
+
Date.now() - days * 24 * 60 * 60 * 1_000,
|
|
90
|
+
).toISOString();
|
|
91
|
+
for (const objectType of objectTypesForProvider(selected.provider)) {
|
|
92
|
+
await sync.mutateAsync({
|
|
93
|
+
connectionId: connection.id,
|
|
94
|
+
objectType,
|
|
95
|
+
scope: {
|
|
96
|
+
updatedAfter,
|
|
97
|
+
...(selected.provider === "hubspot" &&
|
|
98
|
+
objectType === "deals" &&
|
|
99
|
+
selectedPipelines.length
|
|
100
|
+
? { pipelineIds: selectedPipelines }
|
|
101
|
+
: {}),
|
|
102
|
+
},
|
|
103
|
+
maxPages: 2,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
toast.success(
|
|
107
|
+
`Recent ${providerLabel(selected.provider)} records are ready.`,
|
|
108
|
+
);
|
|
109
|
+
navigate("/", { replace: true });
|
|
110
|
+
} catch (error) {
|
|
111
|
+
toast.error(error instanceof Error ? error.message : "CRM sync failed.");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function startNativeCrm() {
|
|
116
|
+
try {
|
|
117
|
+
await configureNative.mutateAsync({});
|
|
118
|
+
toast.success("Your native CRM is ready.");
|
|
119
|
+
navigate("/", { replace: true });
|
|
120
|
+
} catch (error) {
|
|
121
|
+
toast.error(
|
|
122
|
+
error instanceof Error ? error.message : "Could not start native CRM.",
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<>
|
|
129
|
+
<PageHeader
|
|
130
|
+
eyebrow="CRM"
|
|
131
|
+
title="Set up CRM"
|
|
132
|
+
description="Start with CRM's built-in SQL store, or connect a scoped HubSpot or Salesforce companion."
|
|
133
|
+
/>
|
|
134
|
+
<div className="mx-auto grid w-full max-w-xl gap-6 p-5 sm:p-7">
|
|
135
|
+
<section className="grid gap-4 rounded-lg border border-border/70 bg-card p-4">
|
|
136
|
+
<div className="grid gap-1">
|
|
137
|
+
<p className="text-sm font-medium">Start with Native SQL</p>
|
|
138
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
139
|
+
Run accounts, people, opportunities, saved views, tasks, and
|
|
140
|
+
cadence without connecting another CRM. Your CRM is
|
|
141
|
+
local-authoritative and portable across SQLite, Postgres, and D1.
|
|
142
|
+
</p>
|
|
143
|
+
</div>
|
|
144
|
+
<Button
|
|
145
|
+
className="w-full sm:w-fit"
|
|
146
|
+
disabled={configureNative.isPending}
|
|
147
|
+
onClick={() => void startNativeCrm()}
|
|
148
|
+
>
|
|
149
|
+
{configureNative.isPending ? "Starting…" : "Start with Native SQL"}
|
|
150
|
+
</Button>
|
|
151
|
+
</section>
|
|
152
|
+
<div className="flex items-center gap-3 text-xs font-medium uppercase tracking-[0.12em] text-muted-foreground">
|
|
153
|
+
<span className="h-px flex-1 bg-border" />
|
|
154
|
+
Or connect an existing CRM
|
|
155
|
+
<span className="h-px flex-1 bg-border" />
|
|
156
|
+
</div>
|
|
157
|
+
<div className="grid gap-2">
|
|
158
|
+
<Label htmlFor="crm-connection">CRM connection</Label>
|
|
159
|
+
<Select
|
|
160
|
+
value={workspaceConnectionId}
|
|
161
|
+
onValueChange={setWorkspaceConnectionId}
|
|
162
|
+
disabled={connectionsQuery.isLoading}
|
|
163
|
+
>
|
|
164
|
+
<SelectTrigger id="crm-connection">
|
|
165
|
+
<SelectValue placeholder="Select HubSpot or Salesforce" />
|
|
166
|
+
</SelectTrigger>
|
|
167
|
+
<SelectContent>
|
|
168
|
+
{connections.map((connection) => (
|
|
169
|
+
<SelectItem key={connection.id} value={connection.id}>
|
|
170
|
+
{connection.label} · {providerLabel(connection.provider)}
|
|
171
|
+
{connection.accountLabel
|
|
172
|
+
? ` · ${connection.accountLabel}`
|
|
173
|
+
: ""}
|
|
174
|
+
</SelectItem>
|
|
175
|
+
))}
|
|
176
|
+
</SelectContent>
|
|
177
|
+
</Select>
|
|
178
|
+
<p className="text-xs text-muted-foreground">
|
|
179
|
+
Only workspace Connections granted to this app can be used. CRM
|
|
180
|
+
never stores provider tokens.
|
|
181
|
+
</p>
|
|
182
|
+
</div>
|
|
183
|
+
<div className="grid gap-4 rounded-lg border border-border/70 bg-card p-4 sm:grid-cols-2">
|
|
184
|
+
<div className="grid gap-2">
|
|
185
|
+
<Label htmlFor="history-days">Recent history</Label>
|
|
186
|
+
<Input
|
|
187
|
+
id="history-days"
|
|
188
|
+
type="number"
|
|
189
|
+
min={1}
|
|
190
|
+
max={365}
|
|
191
|
+
value={historyDays}
|
|
192
|
+
onChange={(event) => setHistoryDays(event.target.value)}
|
|
193
|
+
/>
|
|
194
|
+
<p className="text-xs text-muted-foreground">
|
|
195
|
+
Days, capped at 365.
|
|
196
|
+
</p>
|
|
197
|
+
</div>
|
|
198
|
+
{selected?.provider === "hubspot" ? (
|
|
199
|
+
<div className="grid gap-2">
|
|
200
|
+
<Label htmlFor="pipeline-ids">Deal pipeline IDs</Label>
|
|
201
|
+
<Input
|
|
202
|
+
id="pipeline-ids"
|
|
203
|
+
value={pipelineIds}
|
|
204
|
+
maxLength={8_000}
|
|
205
|
+
placeholder="Optional, comma-separated"
|
|
206
|
+
onChange={(event) => setPipelineIds(event.target.value)}
|
|
207
|
+
/>
|
|
208
|
+
<p className="text-xs text-muted-foreground">
|
|
209
|
+
Leave blank for recently updated deals.
|
|
210
|
+
</p>
|
|
211
|
+
</div>
|
|
212
|
+
) : selected?.provider === "salesforce" ? (
|
|
213
|
+
<div className="grid gap-2">
|
|
214
|
+
<p className="text-sm font-medium">Salesforce objects</p>
|
|
215
|
+
<p className="text-xs leading-5 text-muted-foreground">
|
|
216
|
+
CRM mirrors recently updated Accounts, Contacts, and
|
|
217
|
+
Opportunities in this initial cohort.
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
) : (
|
|
221
|
+
<div className="grid gap-2">
|
|
222
|
+
<p className="text-sm font-medium">Cohort objects</p>
|
|
223
|
+
<p className="text-xs leading-5 text-muted-foreground">
|
|
224
|
+
Choose a connection to see its initial object cohort.
|
|
225
|
+
</p>
|
|
226
|
+
</div>
|
|
227
|
+
)}
|
|
228
|
+
</div>
|
|
229
|
+
{connections.length ? (
|
|
230
|
+
<Button
|
|
231
|
+
disabled={
|
|
232
|
+
!selected ||
|
|
233
|
+
selected.status !== "connected" ||
|
|
234
|
+
configure.isPending ||
|
|
235
|
+
sync.isPending
|
|
236
|
+
}
|
|
237
|
+
onClick={() => void syncRecentRecords()}
|
|
238
|
+
>
|
|
239
|
+
{configure.isPending || sync.isPending
|
|
240
|
+
? "Syncing…"
|
|
241
|
+
: "Configure and sync"}
|
|
242
|
+
</Button>
|
|
243
|
+
) : (
|
|
244
|
+
<div className="rounded-lg border border-dashed border-border p-5 text-center">
|
|
245
|
+
<p className="text-sm font-medium">
|
|
246
|
+
No connected HubSpot or Salesforce account is available.
|
|
247
|
+
</p>
|
|
248
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
249
|
+
You can start with Native SQL above, or authorize a provider and
|
|
250
|
+
grant it to CRM from shared settings.
|
|
251
|
+
</p>
|
|
252
|
+
<Button asChild variant="outline" className="mt-4">
|
|
253
|
+
<Link to="/settings/connections">Open shared connections</Link>
|
|
254
|
+
</Button>
|
|
255
|
+
<p className="mt-3 text-xs text-muted-foreground">
|
|
256
|
+
Using a Salesforce sandbox?{" "}
|
|
257
|
+
<a
|
|
258
|
+
className="font-medium text-foreground underline underline-offset-4"
|
|
259
|
+
href="/_agent-native/connections/oauth/salesforce/start?environment=sandbox"
|
|
260
|
+
>
|
|
261
|
+
Authorize the sandbox directly
|
|
262
|
+
</a>
|
|
263
|
+
.
|
|
264
|
+
</p>
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
267
|
+
</div>
|
|
268
|
+
</>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function crmConnections(data: unknown): WorkspaceConnection[] {
|
|
273
|
+
if (!data || typeof data !== "object") return [];
|
|
274
|
+
const rows = (data as { connections?: unknown }).connections;
|
|
275
|
+
if (!Array.isArray(rows)) return [];
|
|
276
|
+
return rows.flatMap((row) => {
|
|
277
|
+
if (!row || typeof row !== "object") return [];
|
|
278
|
+
const item = row as Record<string, unknown>;
|
|
279
|
+
if (
|
|
280
|
+
(item.provider !== "hubspot" && item.provider !== "salesforce") ||
|
|
281
|
+
typeof item.id !== "string" ||
|
|
282
|
+
typeof item.label !== "string" ||
|
|
283
|
+
typeof item.status !== "string"
|
|
284
|
+
) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
return [
|
|
288
|
+
{
|
|
289
|
+
id: item.id,
|
|
290
|
+
provider: item.provider,
|
|
291
|
+
label: item.label,
|
|
292
|
+
accountLabel:
|
|
293
|
+
typeof item.accountLabel === "string" ? item.accountLabel : null,
|
|
294
|
+
status: item.status,
|
|
295
|
+
},
|
|
296
|
+
];
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function objectTypesForProvider(provider: WorkspaceConnection["provider"]) {
|
|
301
|
+
return provider === "hubspot"
|
|
302
|
+
? ["companies", "contacts", "deals"]
|
|
303
|
+
: ["Account", "Contact", "Opportunity"];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function providerLabel(provider: WorkspaceConnection["provider"]) {
|
|
307
|
+
return provider === "hubspot" ? "HubSpot" : "Salesforce";
|
|
308
|
+
}
|