@elevasis/ui 2.35.0 → 2.36.0
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/dist/app/index.d.ts +25 -18
- package/dist/app/index.js +2 -2
- package/dist/{chunk-26HFM4MH.js → chunk-F6EFC2MJ.js} +1555 -1903
- package/dist/{chunk-VDOOGGBA.js → chunk-K4UZU3TU.js} +2 -2
- package/dist/{chunk-4U3XAWCN.js → chunk-O2Q4VMRN.js} +134 -495
- package/dist/components/index.d.ts +7 -4
- package/dist/components/index.js +2 -2
- package/dist/components/navigation/index.js +2 -2
- package/dist/execution/index.d.ts +2 -2
- package/dist/features/auth/index.d.ts +3 -0
- package/dist/features/auth/index.js +2 -2
- package/dist/features/clients/index.js +2 -2
- package/dist/features/crm/index.d.ts +3 -0
- package/dist/features/crm/index.js +2 -2
- package/dist/features/dashboard/index.d.ts +3 -3
- package/dist/features/dashboard/index.js +2 -2
- package/dist/features/delivery/index.d.ts +3 -0
- package/dist/features/delivery/index.js +2 -2
- package/dist/features/knowledge/index.js +3 -3
- package/dist/features/lead-gen/index.d.ts +286 -48
- package/dist/features/lead-gen/index.js +2 -2
- package/dist/features/monitoring/index.js +2 -2
- package/dist/features/monitoring/requests/index.js +2 -2
- package/dist/features/operations/index.d.ts +30 -30
- package/dist/features/operations/index.js +2 -2
- package/dist/features/settings/index.d.ts +3 -0
- package/dist/features/settings/index.js +2 -2
- package/dist/hooks/delivery/index.d.ts +3 -0
- package/dist/hooks/delivery/index.js +2 -2
- package/dist/hooks/index.d.ts +29 -16
- package/dist/hooks/index.js +2 -2
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +13 -13
- package/dist/hooks/published.d.ts +29 -16
- package/dist/hooks/published.js +2 -2
- package/dist/index.d.ts +51 -34
- package/dist/index.js +2 -2
- package/dist/initialization/index.d.ts +3 -0
- package/dist/knowledge/index.d.ts +21 -21
- package/dist/knowledge/index.js +6 -6
- package/dist/{knowledge-search-index-ORIJCEZX.js → knowledge-search-index-NBCTFIOH.js} +2 -2
- package/dist/organization/index.js +2 -2
- package/dist/profile/index.d.ts +3 -0
- package/dist/provider/index.d.ts +25 -18
- package/dist/provider/index.js +2 -2
- package/dist/provider/published.d.ts +25 -18
- package/dist/provider/published.js +2 -2
- package/dist/sse/index.js +26 -5
- package/dist/supabase/index.d.ts +6 -0
- package/dist/types/index.d.ts +16 -13
- package/dist/utils/index.d.ts +3 -3
- package/package.json +4 -4
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ChatHeader, ChatSidebar } from './chunk-CXY7FMUM.js';
|
|
2
|
-
import { observabilityKeys, useCyberColors, CardHeader, EmptyState, CyberLegendItem, CyberAreaChart, CenteredErrorState, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, FeatureUnavailableState, ElevasisLoader, GlowDot, JsonViewer, ListSkeleton, PageTitleCaption, StatCard, APIErrorAlert, CyberDonut, CollapsibleSection, ActivityTimeline, StatusBadge, TabCountBadge, ResourceCard, HeroStatsRow,
|
|
2
|
+
import { observabilityKeys, useCyberColors, CardHeader, EmptyState, CyberLegendItem, CyberAreaChart, CenteredErrorState, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, FeatureUnavailableState, ElevasisLoader, GlowDot, JsonViewer, ListSkeleton, PageTitleCaption, StatCard, APIErrorAlert, CyberDonut, CollapsibleSection, ActivityTimeline, ContextViewer, StatusBadge, TabCountBadge, ResourceCard, HeroStatsRow, CostTrendChart, ActivityTrendChart } from './chunk-SIQ3P4OR.js';
|
|
3
3
|
import { StyledMarkdown } from './chunk-3KMDHCAR.js';
|
|
4
4
|
import { glassBase, mantineThemeOverride, createCssVariablesResolver, PresetsProvider, useAvailablePresets } from './chunk-AKW7KISS.js';
|
|
5
5
|
import { PRESETS, getPreset, generateShades } from './chunk-WF7CONXF.js';
|
|
6
6
|
import { useSupabase } from './chunk-BRXELOHC.js';
|
|
7
|
-
import {
|
|
7
|
+
import { resolveOrganizationModel, OrgKnowledgeNodeSchema, defineResources, defineActions, defineTopology, topologyRef, listAllSystems, projectOrganizationSurfaces, topologyRelationship, PROJECTS_VIEW_ACTION_ID, resolveSemanticIconComponent, getAllBuildTemplates, getLeadGenStageCatalog, buildOrganizationGraph, getResourcesForSystem, devOnlyFor, requiresAdminFor, topLevel, parentOf, ancestorsOf, childrenOf, findById, findByPath, getSystem, SemanticIcon, defaultPathFor, getSortedSidebarEntries, compileOrganizationOntology, getSystemAncestors, getSemanticIconComponent } from './chunk-O2Q4VMRN.js';
|
|
8
8
|
import { SubshellContainer, SubshellSidebar, SubshellRightSideContainer, AppearanceProvider, AppShellLoader, useAppearance, SubshellSidebarLoader, SubshellContentContainer, PageContainer, SubshellLoader, AppShellCenteredContainer } from './chunk-LUYVRATI.js';
|
|
9
9
|
import { AppBackground } from './chunk-WLOQ4IBG.js';
|
|
10
10
|
import { HTTP_HEADERS, ApiClientProvider, useApiClient } from './chunk-57OZ3AEG.js';
|
|
@@ -14,7 +14,7 @@ import { useRouterContext } from './chunk-Q7DJKLEN.js';
|
|
|
14
14
|
import { Graph_module_css_default, useDirectedChainHighlighting, useNodeSelection, useFitViewTrigger, useGraphHighlighting, calculateGraphHeight, GRAPH_CONSTANTS } from './chunk-HENXLGVD.js';
|
|
15
15
|
import { STATUS_COLORS, getStatusIcon, formatDuration, getStatusColors, AGENT_CONSTANTS, shouldAnimateEdge, TIMELINE_CONSTANTS, calculateBarPosition, CONTAINER_CONSTANTS, useExecutionPath, useUnifiedWorkflowLayout, WORKFLOW_CONSTANTS, useReactFlowAgent, getResourceStatusColor, useMergedExecution, useTimelineData, useAgentIterationData } from './chunk-7FPLLSHN.js';
|
|
16
16
|
import { ResourceTypeSchema, NonEmptyStringSchema, OriginResourceTypeSchema, UuidSchema, CredentialNameSchema, getErrorInfo, getErrorTitle, formatErrorMessage, STALE_TIME_DEFAULT, isAPIClientError, getTimeRangeDates, formatBucketTime, PAGE_SIZE_DEFAULT, REFETCH_INTERVAL_DASHBOARD, STALE_TIME_MONITORING, REFETCH_INTERVAL_RUNNING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, STALE_TIME_ADMIN, APIClientError, GC_TIME_MEDIUM, GC_TIME_SHORT, formatDateTime, getResourceIcon, formatTimeAgo, formatDate, formatRelativeTime, debounce, OAUTH_FLOW_TIMEOUT } from './chunk-GEFWMU26.js';
|
|
17
|
-
import { ResourceStatusColors, toWorkflowLogMessages
|
|
17
|
+
import { ResourceStatusColors, toWorkflowLogMessages } from './chunk-KRWALB24.js';
|
|
18
18
|
import { useStableAccessToken } from './chunk-VKIZUUPM.js';
|
|
19
19
|
import { useInitialization, InitializationProvider } from './chunk-533DUEQY.js';
|
|
20
20
|
import { OrganizationContext, useOrganization } from './chunk-DD3CCMCZ.js';
|
|
@@ -24,7 +24,7 @@ import { useAuthContext } from './chunk-BRJ3QZ4E.js';
|
|
|
24
24
|
import { createContext, lazy, memo, useMemo, useState, useRef, useEffect, useCallback, createElement, useContext, cloneElement, useId, Fragment as Fragment$1, Component, useDeferredValue, useEffectEvent, Suspense } from 'react';
|
|
25
25
|
import { useQueryClient, useQuery, useMutation, QueryClientProvider, useQueries, QueryClient } from '@tanstack/react-query';
|
|
26
26
|
import { createUseExternalEvents, Paper, Stack, Text, Group, Badge, Box, useComputedColorScheme, Card, Title, Checkbox, Tooltip, Center, Modal, TextInput, Textarea, Loader, Alert, Button, Space, Table, Select, ActionIcon, SegmentedControl, NumberFormatter, Switch, Pagination, mergeThemeOverrides, MantineProvider, UnstyledButton, Divider, ScrollArea, Popover, Indicator, Collapse, ThemeIcon, SimpleGrid, Code, CopyButton, PasswordInput, Anchor, Menu, Timeline, useMantineTheme, RangeSlider, Progress, Tabs, Breadcrumbs as Breadcrumbs$1, NumberInput, ColorSwatch, RingProgress, Grid, LoadingOverlay, Accordion, MultiSelect, Radio, Pill, Drawer, Chip, JsonInput, TagsInput } from '@mantine/core';
|
|
27
|
-
import { IconPlayerPlay, IconPlayerStop, IconArrowsSplit, IconSquare, IconBrain, IconFileText, IconLayoutGrid, IconColumns, IconFileInvoice, IconNotes, IconBriefcase, IconChecklist, IconFlag, IconList, IconBuilding, IconAddressBook, IconMail, IconSend, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconTarget, IconActivity, IconCode, IconSettings, IconLock, IconShieldOff, IconChevronUp, IconChevronDown, IconSelector, IconTrash, IconChartBar, IconCircleCheck, IconThumbDown, IconThumbUp, IconCircleX, IconSearch, IconFilterOff, IconArrowUpRight, IconAlertCircle, IconExternalLink, IconChartPie, IconHeartbeat, IconDownload, IconCpu, IconTrendingUp, IconCash, IconInfoCircle, IconExclamationCircle, IconBug, IconChecks, IconCircle, IconCircleFilled, IconBell, IconFocus2, IconChevronRight, IconTool, IconClockHour4, IconVersions, IconNetwork, IconSitemap, IconPencil, IconKey, IconCalendar, IconExclamationMark, IconShieldLock, IconCopy, IconPlus, IconPower, IconTag, IconUsers, IconWebhook, IconReload, IconTerminal2, IconMessage, IconArrowLeft, IconCalendarRepeat, IconCalendarEvent, IconCalendarTime, IconRobot, IconGitBranch, IconDotsVertical, IconPlayerPause, IconCalendarDue, IconCalendarStats, IconCalendarOff, IconListCheck, IconFilter, IconCategory, IconDatabase, IconTrophy, IconClockExclamation, IconUser, IconHistory, IconCurrencyDollar, IconTargetArrow, IconMessages, IconInbox, IconBolt, IconRestore, IconArrowRight, IconSparkles, IconListDetails, IconLayoutDashboard, IconBuildingFactory2, IconFileDescription, IconApps, IconRoute, IconHandStop, IconAdjustmentsHorizontal, IconCircleDashed, IconFolders, IconBraces, IconTopologyStar3, IconLayoutSidebarRightExpand, IconNote, IconArchive, IconTimeline, IconPalette, IconAdjustments, IconBrandDropbox, IconBrandGoogleDrive, IconPlug, IconMailForward, IconArrowDown, IconUserX, IconUserCheck, IconFileOff, IconCheckbox, IconPhone, IconActivityHeartbeat, IconClockPause, IconArrowsMaximize, IconShare2, IconFolder,
|
|
27
|
+
import { IconPlayerPlay, IconPlayerStop, IconArrowsSplit, IconSquare, IconBrain, IconFileText, IconLayoutGrid, IconColumns, IconFileInvoice, IconNotes, IconBriefcase, IconChecklist, IconFlag, IconList, IconBuilding, IconAddressBook, IconMail, IconSend, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconTarget, IconActivity, IconCode, IconSettings, IconLock, IconShieldOff, IconChevronUp, IconChevronDown, IconSelector, IconTrash, IconChartBar, IconCircleCheck, IconThumbDown, IconThumbUp, IconCircleX, IconSearch, IconFilterOff, IconArrowUpRight, IconAlertCircle, IconExternalLink, IconChartPie, IconHeartbeat, IconDownload, IconCpu, IconTrendingUp, IconCash, IconInfoCircle, IconExclamationCircle, IconBug, IconChecks, IconCircle, IconCircleFilled, IconBell, IconFocus2, IconChevronRight, IconTool, IconClockHour4, IconVersions, IconNetwork, IconSitemap, IconPencil, IconKey, IconCalendar, IconExclamationMark, IconShieldLock, IconCopy, IconPlus, IconPower, IconTag, IconUsers, IconWebhook, IconReload, IconTerminal2, IconMessage, IconArrowLeft, IconCalendarRepeat, IconCalendarEvent, IconCalendarTime, IconRobot, IconGitBranch, IconDotsVertical, IconPlayerPause, IconCalendarDue, IconCalendarStats, IconCalendarOff, IconListCheck, IconFilter, IconCategory, IconDatabase, IconTrophy, IconClockExclamation, IconUser, IconHistory, IconCurrencyDollar, IconTargetArrow, IconMessages, IconInbox, IconBolt, IconRestore, IconArrowRight, IconSparkles, IconListDetails, IconLayoutDashboard, IconBuildingFactory2, IconFileDescription, IconApps, IconRoute, IconHandStop, IconAdjustmentsHorizontal, IconCircleDashed, IconFolders, IconBraces, IconTopologyStar3, IconLayoutSidebarRightExpand, IconNote, IconArchive, IconTimeline, IconPalette, IconAdjustments, IconBrandDropbox, IconBrandGoogleDrive, IconPlug, IconMailForward, IconArrowDown, IconUserX, IconUserCheck, IconFileOff, IconCheckbox, IconPhone, IconActivityHeartbeat, IconClockPause, IconArrowsMaximize, IconShare2, IconFolder, IconScript, IconPlugConnected } from '@tabler/icons-react';
|
|
28
28
|
import { z } from 'zod';
|
|
29
29
|
import * as runtime from 'react/jsx-runtime';
|
|
30
30
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -135,7 +135,7 @@ function OrganizationProvider({ apiRequest, children }) {
|
|
|
135
135
|
const stillPresent = data.find((m) => m.organization?.workos_org_id === currentWorkOSOrganizationId);
|
|
136
136
|
if (!stillPresent) {
|
|
137
137
|
applyMembership(data[0] ?? null);
|
|
138
|
-
} else
|
|
138
|
+
} else {
|
|
139
139
|
applyMembership(stillPresent);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
@@ -152,7 +152,6 @@ function OrganizationProvider({ apiRequest, children }) {
|
|
|
152
152
|
memberships.length,
|
|
153
153
|
apiRequest,
|
|
154
154
|
currentWorkOSOrganizationId,
|
|
155
|
-
currentMembership?.id,
|
|
156
155
|
selectOrganization,
|
|
157
156
|
applyMembership
|
|
158
157
|
]);
|
|
@@ -330,70 +329,6 @@ var ListMembershipsQuerySchema = z.object({
|
|
|
330
329
|
}).strict().refine((data) => data.userId || data.organizationId, {
|
|
331
330
|
message: "Either userId or organizationId must be provided"
|
|
332
331
|
});
|
|
333
|
-
|
|
334
|
-
// ../core/src/business/acquisition/build-templates.ts
|
|
335
|
-
var BUILD_TEMPLATE_CATALOG = [
|
|
336
|
-
{
|
|
337
|
-
id: "local-services",
|
|
338
|
-
label: "Local Services",
|
|
339
|
-
description: "Source, analyze, qualify, and personalize local service businesses for outreach.",
|
|
340
|
-
steps: Object.values(PROSPECTING_STEPS.localServices)
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
id: "dtc-subscription-apollo-clickup",
|
|
344
|
-
label: "DTC Subscription (Apollo + ClickUp)",
|
|
345
|
-
description: "Import DTC brand leads from Apollo, crawl their websites, score fit, enrich contacts, and export via ClickUp.",
|
|
346
|
-
steps: Object.values(PROSPECTING_STEPS.dtcApolloClickup)
|
|
347
|
-
}
|
|
348
|
-
];
|
|
349
|
-
var DEFAULT_PROSPECTING_BUILD_TEMPLATE_ID = "local-services";
|
|
350
|
-
var PROSPECTING_BUILD_TEMPLATE_OPTIONS = BUILD_TEMPLATE_CATALOG.map(({ id, label, description }) => ({
|
|
351
|
-
id,
|
|
352
|
-
label,
|
|
353
|
-
description
|
|
354
|
-
}));
|
|
355
|
-
function createBuildPlanSnapshotFromTemplateId(templateId) {
|
|
356
|
-
const template = BUILD_TEMPLATE_CATALOG.find((item) => item.id === templateId);
|
|
357
|
-
if (!template) return null;
|
|
358
|
-
return {
|
|
359
|
-
templateId: template.id,
|
|
360
|
-
templateLabel: template.label,
|
|
361
|
-
steps: template.steps.map((step) => {
|
|
362
|
-
const snapshotStep = {
|
|
363
|
-
id: step.id,
|
|
364
|
-
label: step.label,
|
|
365
|
-
primaryEntity: step.primaryEntity,
|
|
366
|
-
outputs: [...step.outputs],
|
|
367
|
-
stageKey: step.stageKey,
|
|
368
|
-
recordsStageKey: step.recordsStageKey ?? step.stageKey,
|
|
369
|
-
recordSourceStageKey: step.recordSourceStageKey ?? step.recordsStageKey ?? step.stageKey,
|
|
370
|
-
dependencyMode: step.dependencyMode,
|
|
371
|
-
actionKey: step.actionKey,
|
|
372
|
-
defaultBatchSize: step.defaultBatchSize,
|
|
373
|
-
maxBatchSize: step.maxBatchSize
|
|
374
|
-
};
|
|
375
|
-
if (step.description) snapshotStep.description = step.description;
|
|
376
|
-
if (step.recordEntity) snapshotStep.recordEntity = step.recordEntity;
|
|
377
|
-
if (step.dependsOn?.length) snapshotStep.dependsOn = [...step.dependsOn];
|
|
378
|
-
if (step.credentialRequirements?.length) {
|
|
379
|
-
snapshotStep.credentialRequirements = step.credentialRequirements.map((requirement) => ({
|
|
380
|
-
...requirement
|
|
381
|
-
}));
|
|
382
|
-
}
|
|
383
|
-
if (step.recordColumns) {
|
|
384
|
-
snapshotStep.recordColumns = {
|
|
385
|
-
...step.recordColumns.company ? {
|
|
386
|
-
company: step.recordColumns.company.map((column) => ({ ...column }))
|
|
387
|
-
} : {},
|
|
388
|
-
...step.recordColumns.contact ? {
|
|
389
|
-
contact: step.recordColumns.contact.map((column) => ({ ...column }))
|
|
390
|
-
} : {}
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
return snapshotStep;
|
|
394
|
-
})
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
332
|
var RelativeScheduleItemSchema = z.object({
|
|
398
333
|
offset: z.string().regex(/^[+-]\d+[dhm]$/, "Invalid offset format. Use +3d, -2h, +30m, etc."),
|
|
399
334
|
payload: z.record(z.string(), z.unknown()),
|
|
@@ -651,6 +586,60 @@ z.object({
|
|
|
651
586
|
z.object({
|
|
652
587
|
ids: z.array(UuidSchema).min(1).max(500)
|
|
653
588
|
}).strict();
|
|
589
|
+
|
|
590
|
+
// ../core/src/business/acquisition/build-templates.ts
|
|
591
|
+
function getProspectingBuildTemplateOptions(templates) {
|
|
592
|
+
return templates.map(({ id, label, description }) => ({
|
|
593
|
+
id,
|
|
594
|
+
label,
|
|
595
|
+
description
|
|
596
|
+
}));
|
|
597
|
+
}
|
|
598
|
+
function createBuildPlanSnapshotFromTemplate(template) {
|
|
599
|
+
return {
|
|
600
|
+
templateId: template.id,
|
|
601
|
+
templateLabel: template.label,
|
|
602
|
+
steps: template.steps.map((step) => {
|
|
603
|
+
const snapshotStep = {
|
|
604
|
+
id: step.id,
|
|
605
|
+
label: step.label,
|
|
606
|
+
primaryEntity: step.primaryEntity,
|
|
607
|
+
outputs: [...step.outputs],
|
|
608
|
+
stageKey: step.stageKey,
|
|
609
|
+
recordsStageKey: step.recordsStageKey ?? step.stageKey,
|
|
610
|
+
recordSourceStageKey: step.recordSourceStageKey ?? step.recordsStageKey ?? step.stageKey,
|
|
611
|
+
dependencyMode: step.dependencyMode,
|
|
612
|
+
actionKey: step.actionKey,
|
|
613
|
+
defaultBatchSize: step.defaultBatchSize,
|
|
614
|
+
maxBatchSize: step.maxBatchSize
|
|
615
|
+
};
|
|
616
|
+
if (step.description) snapshotStep.description = step.description;
|
|
617
|
+
if (step.recordEntity) snapshotStep.recordEntity = step.recordEntity;
|
|
618
|
+
if (step.dependsOn?.length) snapshotStep.dependsOn = [...step.dependsOn];
|
|
619
|
+
if (step.credentialRequirements?.length) {
|
|
620
|
+
snapshotStep.credentialRequirements = step.credentialRequirements.map((requirement) => ({
|
|
621
|
+
...requirement
|
|
622
|
+
}));
|
|
623
|
+
}
|
|
624
|
+
if (step.recordColumns) {
|
|
625
|
+
snapshotStep.recordColumns = {
|
|
626
|
+
...step.recordColumns.company ? {
|
|
627
|
+
company: step.recordColumns.company.map((column) => ({ ...column }))
|
|
628
|
+
} : {},
|
|
629
|
+
...step.recordColumns.contact ? {
|
|
630
|
+
contact: step.recordColumns.contact.map((column) => ({ ...column }))
|
|
631
|
+
} : {}
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
return snapshotStep;
|
|
635
|
+
})
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function createBuildPlanSnapshotFromTemplateId(templateId, templates = []) {
|
|
639
|
+
const template = templates.find((item) => item.id === templateId);
|
|
640
|
+
if (!template) return null;
|
|
641
|
+
return createBuildPlanSnapshotFromTemplate(template);
|
|
642
|
+
}
|
|
654
643
|
z.object({
|
|
655
644
|
replyBody: z.string().trim().min(1).max(1e4)
|
|
656
645
|
}).strict();
|
|
@@ -1956,11 +1945,11 @@ function FilterBar({ children, actions }) {
|
|
|
1956
1945
|
/* @__PURE__ */ jsx(Group, { gap: "md", children: actions })
|
|
1957
1946
|
] }) });
|
|
1958
1947
|
}
|
|
1959
|
-
function TableSelectionToolbar({ selectedCount
|
|
1960
|
-
if (
|
|
1948
|
+
function TableSelectionToolbar({ selectedCount, onDelete, isDeleting }) {
|
|
1949
|
+
if (selectedCount === 0) return null;
|
|
1961
1950
|
return /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
1962
1951
|
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 600, c: "blue", children: [
|
|
1963
|
-
|
|
1952
|
+
selectedCount,
|
|
1964
1953
|
" selected"
|
|
1965
1954
|
] }),
|
|
1966
1955
|
onDelete && /* @__PURE__ */ jsx(
|
|
@@ -3449,16 +3438,190 @@ function useExecutions(resourceId, resourceStatus, limit, offset) {
|
|
|
3449
3438
|
enabled: isReady && !!resourceId
|
|
3450
3439
|
});
|
|
3451
3440
|
}
|
|
3441
|
+
var acquisitionListKeys = {
|
|
3442
|
+
all: ["acquisition-lists"],
|
|
3443
|
+
list: (organizationId) => [...acquisitionListKeys.all, organizationId],
|
|
3444
|
+
detail: (organizationId, listId) => [...acquisitionListKeys.all, organizationId, listId],
|
|
3445
|
+
telemetry: (organizationId) => [...acquisitionListKeys.all, "telemetry", organizationId],
|
|
3446
|
+
progress: (organizationId, listId) => [...acquisitionListKeys.all, "progress", organizationId, listId],
|
|
3447
|
+
executionsBase: (organizationId, listId) => [...acquisitionListKeys.all, "executions", organizationId, listId],
|
|
3448
|
+
records: (organizationId, listId, filters) => [
|
|
3449
|
+
...acquisitionListKeys.all,
|
|
3450
|
+
"records",
|
|
3451
|
+
organizationId,
|
|
3452
|
+
listId,
|
|
3453
|
+
filters.entity,
|
|
3454
|
+
filters.stage ?? null,
|
|
3455
|
+
filters.limit ?? null,
|
|
3456
|
+
filters.offset ?? null
|
|
3457
|
+
],
|
|
3458
|
+
executions: (organizationId, listId, filters) => [
|
|
3459
|
+
...acquisitionListKeys.executionsBase(organizationId, listId),
|
|
3460
|
+
filters?.resourceId ?? null,
|
|
3461
|
+
filters?.limit ?? null
|
|
3462
|
+
]
|
|
3463
|
+
};
|
|
3464
|
+
function useLists() {
|
|
3465
|
+
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3466
|
+
return useQuery({
|
|
3467
|
+
queryKey: acquisitionListKeys.list(workOSOrganizationId),
|
|
3468
|
+
queryFn: () => apiRequest("/acquisition/lists"),
|
|
3469
|
+
enabled: isReady
|
|
3470
|
+
});
|
|
3471
|
+
}
|
|
3472
|
+
function useList(listId) {
|
|
3473
|
+
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3474
|
+
return useQuery({
|
|
3475
|
+
queryKey: acquisitionListKeys.detail(workOSOrganizationId, listId),
|
|
3476
|
+
queryFn: () => apiRequest(`/acquisition/lists/${listId}`),
|
|
3477
|
+
enabled: isReady && !!listId
|
|
3478
|
+
});
|
|
3479
|
+
}
|
|
3480
|
+
function useListsTelemetry() {
|
|
3481
|
+
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3482
|
+
return useQuery({
|
|
3483
|
+
queryKey: acquisitionListKeys.telemetry(workOSOrganizationId),
|
|
3484
|
+
queryFn: () => apiRequest("/acquisition/lists/telemetry"),
|
|
3485
|
+
enabled: isReady
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
function useListProgress(listId, options = {}) {
|
|
3489
|
+
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3490
|
+
return useQuery({
|
|
3491
|
+
queryKey: acquisitionListKeys.progress(workOSOrganizationId, listId),
|
|
3492
|
+
queryFn: () => apiRequest(`/acquisition/lists/${listId}/progress`),
|
|
3493
|
+
enabled: isReady && !!listId && (options.enabled ?? true),
|
|
3494
|
+
refetchInterval: options.refetchInterval
|
|
3495
|
+
});
|
|
3496
|
+
}
|
|
3497
|
+
function useListRecords(listId, filters) {
|
|
3498
|
+
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3499
|
+
return useQuery({
|
|
3500
|
+
queryKey: acquisitionListKeys.records(workOSOrganizationId, listId, filters),
|
|
3501
|
+
queryFn: () => {
|
|
3502
|
+
const params = new URLSearchParams({
|
|
3503
|
+
entity: filters.entity,
|
|
3504
|
+
limit: String(filters.limit ?? 50),
|
|
3505
|
+
offset: String(filters.offset ?? 0)
|
|
3506
|
+
});
|
|
3507
|
+
if (filters.stage) params.set("stage", filters.stage);
|
|
3508
|
+
return apiRequest(`/acquisition/lists/${listId}/records?${params.toString()}`);
|
|
3509
|
+
},
|
|
3510
|
+
enabled: isReady && !!listId && !!filters.entity
|
|
3511
|
+
});
|
|
3512
|
+
}
|
|
3513
|
+
function useListExecutions(listId, filters = {}) {
|
|
3514
|
+
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3515
|
+
return useQuery({
|
|
3516
|
+
queryKey: acquisitionListKeys.executions(workOSOrganizationId, listId, filters),
|
|
3517
|
+
queryFn: async () => {
|
|
3518
|
+
const executions = await apiRequest(`/acquisition/lists/${listId}/executions`);
|
|
3519
|
+
const filteredExecutions = filters.resourceId ? executions.filter((execution) => execution.resourceId === filters.resourceId) : executions;
|
|
3520
|
+
return typeof filters.limit === "number" ? filteredExecutions.slice(0, filters.limit) : filteredExecutions;
|
|
3521
|
+
},
|
|
3522
|
+
enabled: isReady && !!listId
|
|
3523
|
+
});
|
|
3524
|
+
}
|
|
3525
|
+
function useCreateList() {
|
|
3526
|
+
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3527
|
+
const queryClient = useQueryClient();
|
|
3528
|
+
return useMutation({
|
|
3529
|
+
mutationFn: (body) => apiRequest("/acquisition/lists", {
|
|
3530
|
+
method: "POST",
|
|
3531
|
+
body: JSON.stringify(body)
|
|
3532
|
+
}),
|
|
3533
|
+
onSuccess: () => {
|
|
3534
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3535
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.telemetry(workOSOrganizationId) });
|
|
3536
|
+
showSuccessNotification("List created");
|
|
3537
|
+
},
|
|
3538
|
+
onError: (error) => {
|
|
3539
|
+
showApiErrorNotification(error);
|
|
3540
|
+
}
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
function useUpdateList(listId) {
|
|
3544
|
+
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3545
|
+
const queryClient = useQueryClient();
|
|
3546
|
+
return useMutation({
|
|
3547
|
+
mutationFn: (body) => apiRequest(`/acquisition/lists/${listId}`, {
|
|
3548
|
+
method: "PATCH",
|
|
3549
|
+
body: JSON.stringify(body)
|
|
3550
|
+
}),
|
|
3551
|
+
onSuccess: () => {
|
|
3552
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3553
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.detail(workOSOrganizationId, listId) });
|
|
3554
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.telemetry(workOSOrganizationId) });
|
|
3555
|
+
showSuccessNotification("List updated");
|
|
3556
|
+
},
|
|
3557
|
+
onError: (error) => {
|
|
3558
|
+
showApiErrorNotification(error);
|
|
3559
|
+
}
|
|
3560
|
+
});
|
|
3561
|
+
}
|
|
3562
|
+
function useUpdateListConfig(listId) {
|
|
3563
|
+
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3564
|
+
const queryClient = useQueryClient();
|
|
3565
|
+
return useMutation({
|
|
3566
|
+
mutationFn: (body) => apiRequest(`/acquisition/lists/${listId}/config`, {
|
|
3567
|
+
method: "PATCH",
|
|
3568
|
+
body: JSON.stringify(body)
|
|
3569
|
+
}),
|
|
3570
|
+
onSuccess: () => {
|
|
3571
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3572
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.detail(workOSOrganizationId, listId) });
|
|
3573
|
+
showSuccessNotification("List configuration saved");
|
|
3574
|
+
},
|
|
3575
|
+
onError: (error) => {
|
|
3576
|
+
showApiErrorNotification(error);
|
|
3577
|
+
}
|
|
3578
|
+
});
|
|
3579
|
+
}
|
|
3580
|
+
function useDeleteList() {
|
|
3581
|
+
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3582
|
+
const queryClient = useQueryClient();
|
|
3583
|
+
return useMutation({
|
|
3584
|
+
mutationFn: async (listId) => {
|
|
3585
|
+
await apiRequest(`/acquisition/lists/${listId}`, {
|
|
3586
|
+
method: "DELETE"
|
|
3587
|
+
});
|
|
3588
|
+
},
|
|
3589
|
+
onSuccess: () => {
|
|
3590
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3591
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.telemetry(workOSOrganizationId) });
|
|
3592
|
+
showSuccessNotification("List deleted");
|
|
3593
|
+
},
|
|
3594
|
+
onError: (error) => {
|
|
3595
|
+
showApiErrorNotification(error);
|
|
3596
|
+
}
|
|
3597
|
+
});
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3600
|
+
// src/hooks/executions/useInFlightExecutions.ts
|
|
3452
3601
|
function useInFlightExecutions(resourceId, options = {}) {
|
|
3453
3602
|
const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
|
|
3454
3603
|
const limit = options.limit ?? 20;
|
|
3455
3604
|
const offset = options.offset ?? 0;
|
|
3456
3605
|
return useQuery({
|
|
3457
|
-
queryKey: [
|
|
3458
|
-
...executionsKeys.executions(workOSOrganizationId, resourceId, "all", limit, offset),
|
|
3459
|
-
"in-flight"
|
|
3460
|
-
],
|
|
3606
|
+
queryKey: options.listId ? [...acquisitionListKeys.executions(workOSOrganizationId, options.listId, { resourceId, limit }), "in-flight"] : [...executionsKeys.executions(workOSOrganizationId, resourceId, "all", limit, offset), "in-flight"],
|
|
3461
3607
|
queryFn: async () => {
|
|
3608
|
+
if (options.listId) {
|
|
3609
|
+
const executions2 = await apiRequest(
|
|
3610
|
+
`/acquisition/lists/${options.listId}/executions`
|
|
3611
|
+
);
|
|
3612
|
+
const runningExecutions = executions2.filter((execution) => execution.resourceId === resourceId && execution.status === "running").slice(0, limit);
|
|
3613
|
+
return {
|
|
3614
|
+
executions: runningExecutions.map((execution) => ({
|
|
3615
|
+
id: execution.executionId,
|
|
3616
|
+
status: "running",
|
|
3617
|
+
startTime: new Date(execution.createdAt).getTime()
|
|
3618
|
+
})),
|
|
3619
|
+
total: runningExecutions.length,
|
|
3620
|
+
limit,
|
|
3621
|
+
offset,
|
|
3622
|
+
hasMore: false
|
|
3623
|
+
};
|
|
3624
|
+
}
|
|
3462
3625
|
const params = new URLSearchParams({
|
|
3463
3626
|
limit: String(limit),
|
|
3464
3627
|
offset: String(offset)
|
|
@@ -3494,11 +3657,21 @@ function useExecuteAsync() {
|
|
|
3494
3657
|
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3495
3658
|
const queryClient = useQueryClient();
|
|
3496
3659
|
return useMutation({
|
|
3497
|
-
mutationFn: async ({ resourceId, resourceType, input }) => {
|
|
3660
|
+
mutationFn: async ({ resourceId, resourceType, input, listId }) => {
|
|
3498
3661
|
const response = await apiRequest("/execution-engine/execute-async", {
|
|
3499
3662
|
method: "POST",
|
|
3500
3663
|
body: JSON.stringify({ resourceType, resourceId, input })
|
|
3501
3664
|
});
|
|
3665
|
+
if (listId) {
|
|
3666
|
+
try {
|
|
3667
|
+
await apiRequest(`/acquisition/lists/${listId}/executions`, {
|
|
3668
|
+
method: "POST",
|
|
3669
|
+
body: JSON.stringify({ executionId: response.executionId })
|
|
3670
|
+
});
|
|
3671
|
+
} catch (error) {
|
|
3672
|
+
console.warn("Failed to attach execution to list history", error);
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3502
3675
|
return { ...response, resourceId };
|
|
3503
3676
|
},
|
|
3504
3677
|
onSuccess: (data) => {
|
|
@@ -3508,166 +3681,6 @@ function useExecuteAsync() {
|
|
|
3508
3681
|
}
|
|
3509
3682
|
});
|
|
3510
3683
|
}
|
|
3511
|
-
var acquisitionListKeys = {
|
|
3512
|
-
all: ["acquisition-lists"],
|
|
3513
|
-
list: (organizationId) => [...acquisitionListKeys.all, organizationId],
|
|
3514
|
-
detail: (organizationId, listId) => [...acquisitionListKeys.all, organizationId, listId],
|
|
3515
|
-
telemetry: (organizationId) => [...acquisitionListKeys.all, "telemetry", organizationId],
|
|
3516
|
-
progress: (organizationId, listId) => [...acquisitionListKeys.all, "progress", organizationId, listId],
|
|
3517
|
-
records: (organizationId, listId, filters) => [
|
|
3518
|
-
...acquisitionListKeys.all,
|
|
3519
|
-
"records",
|
|
3520
|
-
organizationId,
|
|
3521
|
-
listId,
|
|
3522
|
-
filters.entity,
|
|
3523
|
-
filters.stage ?? null,
|
|
3524
|
-
filters.limit ?? null,
|
|
3525
|
-
filters.offset ?? null
|
|
3526
|
-
],
|
|
3527
|
-
executions: (organizationId, listId, filters) => [
|
|
3528
|
-
...acquisitionListKeys.all,
|
|
3529
|
-
"executions",
|
|
3530
|
-
organizationId,
|
|
3531
|
-
listId,
|
|
3532
|
-
filters?.resourceId ?? null,
|
|
3533
|
-
filters?.limit ?? null
|
|
3534
|
-
]
|
|
3535
|
-
};
|
|
3536
|
-
function useLists() {
|
|
3537
|
-
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3538
|
-
return useQuery({
|
|
3539
|
-
queryKey: acquisitionListKeys.list(workOSOrganizationId),
|
|
3540
|
-
queryFn: () => apiRequest("/acquisition/lists"),
|
|
3541
|
-
enabled: isReady
|
|
3542
|
-
});
|
|
3543
|
-
}
|
|
3544
|
-
function useList(listId) {
|
|
3545
|
-
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3546
|
-
return useQuery({
|
|
3547
|
-
queryKey: acquisitionListKeys.detail(workOSOrganizationId, listId),
|
|
3548
|
-
queryFn: () => apiRequest(`/acquisition/lists/${listId}`),
|
|
3549
|
-
enabled: isReady && !!listId
|
|
3550
|
-
});
|
|
3551
|
-
}
|
|
3552
|
-
function useListsTelemetry() {
|
|
3553
|
-
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3554
|
-
return useQuery({
|
|
3555
|
-
queryKey: acquisitionListKeys.telemetry(workOSOrganizationId),
|
|
3556
|
-
queryFn: () => apiRequest("/acquisition/lists/telemetry"),
|
|
3557
|
-
enabled: isReady
|
|
3558
|
-
});
|
|
3559
|
-
}
|
|
3560
|
-
function useListProgress(listId, options = {}) {
|
|
3561
|
-
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3562
|
-
return useQuery({
|
|
3563
|
-
queryKey: acquisitionListKeys.progress(workOSOrganizationId, listId),
|
|
3564
|
-
queryFn: () => apiRequest(`/acquisition/lists/${listId}/progress`),
|
|
3565
|
-
enabled: isReady && !!listId && (options.enabled ?? true),
|
|
3566
|
-
refetchInterval: options.refetchInterval
|
|
3567
|
-
});
|
|
3568
|
-
}
|
|
3569
|
-
function useListRecords(listId, filters) {
|
|
3570
|
-
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3571
|
-
return useQuery({
|
|
3572
|
-
queryKey: acquisitionListKeys.records(workOSOrganizationId, listId, filters),
|
|
3573
|
-
queryFn: () => {
|
|
3574
|
-
const params = new URLSearchParams({
|
|
3575
|
-
entity: filters.entity,
|
|
3576
|
-
limit: String(filters.limit ?? 50),
|
|
3577
|
-
offset: String(filters.offset ?? 0)
|
|
3578
|
-
});
|
|
3579
|
-
if (filters.stage) params.set("stage", filters.stage);
|
|
3580
|
-
return apiRequest(`/acquisition/lists/${listId}/records?${params.toString()}`);
|
|
3581
|
-
},
|
|
3582
|
-
enabled: isReady && !!listId && !!filters.entity
|
|
3583
|
-
});
|
|
3584
|
-
}
|
|
3585
|
-
function useListExecutions(listId, filters = {}) {
|
|
3586
|
-
const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
|
|
3587
|
-
return useQuery({
|
|
3588
|
-
queryKey: acquisitionListKeys.executions(workOSOrganizationId, listId, filters),
|
|
3589
|
-
queryFn: async () => {
|
|
3590
|
-
const executions = await apiRequest(`/acquisition/lists/${listId}/executions`);
|
|
3591
|
-
const filteredExecutions = filters.resourceId ? executions.filter((execution) => execution.resourceId === filters.resourceId) : executions;
|
|
3592
|
-
return typeof filters.limit === "number" ? filteredExecutions.slice(0, filters.limit) : filteredExecutions;
|
|
3593
|
-
},
|
|
3594
|
-
enabled: isReady && !!listId
|
|
3595
|
-
});
|
|
3596
|
-
}
|
|
3597
|
-
function useCreateList() {
|
|
3598
|
-
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3599
|
-
const queryClient = useQueryClient();
|
|
3600
|
-
return useMutation({
|
|
3601
|
-
mutationFn: (body) => apiRequest("/acquisition/lists", {
|
|
3602
|
-
method: "POST",
|
|
3603
|
-
body: JSON.stringify(body)
|
|
3604
|
-
}),
|
|
3605
|
-
onSuccess: () => {
|
|
3606
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3607
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.telemetry(workOSOrganizationId) });
|
|
3608
|
-
showSuccessNotification("List created");
|
|
3609
|
-
},
|
|
3610
|
-
onError: (error) => {
|
|
3611
|
-
showApiErrorNotification(error);
|
|
3612
|
-
}
|
|
3613
|
-
});
|
|
3614
|
-
}
|
|
3615
|
-
function useUpdateList(listId) {
|
|
3616
|
-
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3617
|
-
const queryClient = useQueryClient();
|
|
3618
|
-
return useMutation({
|
|
3619
|
-
mutationFn: (body) => apiRequest(`/acquisition/lists/${listId}`, {
|
|
3620
|
-
method: "PATCH",
|
|
3621
|
-
body: JSON.stringify(body)
|
|
3622
|
-
}),
|
|
3623
|
-
onSuccess: () => {
|
|
3624
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3625
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.detail(workOSOrganizationId, listId) });
|
|
3626
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.telemetry(workOSOrganizationId) });
|
|
3627
|
-
showSuccessNotification("List updated");
|
|
3628
|
-
},
|
|
3629
|
-
onError: (error) => {
|
|
3630
|
-
showApiErrorNotification(error);
|
|
3631
|
-
}
|
|
3632
|
-
});
|
|
3633
|
-
}
|
|
3634
|
-
function useUpdateListConfig(listId) {
|
|
3635
|
-
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3636
|
-
const queryClient = useQueryClient();
|
|
3637
|
-
return useMutation({
|
|
3638
|
-
mutationFn: (body) => apiRequest(`/acquisition/lists/${listId}/config`, {
|
|
3639
|
-
method: "PATCH",
|
|
3640
|
-
body: JSON.stringify(body)
|
|
3641
|
-
}),
|
|
3642
|
-
onSuccess: () => {
|
|
3643
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3644
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.detail(workOSOrganizationId, listId) });
|
|
3645
|
-
showSuccessNotification("List configuration saved");
|
|
3646
|
-
},
|
|
3647
|
-
onError: (error) => {
|
|
3648
|
-
showApiErrorNotification(error);
|
|
3649
|
-
}
|
|
3650
|
-
});
|
|
3651
|
-
}
|
|
3652
|
-
function useDeleteList() {
|
|
3653
|
-
const { apiRequest, workOSOrganizationId } = useElevasisServices();
|
|
3654
|
-
const queryClient = useQueryClient();
|
|
3655
|
-
return useMutation({
|
|
3656
|
-
mutationFn: (listId) => apiRequest(`/acquisition/lists/${listId}`, {
|
|
3657
|
-
method: "DELETE"
|
|
3658
|
-
}),
|
|
3659
|
-
onSuccess: () => {
|
|
3660
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.list(workOSOrganizationId) });
|
|
3661
|
-
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.telemetry(workOSOrganizationId) });
|
|
3662
|
-
showSuccessNotification("List deleted");
|
|
3663
|
-
},
|
|
3664
|
-
onError: (error) => {
|
|
3665
|
-
showApiErrorNotification(error);
|
|
3666
|
-
}
|
|
3667
|
-
});
|
|
3668
|
-
}
|
|
3669
|
-
|
|
3670
|
-
// src/hooks/executions/useWorkflowExecution.ts
|
|
3671
3684
|
function useWorkflowExecution({ workflowId, listId }) {
|
|
3672
3685
|
const mutation = useExecuteAsync();
|
|
3673
3686
|
const queryClient = useQueryClient();
|
|
@@ -3677,14 +3690,15 @@ function useWorkflowExecution({ workflowId, listId }) {
|
|
|
3677
3690
|
const result = await mutation.mutateAsync({
|
|
3678
3691
|
resourceId: workflowId,
|
|
3679
3692
|
resourceType: "workflow",
|
|
3680
|
-
input
|
|
3693
|
+
input,
|
|
3694
|
+
listId
|
|
3681
3695
|
});
|
|
3682
3696
|
queryClient.invalidateQueries({
|
|
3683
3697
|
queryKey: executionsKeys.executionsListBase(workOSOrganizationId, workflowId)
|
|
3684
3698
|
});
|
|
3685
3699
|
if (listId) {
|
|
3686
3700
|
queryClient.invalidateQueries({
|
|
3687
|
-
queryKey: acquisitionListKeys.
|
|
3701
|
+
queryKey: acquisitionListKeys.executionsBase(workOSOrganizationId, listId)
|
|
3688
3702
|
});
|
|
3689
3703
|
}
|
|
3690
3704
|
return result;
|
|
@@ -4101,7 +4115,7 @@ function useExecutionSSE(resourceId, options = {}) {
|
|
|
4101
4115
|
});
|
|
4102
4116
|
if (listId) {
|
|
4103
4117
|
queryClient.invalidateQueries({
|
|
4104
|
-
queryKey: acquisitionListKeys.
|
|
4118
|
+
queryKey: acquisitionListKeys.executionsBase(workOSOrganizationId, listId)
|
|
4105
4119
|
});
|
|
4106
4120
|
queryClient.invalidateQueries({
|
|
4107
4121
|
queryKey: acquisitionListKeys.progress(workOSOrganizationId, listId)
|
|
@@ -6725,7 +6739,8 @@ function useCompanies(filters = {}) {
|
|
|
6725
6739
|
});
|
|
6726
6740
|
return apiRequest(`/acquisition/companies${queryString}`);
|
|
6727
6741
|
},
|
|
6728
|
-
enabled: isReady && !!workOSOrganizationId
|
|
6742
|
+
enabled: isReady && !!workOSOrganizationId,
|
|
6743
|
+
retry: (_failureCount, error) => !(error instanceof APIClientError && error.statusCode === 401)
|
|
6729
6744
|
});
|
|
6730
6745
|
}
|
|
6731
6746
|
function useCompanyFacets() {
|
|
@@ -6883,7 +6898,8 @@ function useContacts(filters = {}) {
|
|
|
6883
6898
|
});
|
|
6884
6899
|
return apiRequest(`/acquisition/contacts${queryString}`);
|
|
6885
6900
|
},
|
|
6886
|
-
enabled: isReady && !!workOSOrganizationId
|
|
6901
|
+
enabled: isReady && !!workOSOrganizationId,
|
|
6902
|
+
retry: (_failureCount, error) => !(error instanceof APIClientError && error.statusCode === 401)
|
|
6887
6903
|
});
|
|
6888
6904
|
}
|
|
6889
6905
|
function useContact(contactId) {
|
|
@@ -7304,7 +7320,8 @@ function useCredentials() {
|
|
|
7304
7320
|
const service = new CredentialService(apiRequest);
|
|
7305
7321
|
return await service.listCredentials();
|
|
7306
7322
|
},
|
|
7307
|
-
enabled: isReady
|
|
7323
|
+
enabled: isReady && Boolean(workOSOrganizationId),
|
|
7324
|
+
retry: false
|
|
7308
7325
|
});
|
|
7309
7326
|
}
|
|
7310
7327
|
function useVerifyCredential() {
|
|
@@ -7653,6 +7670,7 @@ function useUpdateMemberConfig() {
|
|
|
7653
7670
|
const { apiRequest } = useElevasisServices();
|
|
7654
7671
|
const adapter = useNotificationAdapter();
|
|
7655
7672
|
const queryClient = useQueryClient();
|
|
7673
|
+
const { retry: refreshOrganizations } = useOrganization();
|
|
7656
7674
|
return useMutation({
|
|
7657
7675
|
mutationFn: async ({ membershipId, config }) => {
|
|
7658
7676
|
return apiRequest(`/memberships/${membershipId}/config`, {
|
|
@@ -7660,8 +7678,9 @@ function useUpdateMemberConfig() {
|
|
|
7660
7678
|
body: JSON.stringify({ config })
|
|
7661
7679
|
});
|
|
7662
7680
|
},
|
|
7663
|
-
onSuccess: () => {
|
|
7681
|
+
onSuccess: async () => {
|
|
7664
7682
|
queryClient.invalidateQueries({ queryKey: ["memberships"] });
|
|
7683
|
+
await refreshOrganizations();
|
|
7665
7684
|
notifications.show({
|
|
7666
7685
|
title: "Success",
|
|
7667
7686
|
message: "Member config updated",
|
|
@@ -10883,6 +10902,27 @@ function renderField(field, form, disabled, jsonState, setJsonState) {
|
|
|
10883
10902
|
const description = field.description;
|
|
10884
10903
|
const placeholder = field.placeholder;
|
|
10885
10904
|
switch (field.component) {
|
|
10905
|
+
case "checkboxgroup":
|
|
10906
|
+
return /* @__PURE__ */ jsx(
|
|
10907
|
+
Checkbox.Group,
|
|
10908
|
+
{
|
|
10909
|
+
label,
|
|
10910
|
+
description,
|
|
10911
|
+
value: inputProps.value ?? [],
|
|
10912
|
+
onChange: (val) => form.setFieldValue(field.path, val),
|
|
10913
|
+
error: inputProps.error,
|
|
10914
|
+
children: /* @__PURE__ */ jsx(Stack, { gap: 6, mt: "xs", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsx(
|
|
10915
|
+
Checkbox,
|
|
10916
|
+
{
|
|
10917
|
+
value: option.value,
|
|
10918
|
+
label: option.label,
|
|
10919
|
+
disabled
|
|
10920
|
+
},
|
|
10921
|
+
option.value
|
|
10922
|
+
)) })
|
|
10923
|
+
},
|
|
10924
|
+
field.path
|
|
10925
|
+
);
|
|
10886
10926
|
case "segmented": {
|
|
10887
10927
|
const options = field.options ?? [];
|
|
10888
10928
|
return /* @__PURE__ */ jsx(
|
|
@@ -15850,7 +15890,7 @@ var mdxKnowledgeNodes = [
|
|
|
15850
15890
|
"title": "New Vertical Launch Playbook",
|
|
15851
15891
|
"summary": "Zero-to-first-campaign workflow for launching a new acquisition vertical: batch definition, tracker setup, lead generation stages, campaign launch, and monitoring.",
|
|
15852
15892
|
"icon": "playbook",
|
|
15853
|
-
"body": '## Overview\n\nUse this playbook when launching a new acquisition vertical from zero to first campaign. A vertical launch turns an audience hypothesis such as independent dental practices, auto repair shops, or bookkeeping firms into a tracked lead generation batch, qualified contacts, a draft Instantly campaign, and an active monitoring loop.\n\nThe workflow has five phases:\n\n1. Define the batch and qualification rules.\n2. Create the batch tracker.\n3. Run the lead generation pipeline.\n4. Launch the outreach campaign.\n5. Monitor replies and campaign quality.\n\n## Define the Batch\n\nChoose a batch ID using the acquisition naming convention: `{vertical}-{number}`, for example `dental-1`, `auto-1`, or `home-1`.\n\nRecord the batch configuration in the tracker before running pipeline stages. At minimum, capture:\n\n- Target description, such as "independent dental practices in Orange County, California".\n- Search queries for the initial source pull.\n- Region: county, state, country, or other geography accepted by the scraper workflow.\n- Minimum review count and minimum rating, when Google Maps quality thresholds matter.\n- Custom disqualification rules, such as excluding chains, franchises, pediatric-only practices, or irrelevant subcategories.\n- Website crawl keywords, such as `about`, `team`, `staff`, `contact`, `services`, or vertical-specific service pages.\n\nUse `packages/elevasis-operations/src/sales/prospecting/constants.ts` as the batch registry. Current launch work should keep the tracker as the human-readable source and pass qualification criteria through the workflow input, list qualification metadata, or the registered batch config for the stage being run.\n\n## Create the Batch Tracker\n\nCreate a tracker from the acquisition batch template:\n\n```text\napps/docs/content/docs/operations/client-acquisition/outreach/batches/_template.mdx\n```\n\nPlace the new tracker in the pending batch directory:\n\n```text\napps/docs/content/docs/operations/client-acquisition/outreach/batches/pending/{batch-id}.mdx\n```\n\nFill in the frontmatter with `status: in-progress`, then complete the batch configuration table before running pipeline work. The tracker should make it possible to reconstruct the vertical, region, search inputs, disqualification rules, and campaign state without reading execution logs.\n\n## Run Lead Generation\n\nRun the lead generation stages with the platform CLI from the monorepo root so `.env.development` and `.env.production` resolve correctly.\n\n### Stage 01: Google Maps Scrape\n\nUse the Google Maps scrape workflow to acquire initial companies:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-01a-google-maps-scrape-workflow --input \'{"searchQueries":["dentist","dental clinic"],"county":"Orange County","state":"California"}\' --async\n```\n\nAfter the execution starts, record the execution ID and source counts in the batch tracker.\n\n### Local Website Crawl\n\nRun the local website crawler against the batch:\n\n```bash\npnpm -C scripts/web-scraper run crawl -- {batch-id}\n```\n\nThe crawl should capture relevant sub-pages for LLM extraction. If vertical-specific keywords are not available in the active code path, use the default crawl coverage and note any manual crawl gaps in the tracker before extraction.\n\n### Stage 02: Website Extract\n\nExtract structured company profile data from crawl output:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-02-website-extract-workflow --input \'{"batchId":"{batch-id}"}\' --async\n```\n\n### Stage 03: Company Qualification\n\nQualify companies using the target description, review thresholds, rating thresholds, and custom rules captured in the tracker. If the workflow does not resolve criteria automatically for the batch, pass the criteria explicitly in the input or attach them through the list qualification surface before running the stage.\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-03-company-qualification-workflow --input \'{"batchId":"{batch-id}","criteria":{"targetDescription":"Independent dental practices in Orange County, California","minimumReviewCount":5,"minimumRating":3,"customRules":"Disqualify franchises and chains. Disqualify orthodontics-only and pediatric-only practices."}}\' --async\n```\n\nFor list-oriented runs, use `listId` instead of `batchId`; list configuration takes priority over the batch registry unless an explicit `criteria` override is provided.\n\n### Stage 04: Email Discovery\n\nDiscover contacts for qualified companies:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-04-email-discovery-workflow --input \'{"batchId":"{batch-id}"}\' --async\n```\n\n### Stage 05: Email Verification\n\nVerify discovered emails before campaign upload:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-05-email-verification-workflow --input \'{"batchId":"{batch-id}"}\' --async\n```\n\nWhen verification completes, update the tracker with company counts, contact counts, usable email counts, and set the batch status to `ready` if campaign launch prerequisites are satisfied.\n\n## Launch the Campaign\n\nUse the acquisition outreach workflow to move a ready batch into Instantly:\n\n1. Check account inventory with `ist-account-inventory-workflow`.\n2. Personalize contacts with `ist-personalization-workflow`.\n3. Create a draft campaign with `ist-campaign-create-workflow` and `activate: false`.\n4. Create the tracking list with `ist-campaign-list-workflow`.\n5. Upload contacts with `ist-upload-workflow`, dry run first and then real.\n6. Activate with `ist-campaign-activate-workflow`.\n7. Update the tracker to `status: active` and fill in campaign metadata.\n\nKeep the first campaign small enough to evaluate copy and deliverability. Prefer 100-200 contacts per segment, 1-2 contacts per company, and conservative sending volume until benchmarks are visible.\n\n## Monitor and Optimize\n\nAfter launch, monitor both campaign metrics and inbound replies:\n\n- Use `/acquisition --outreach` for campaign review and analytics.\n- Use `/acquisition --inbound status` for reply handling and active deal state.\n- Watch open rate, reply rate, positive reply rate, and bounce rate.\n- Pause or repair the campaign if bounce rate rises above the accepted threshold.\n- Rework subject lines, personalization, or offer framing when reply rate is below target.\n\nEvery optimization pass should write back to the tracker: what changed, why it changed, and what result would justify scaling the vertical.\n\n## Launch Checklist\n\n- Batch ID selected with `{vertical}-{number}` naming.\n- Batch tracker created from the template.\n- Target description, geography, search queries, thresholds, and custom rules recorded.\n- Stage 01 scrape execution complete.\n- Website crawl complete or crawl gaps documented.\n- Stage 02 extraction complete.\n- Stage 03 qualification complete with explicit criteria source.\n- Stage 04 email discovery complete.\n- Stage 05 email verification complete.\n- Tracker status set to `ready`.\n- Draft Instantly campaign created.\n- Tracking list created and contacts uploaded.\n- Campaign activated.\n- Tracker status set to `active` with campaign metadata.',
|
|
15893
|
+
"body": '## Overview\n\nUse this playbook when launching a new acquisition vertical from zero to first campaign. A vertical launch turns an audience hypothesis such as independent dental practices, auto repair shops, or bookkeeping firms into a tracked lead generation batch, qualified contacts, a draft Instantly campaign, and an active monitoring loop.\n\nThe workflow has five phases:\n\n1. Define the batch and qualification rules.\n2. Create the batch tracker.\n3. Run the lead generation pipeline.\n4. Launch the outreach campaign.\n5. Monitor replies and campaign quality.\n\n## Define the Batch\n\nChoose a batch ID using the acquisition naming convention: `{vertical}-{number}`, for example `dental-1`, `auto-1`, or `home-1`.\n\nRecord the batch configuration in the tracker before running pipeline stages. At minimum, capture:\n\n- Target description, such as "independent dental practices in Orange County, California".\n- Search queries for the initial source pull.\n- Region: county, state, country, or other geography accepted by the scraper workflow.\n- Minimum review count and minimum rating, when Google Maps quality thresholds matter.\n- Custom disqualification rules, such as excluding chains, franchises, pediatric-only practices, or irrelevant subcategories.\n- Website crawl keywords, such as `about`, `team`, `staff`, `contact`, `services`, or vertical-specific service pages.\n\nUse `packages/elevasis-operations/src/sales/prospecting/constants.ts` as the batch registry. Current launch work should keep the tracker as the human-readable source and pass qualification criteria through the workflow input, list qualification metadata, or the registered batch config for the stage being run.\n\n## Create the Batch Tracker\n\nCreate a tracker from the acquisition batch template:\n\n```text\napps/docs/content/docs/operations/client-acquisition/outreach/batches/_template.mdx\n```\n\nPlace the new tracker in the pending batch directory:\n\n```text\napps/docs/content/docs/operations/client-acquisition/outreach/batches/pending/{batch-id}.mdx\n```\n\nFill in the frontmatter with `status: in-progress`, then complete the batch configuration table before running pipeline work. The tracker should make it possible to reconstruct the vertical, region, search inputs, disqualification rules, and campaign state without reading execution logs.\n\n## Run Lead Generation\n\nRun the lead generation stages with the platform CLI from the monorepo root so `.env.development` and `.env.production` resolve correctly.\n\n### Stage 01: Google Maps Scrape\n\nUse the Google Maps scrape workflow to acquire initial companies:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-01a-google-maps-scrape-workflow --input \'{"searchQueries":["dentist","dental clinic"],"county":"Orange County","state":"California"}\' --async\n```\n\nAfter the execution starts, record the execution ID and source counts in the batch tracker.\n\n### Local Website Crawl\n\nRun the local website crawler against the batch:\n\n```bash\npnpm -C scripts/web-scraper run crawl -- {batch-id}\n```\n\nThe crawl should capture relevant sub-pages for LLM extraction. If vertical-specific keywords are not available in the active code path, use the default crawl coverage and note any manual crawl gaps in the tracker before extraction.\n\n### Stage 02: Website Extract\n\nExtract structured company profile data from crawl output:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-02-website-extract-workflow --input \'{"batchId":"{batch-id}"}\' --async\n```\n\n### Stage 03: Company Qualification\n\nQualify companies using the target description, review thresholds, rating thresholds, and custom rules captured in the tracker. If the workflow does not resolve criteria automatically for the batch, pass the criteria explicitly in the input or attach them through the list qualification surface before running the stage.\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-03-company-qualification-workflow --input \'{"batchId":"{batch-id}","criteria":{"targetDescription":"Independent dental practices in Orange County, California","minimumReviewCount":5,"minimumRating":3,"customRules":"Disqualify franchises and chains. Disqualify orthodontics-only and pediatric-only practices."}}\' --async\n```\n\nFor list-oriented runs, use `listId` instead of `batchId`; list configuration takes priority over the batch registry unless an explicit `criteria` override is provided.\n\n### Stage 04: Email Discovery\n\nDiscover contacts for qualified companies:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-04-email-discovery-workflow --input \'{"batchId":"{batch-id}"}\' --async\n```\n\n### Stage 05: Email Verification\n\nVerify discovered emails before campaign upload:\n\n```bash\npnpm exec elevasis exec Elevasis/lgn-05-email-verification-workflow --input \'{"batchId":"{batch-id}"}\' --async\n```\n\nWhen verification completes, update the tracker with company counts, contact counts, usable email counts, and set the batch status to `ready` if campaign launch prerequisites are satisfied.\n\n## Launch the Campaign\n\nUse the acquisition outreach workflow to move a ready batch into Instantly:\n\n1. Check account inventory with `ist-account-inventory-workflow`.\n2. Personalize contacts with `ist-personalization-workflow`.\n3. Create a draft campaign with `ist-campaign-create-workflow` and `activate: false`.\n4. Create the tracking list with `ist-campaign-list-workflow`.\n5. Upload contacts with `ist-upload-contacts-workflow`, dry run first and then real.\n6. Activate with `ist-campaign-activate-workflow`.\n7. Update the tracker to `status: active` and fill in campaign metadata.\n\nKeep the first campaign small enough to evaluate copy and deliverability. Prefer 100-200 contacts per segment, 1-2 contacts per company, and conservative sending volume until benchmarks are visible.\n\n## Monitor and Optimize\n\nAfter launch, monitor both campaign metrics and inbound replies:\n\n- Use `/acquisition --outreach` for campaign review and analytics.\n- Use `/acquisition --inbound status` for reply handling and active deal state.\n- Watch open rate, reply rate, positive reply rate, and bounce rate.\n- Pause or repair the campaign if bounce rate rises above the accepted threshold.\n- Rework subject lines, personalization, or offer framing when reply rate is below target.\n\nEvery optimization pass should write back to the tracker: what changed, why it changed, and what result would justify scaling the vertical.\n\n## Launch Checklist\n\n- Batch ID selected with `{vertical}-{number}` naming.\n- Batch tracker created from the template.\n- Target description, geography, search queries, thresholds, and custom rules recorded.\n- Stage 01 scrape execution complete.\n- Website crawl complete or crawl gaps documented.\n- Stage 02 extraction complete.\n- Stage 03 qualification complete with explicit criteria source.\n- Stage 04 email discovery complete.\n- Stage 05 email verification complete.\n- Tracker status set to `ready`.\n- Draft Instantly campaign created.\n- Tracking list created and contacts uploaded.\n- Campaign activated.\n- Tracker status set to `active` with campaign metadata.',
|
|
15854
15894
|
"links": [
|
|
15855
15895
|
{
|
|
15856
15896
|
"target": {
|
|
@@ -16411,7 +16451,7 @@ Advanced personalization doubles reply rates: ~18% vs ~9% for generic.
|
|
|
16411
16451
|
icon: "playbook",
|
|
16412
16452
|
title: "Lead-Gen Playbook",
|
|
16413
16453
|
summary: "Empirical benchmarks, threshold guidance, provider economics, and codified learnings from 3 completed batches of the lead-gen pipeline.",
|
|
16414
|
-
body: "## Performance Benchmarks\n\nPer-stage success rates across the 3 completed Orange County batches (vet-1, auto-1, home-1).\n\n### Stage 1: Scrape (Raw to Filtered)\n\n| Metric | vet-1 | auto-1 | home-1 | Benchmark |\n| --- | --- | --- | --- | --- |\n| Raw results | 480 | 800 | 1000 | -- |\n| Companies created | 393 | 566 | 701 | -- |\n| Active in DB | 322 | 428 | 640 | -- |\n\n### Stage 3: Company Qualification Rate\n\n| Metric | vet-1 | auto-1 | home-1 | Benchmark |\n| --- | --- | --- | --- | --- |\n| Qualified | 213 (76%) | 284 (79%) | 326 (60%) | 60-80% |\n| Disqualified | 66 (24%) | 74 (21%) | 222 (40%) | 20-40% |\n\n### Stage 5: Email Verification\n\nVALID rate: ~33-41% of discovered emails across batches. Target bounce rate \\<2%.\n\n## Model Selection\n\nUse Gemini Flash models for high-volume qualification steps (cost/quality balance). Use GPT for personalization where quality matters most.\n\n## Provider Economics\n\nTomba domain search provides the best cost-per-verified-contact for local SMBs. Dual-verify (Tomba + Mails.so) catches most false positives.\n\n## Pipeline Stages\n\n1. Scrape (Google Maps via Apify)\n2. LLM Extract (website crawl \xE2\u2020\u2019 structured data)\n3. Company Qualification (LLM ICP scoring)\n4. Email Discovery (Tomba domain search)\n5. Email Verification (Mails.so)\n6. Opening Line Generation (ist-personalization-workflow)\n7. Campaign Upload (ist-upload-workflow)",
|
|
16454
|
+
body: "## Performance Benchmarks\n\nPer-stage success rates across the 3 completed Orange County batches (vet-1, auto-1, home-1).\n\n### Stage 1: Scrape (Raw to Filtered)\n\n| Metric | vet-1 | auto-1 | home-1 | Benchmark |\n| --- | --- | --- | --- | --- |\n| Raw results | 480 | 800 | 1000 | -- |\n| Companies created | 393 | 566 | 701 | -- |\n| Active in DB | 322 | 428 | 640 | -- |\n\n### Stage 3: Company Qualification Rate\n\n| Metric | vet-1 | auto-1 | home-1 | Benchmark |\n| --- | --- | --- | --- | --- |\n| Qualified | 213 (76%) | 284 (79%) | 326 (60%) | 60-80% |\n| Disqualified | 66 (24%) | 74 (21%) | 222 (40%) | 20-40% |\n\n### Stage 5: Email Verification\n\nVALID rate: ~33-41% of discovered emails across batches. Target bounce rate \\<2%.\n\n## Model Selection\n\nUse Gemini Flash models for high-volume qualification steps (cost/quality balance). Use GPT for personalization where quality matters most.\n\n## Provider Economics\n\nTomba domain search provides the best cost-per-verified-contact for local SMBs. Dual-verify (Tomba + Mails.so) catches most false positives.\n\n## Pipeline Stages\n\n1. Scrape (Google Maps via Apify)\n2. LLM Extract (website crawl \xE2\u2020\u2019 structured data)\n3. Company Qualification (LLM ICP scoring)\n4. Email Discovery (Tomba domain search)\n5. Email Verification (Mails.so)\n6. Opening Line Generation (ist-personalization-workflow)\n7. Campaign Upload (ist-upload-contacts-workflow)",
|
|
16415
16455
|
links: [{ nodeId: "system:sales.lead-gen" }],
|
|
16416
16456
|
ownerIds: [],
|
|
16417
16457
|
updatedAt: "2026-05-02"
|
|
@@ -18619,12 +18659,7 @@ var LEAD_GEN_ACTION_ENTRY_INPUTS = [
|
|
|
18619
18659
|
knowledge: []
|
|
18620
18660
|
}
|
|
18621
18661
|
];
|
|
18622
|
-
var LEAD_GEN_ACTION_ENTRIES =
|
|
18623
|
-
LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
|
|
18624
|
-
const parsed = ActionSchema.parse(action);
|
|
18625
|
-
return [parsed.id, parsed];
|
|
18626
|
-
})
|
|
18627
|
-
);
|
|
18662
|
+
var LEAD_GEN_ACTION_ENTRIES = defineActions(LEAD_GEN_ACTION_ENTRY_INPUTS);
|
|
18628
18663
|
var CRM_ACTION_ENTRY_INPUTS = [
|
|
18629
18664
|
{
|
|
18630
18665
|
id: "send_reply",
|
|
@@ -18735,12 +18770,7 @@ var CRM_ACTION_ENTRY_INPUTS = [
|
|
|
18735
18770
|
knowledge: []
|
|
18736
18771
|
}
|
|
18737
18772
|
];
|
|
18738
|
-
var CRM_ACTION_ENTRIES =
|
|
18739
|
-
CRM_ACTION_ENTRY_INPUTS.map((action) => {
|
|
18740
|
-
const parsed = ActionSchema.parse(action);
|
|
18741
|
-
return [parsed.id, parsed];
|
|
18742
|
-
})
|
|
18743
|
-
);
|
|
18773
|
+
var CRM_ACTION_ENTRIES = defineActions(CRM_ACTION_ENTRY_INPUTS);
|
|
18744
18774
|
var ELEVASIS_DEFAULT_ORGANIZATION_MODEL_ACTIONS = {
|
|
18745
18775
|
...LEAD_GEN_ACTION_ENTRIES,
|
|
18746
18776
|
...CRM_ACTION_ENTRIES
|
|
@@ -18867,7 +18897,7 @@ var platformSystems = {
|
|
|
18867
18897
|
surfaces: []
|
|
18868
18898
|
},
|
|
18869
18899
|
config: {
|
|
18870
|
-
defaultBuildTemplateId: "
|
|
18900
|
+
defaultBuildTemplateId: "local-services",
|
|
18871
18901
|
defaultCompanyStageCatalogId: "sales.lead-gen:catalog/company-stage",
|
|
18872
18902
|
defaultContactStageCatalogId: "sales.lead-gen:catalog/contact-stage",
|
|
18873
18903
|
listBoard: {
|
|
@@ -19972,92 +20002,6 @@ for (const resource2 of Object.values(canonicalOrganizationModel.resources)) {
|
|
|
19972
20002
|
projectOrganizationSurfaces(canonicalOrganizationModel);
|
|
19973
20003
|
({
|
|
19974
20004
|
...canonicalOrganizationModel});
|
|
19975
|
-
var PROSPECTING_STEPS2 = {
|
|
19976
|
-
localServices: {
|
|
19977
|
-
sourceCompanies: {
|
|
19978
|
-
id: "source-companies",
|
|
19979
|
-
label: "Companies found",
|
|
19980
|
-
primaryEntity: "company",
|
|
19981
|
-
outputs: ["company"],
|
|
19982
|
-
stageKey: "populated",
|
|
19983
|
-
dependencyMode: "per-record-eligibility",
|
|
19984
|
-
actionKey: "lead-gen.company.source",
|
|
19985
|
-
defaultBatchSize: 100,
|
|
19986
|
-
maxBatchSize: 250
|
|
19987
|
-
},
|
|
19988
|
-
analyzeWebsites: {
|
|
19989
|
-
id: "analyze-websites",
|
|
19990
|
-
label: "Websites analyzed",
|
|
19991
|
-
primaryEntity: "company",
|
|
19992
|
-
outputs: ["company"],
|
|
19993
|
-
stageKey: "extracted",
|
|
19994
|
-
dependsOn: ["source-companies"],
|
|
19995
|
-
dependencyMode: "per-record-eligibility",
|
|
19996
|
-
actionKey: "lead-gen.company.website-extract",
|
|
19997
|
-
defaultBatchSize: 50,
|
|
19998
|
-
maxBatchSize: 100
|
|
19999
|
-
},
|
|
20000
|
-
qualifyCompanies: {
|
|
20001
|
-
id: "qualify-companies",
|
|
20002
|
-
label: "Companies qualified",
|
|
20003
|
-
primaryEntity: "company",
|
|
20004
|
-
outputs: ["company"],
|
|
20005
|
-
stageKey: "qualified",
|
|
20006
|
-
dependsOn: ["analyze-websites"],
|
|
20007
|
-
dependencyMode: "per-record-eligibility",
|
|
20008
|
-
actionKey: "lead-gen.company.qualify",
|
|
20009
|
-
defaultBatchSize: 100,
|
|
20010
|
-
maxBatchSize: 250
|
|
20011
|
-
},
|
|
20012
|
-
findContacts: {
|
|
20013
|
-
id: "find-contacts",
|
|
20014
|
-
label: "Decision-makers found",
|
|
20015
|
-
primaryEntity: "contact",
|
|
20016
|
-
outputs: ["contact"],
|
|
20017
|
-
stageKey: "discovered",
|
|
20018
|
-
dependsOn: ["qualify-companies"],
|
|
20019
|
-
dependencyMode: "per-record-eligibility",
|
|
20020
|
-
actionKey: "lead-gen.contact.discover",
|
|
20021
|
-
defaultBatchSize: 50,
|
|
20022
|
-
maxBatchSize: 100
|
|
20023
|
-
},
|
|
20024
|
-
verifyEmails: {
|
|
20025
|
-
id: "verify-emails",
|
|
20026
|
-
label: "Emails verified",
|
|
20027
|
-
primaryEntity: "contact",
|
|
20028
|
-
outputs: ["contact"],
|
|
20029
|
-
stageKey: "verified",
|
|
20030
|
-
dependsOn: ["find-contacts"],
|
|
20031
|
-
dependencyMode: "per-record-eligibility",
|
|
20032
|
-
actionKey: "lead-gen.contact.verify-email",
|
|
20033
|
-
defaultBatchSize: 100,
|
|
20034
|
-
maxBatchSize: 500
|
|
20035
|
-
},
|
|
20036
|
-
personalize: {
|
|
20037
|
-
id: "personalize",
|
|
20038
|
-
label: "Personalize",
|
|
20039
|
-
primaryEntity: "contact",
|
|
20040
|
-
outputs: ["contact"],
|
|
20041
|
-
stageKey: "personalized",
|
|
20042
|
-
dependsOn: ["verify-emails"],
|
|
20043
|
-
dependencyMode: "per-record-eligibility",
|
|
20044
|
-
actionKey: "lead-gen.contact.personalize",
|
|
20045
|
-
defaultBatchSize: 25,
|
|
20046
|
-
maxBatchSize: 100
|
|
20047
|
-
},
|
|
20048
|
-
review: {
|
|
20049
|
-
id: "review",
|
|
20050
|
-
label: "Reviewed and exported",
|
|
20051
|
-
primaryEntity: "contact",
|
|
20052
|
-
outputs: ["export"],
|
|
20053
|
-
stageKey: "uploaded",
|
|
20054
|
-
dependsOn: ["personalize"],
|
|
20055
|
-
dependencyMode: "per-record-eligibility",
|
|
20056
|
-
actionKey: "lead-gen.review.outreach-ready",
|
|
20057
|
-
defaultBatchSize: 25,
|
|
20058
|
-
maxBatchSize: 100
|
|
20059
|
-
}
|
|
20060
|
-
}};
|
|
20061
20005
|
|
|
20062
20006
|
// ../elevasis-core/src/organization-model/sales.ts
|
|
20063
20007
|
var CRM_DISCOVERY_REPLIED_STATE = {
|
|
@@ -20136,40 +20080,6 @@ var DEFAULT_CRM_PRIORITY_RULE_CONFIG = {
|
|
|
20136
20080
|
},
|
|
20137
20081
|
staleAfterDays: 14
|
|
20138
20082
|
};
|
|
20139
|
-
var PENDING_STATE = { stateKey: "pending", label: "Pending" };
|
|
20140
|
-
var ACQ_LIST_MEMBERS_LEAD_GEN_PIPELINE = {
|
|
20141
|
-
pipelineKey: "lead-gen",
|
|
20142
|
-
label: "Lead Generation",
|
|
20143
|
-
entityKey: "acq.list-member",
|
|
20144
|
-
stages: [
|
|
20145
|
-
{
|
|
20146
|
-
stageKey: "outreach",
|
|
20147
|
-
label: "Outreach",
|
|
20148
|
-
states: [
|
|
20149
|
-
PENDING_STATE,
|
|
20150
|
-
{ stateKey: "personalized", label: "Personalized" },
|
|
20151
|
-
{ stateKey: "uploaded", label: "Uploaded" },
|
|
20152
|
-
{ stateKey: "interested", label: "Interested" }
|
|
20153
|
-
]
|
|
20154
|
-
},
|
|
20155
|
-
{
|
|
20156
|
-
stageKey: "prospecting",
|
|
20157
|
-
label: "Prospecting",
|
|
20158
|
-
states: [
|
|
20159
|
-
PENDING_STATE,
|
|
20160
|
-
{ stateKey: "discovered", label: "Discovered" },
|
|
20161
|
-
{ stateKey: "verified", label: "Verified" }
|
|
20162
|
-
]
|
|
20163
|
-
},
|
|
20164
|
-
{
|
|
20165
|
-
stageKey: "qualification",
|
|
20166
|
-
label: "Qualification",
|
|
20167
|
-
states: [PENDING_STATE]
|
|
20168
|
-
}
|
|
20169
|
-
]
|
|
20170
|
-
};
|
|
20171
|
-
var LEAD_GEN_PIPELINE_DEFINITIONS = {
|
|
20172
|
-
"acq.list-member": [ACQ_LIST_MEMBERS_LEAD_GEN_PIPELINE]};
|
|
20173
20083
|
|
|
20174
20084
|
// src/lib/crm/pipeline.ts
|
|
20175
20085
|
function getCrmStageOptions() {
|
|
@@ -21984,6 +21894,7 @@ function DealDetailPage({ dealId, renderActions, onDealLoaded }) {
|
|
|
21984
21894
|
function CompanyDetailPage({ companyId }) {
|
|
21985
21895
|
const navigate = useNavigate();
|
|
21986
21896
|
const { data: company, isLoading, error } = useCompany(companyId);
|
|
21897
|
+
const [enrichmentView, setEnrichmentView] = useState("formatted");
|
|
21987
21898
|
const title = company ? company.name : "Company Detail";
|
|
21988
21899
|
const headerActions = /* @__PURE__ */ jsx(
|
|
21989
21900
|
Button,
|
|
@@ -22101,8 +22012,22 @@ function CompanyDetailPage({ companyId }) {
|
|
|
22101
22012
|
/* @__PURE__ */ jsx(Text, { size: "sm", style: { whiteSpace: "pre-wrap" }, children: company.verticalResearch })
|
|
22102
22013
|
] }) }),
|
|
22103
22014
|
company.enrichmentData && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
22104
|
-
/* @__PURE__ */
|
|
22105
|
-
|
|
22015
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", children: [
|
|
22016
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "Enrichment Data" }),
|
|
22017
|
+
/* @__PURE__ */ jsx(
|
|
22018
|
+
SegmentedControl,
|
|
22019
|
+
{
|
|
22020
|
+
value: enrichmentView,
|
|
22021
|
+
onChange: (v) => setEnrichmentView(v),
|
|
22022
|
+
size: "xs",
|
|
22023
|
+
data: [
|
|
22024
|
+
{ label: "Formatted", value: "formatted" },
|
|
22025
|
+
{ label: "JSON", value: "json" }
|
|
22026
|
+
]
|
|
22027
|
+
}
|
|
22028
|
+
)
|
|
22029
|
+
] }),
|
|
22030
|
+
enrichmentView === "formatted" ? /* @__PURE__ */ jsx(ContextViewer, { data: company.enrichmentData }) : /* @__PURE__ */ jsx(JsonViewer, { data: company.enrichmentData })
|
|
22106
22031
|
] }) })
|
|
22107
22032
|
] }) })
|
|
22108
22033
|
] }) });
|
|
@@ -22655,6 +22580,47 @@ function useDeleteLists() {
|
|
|
22655
22580
|
}
|
|
22656
22581
|
});
|
|
22657
22582
|
}
|
|
22583
|
+
function actionMatchesExport(primaryAction) {
|
|
22584
|
+
return primaryAction === "lead-gen.export.list" || primaryAction?.endsWith(":action/export.list") === true || primaryAction?.endsWith(".export.list") === true;
|
|
22585
|
+
}
|
|
22586
|
+
function getLeadGenExportWorkflowId(model) {
|
|
22587
|
+
return Object.values(model.resources ?? {}).find(
|
|
22588
|
+
(resource2) => resource2.kind === "workflow" && resource2.systemPath === "sales.lead-gen" && (actionMatchesExport(resource2.ontology?.primaryAction) || resource2.ontology?.actions?.some(actionMatchesExport) === true)
|
|
22589
|
+
)?.id;
|
|
22590
|
+
}
|
|
22591
|
+
function toBuildStepDefinition(step) {
|
|
22592
|
+
return {
|
|
22593
|
+
...step,
|
|
22594
|
+
description: step.description ?? `Run ${step.label.toLowerCase()} for this list.`,
|
|
22595
|
+
outputs: [...step.outputs],
|
|
22596
|
+
emptyBlockedText: step.emptyBlockedText ?? "Complete prerequisite build steps before this action can run."
|
|
22597
|
+
};
|
|
22598
|
+
}
|
|
22599
|
+
function getDefaultBuildTemplateId(model, templates) {
|
|
22600
|
+
const configuredId = getSystem(model, "sales.lead-gen")?.config?.defaultBuildTemplateId;
|
|
22601
|
+
if (typeof configuredId === "string" && templates.some((template) => template.id === configuredId)) return configuredId;
|
|
22602
|
+
return templates[0]?.id;
|
|
22603
|
+
}
|
|
22604
|
+
function getDefaultBuildSteps(templates, defaultBuildTemplateId) {
|
|
22605
|
+
const template = templates.find((item) => item.id === defaultBuildTemplateId) ?? templates[0];
|
|
22606
|
+
return template?.steps.map((step) => toBuildStepDefinition(step)) ?? [];
|
|
22607
|
+
}
|
|
22608
|
+
function useLeadGenConfig() {
|
|
22609
|
+
const systems = useOptionalElevasisSystems();
|
|
22610
|
+
const organizationModel2 = systems?.organizationModel;
|
|
22611
|
+
return useMemo(() => {
|
|
22612
|
+
if (!organizationModel2) return {};
|
|
22613
|
+
const buildTemplates = getAllBuildTemplates(organizationModel2);
|
|
22614
|
+
const defaultBuildTemplateId = getDefaultBuildTemplateId(organizationModel2, buildTemplates);
|
|
22615
|
+
return {
|
|
22616
|
+
stageCatalog: getLeadGenStageCatalog(organizationModel2),
|
|
22617
|
+
exportWorkflowId: getLeadGenExportWorkflowId(organizationModel2),
|
|
22618
|
+
defaultBuildTemplateId,
|
|
22619
|
+
defaultBuildSteps: getDefaultBuildSteps(buildTemplates, defaultBuildTemplateId),
|
|
22620
|
+
buildTemplates
|
|
22621
|
+
};
|
|
22622
|
+
}, [organizationModel2]);
|
|
22623
|
+
}
|
|
22658
22624
|
function computeBacklog(current, completed) {
|
|
22659
22625
|
return Math.max(current - completed, 0);
|
|
22660
22626
|
}
|
|
@@ -22910,10 +22876,10 @@ function LeadGenOverviewPage() {
|
|
|
22910
22876
|
] }) }) });
|
|
22911
22877
|
}
|
|
22912
22878
|
var PAGE_SIZE_DEFAULT2 = 20;
|
|
22913
|
-
var
|
|
22914
|
-
value:
|
|
22915
|
-
label:
|
|
22916
|
-
|
|
22879
|
+
var DATA_MODE_OPTIONS = [
|
|
22880
|
+
{ value: "mock", label: "Mock data" },
|
|
22881
|
+
{ value: "live", label: "Live data" }
|
|
22882
|
+
];
|
|
22917
22883
|
var STATUS_FILTER_OPTIONS = [
|
|
22918
22884
|
{ value: "", label: "All statuses" },
|
|
22919
22885
|
{ value: "draft", label: "Draft" },
|
|
@@ -22924,12 +22890,22 @@ var STATUS_FILTER_OPTIONS = [
|
|
|
22924
22890
|
];
|
|
22925
22891
|
function LeadGenListsPage() {
|
|
22926
22892
|
const navigate = useNavigate();
|
|
22893
|
+
const leadGenConfig = useLeadGenConfig();
|
|
22894
|
+
const buildTemplateOptions = useMemo(
|
|
22895
|
+
() => getProspectingBuildTemplateOptions(leadGenConfig.buildTemplates ?? []).map((template) => ({
|
|
22896
|
+
value: template.id,
|
|
22897
|
+
label: template.label
|
|
22898
|
+
})),
|
|
22899
|
+
[leadGenConfig.buildTemplates]
|
|
22900
|
+
);
|
|
22901
|
+
const defaultBuildTemplateId = leadGenConfig.defaultBuildTemplateId ?? buildTemplateOptions[0]?.value ?? "";
|
|
22927
22902
|
const [searchQuery, setSearchQuery] = useState("");
|
|
22928
22903
|
const [statusFilter, setStatusFilter] = useState("");
|
|
22929
22904
|
const [showCreateList, setShowCreateList] = useState(false);
|
|
22930
22905
|
const [newListName, setNewListName] = useState("");
|
|
22931
22906
|
const [newListDescription, setNewListDescription] = useState("");
|
|
22932
|
-
const [newBuildTemplateId, setNewBuildTemplateId] = useState(
|
|
22907
|
+
const [newBuildTemplateId, setNewBuildTemplateId] = useState("");
|
|
22908
|
+
const [newDataMode, setNewDataMode] = useState("mock");
|
|
22933
22909
|
const [showBatchDelete, setShowBatchDelete] = useState(false);
|
|
22934
22910
|
const { data: lists, isLoading: listsLoading } = useLists();
|
|
22935
22911
|
const { data: telemetry, isLoading: telemetryLoading } = useListsTelemetry();
|
|
@@ -22970,11 +22946,13 @@ function LeadGenListsPage() {
|
|
|
22970
22946
|
[sortedLists, pagination.offset]
|
|
22971
22947
|
);
|
|
22972
22948
|
const selection = useTableSelection(paginatedLists, sortedLists);
|
|
22973
|
-
const
|
|
22949
|
+
const selectedBuildTemplateId = newBuildTemplateId || defaultBuildTemplateId;
|
|
22950
|
+
const selectedBuildTemplate = leadGenConfig.buildTemplates?.find((template) => template.id === selectedBuildTemplateId);
|
|
22974
22951
|
function resetCreateListModal() {
|
|
22975
22952
|
setNewListName("");
|
|
22976
22953
|
setNewListDescription("");
|
|
22977
|
-
setNewBuildTemplateId(
|
|
22954
|
+
setNewBuildTemplateId("");
|
|
22955
|
+
setNewDataMode("mock");
|
|
22978
22956
|
setShowCreateList(false);
|
|
22979
22957
|
}
|
|
22980
22958
|
function handleCreateList() {
|
|
@@ -22983,7 +22961,10 @@ function LeadGenListsPage() {
|
|
|
22983
22961
|
const body = {
|
|
22984
22962
|
name: trimmedName,
|
|
22985
22963
|
description: newListDescription.trim() || null,
|
|
22986
|
-
buildTemplateId:
|
|
22964
|
+
...selectedBuildTemplateId ? { buildTemplateId: selectedBuildTemplateId } : {},
|
|
22965
|
+
pipelineConfig: {
|
|
22966
|
+
dataMode: newDataMode
|
|
22967
|
+
}
|
|
22987
22968
|
};
|
|
22988
22969
|
createListMutation.mutate(body, {
|
|
22989
22970
|
onSuccess: (list) => {
|
|
@@ -23180,15 +23161,27 @@ function LeadGenListsPage() {
|
|
|
23180
23161
|
{
|
|
23181
23162
|
label: "Build Pipeline",
|
|
23182
23163
|
description: "Choose the sequence this list should follow.",
|
|
23183
|
-
data:
|
|
23184
|
-
value:
|
|
23185
|
-
onChange: (value) => setNewBuildTemplateId(value ??
|
|
23186
|
-
disabled: createListMutation.isPending,
|
|
23164
|
+
data: buildTemplateOptions,
|
|
23165
|
+
value: selectedBuildTemplateId || null,
|
|
23166
|
+
onChange: (value) => setNewBuildTemplateId(value ?? ""),
|
|
23167
|
+
disabled: createListMutation.isPending || buildTemplateOptions.length === 0,
|
|
23187
23168
|
required: true
|
|
23188
23169
|
}
|
|
23189
23170
|
),
|
|
23190
23171
|
selectedBuildTemplate?.description ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: selectedBuildTemplate.description }) : null
|
|
23191
23172
|
] }),
|
|
23173
|
+
/* @__PURE__ */ jsx(
|
|
23174
|
+
Select,
|
|
23175
|
+
{
|
|
23176
|
+
label: "Data Mode",
|
|
23177
|
+
description: "Choose whether sourcing and enrichment use demo fixtures or live providers.",
|
|
23178
|
+
data: DATA_MODE_OPTIONS,
|
|
23179
|
+
value: newDataMode,
|
|
23180
|
+
onChange: (value) => setNewDataMode(value ?? "mock"),
|
|
23181
|
+
disabled: createListMutation.isPending,
|
|
23182
|
+
required: true
|
|
23183
|
+
}
|
|
23184
|
+
),
|
|
23192
23185
|
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "The list will open in draft mode after creation so you can review configuration and run build steps from the list workspace." }),
|
|
23193
23186
|
/* @__PURE__ */ jsxs(Group, { justify: "flex-end", children: [
|
|
23194
23187
|
/* @__PURE__ */ jsx(Button, { variant: "light", onClick: resetCreateListModal, disabled: createListMutation.isPending, children: "Cancel" }),
|
|
@@ -23255,20 +23248,14 @@ function LeadGenListsPage() {
|
|
|
23255
23248
|
}
|
|
23256
23249
|
|
|
23257
23250
|
// src/lib/lead-gen/legacy-pipeline.ts
|
|
23258
|
-
function resolveLegacyListMemberPipelineLabel(member) {
|
|
23259
|
-
const
|
|
23260
|
-
if (!defs) return null;
|
|
23261
|
-
const pipeline = findPipeline(defs, member.pipelineKey);
|
|
23262
|
-
if (!pipeline) return null;
|
|
23263
|
-
const stage = pipeline.stages.find((s) => s.stageKey === member.stageKey);
|
|
23251
|
+
function resolveLegacyListMemberPipelineLabel(member, stageCatalog = {}) {
|
|
23252
|
+
const stage = stageCatalog[member.stageKey];
|
|
23264
23253
|
if (!stage) return null;
|
|
23265
|
-
const state = stage.states.find((s) => s.stateKey === member.stateKey);
|
|
23266
23254
|
return {
|
|
23267
23255
|
stageLabel: stage.label,
|
|
23268
|
-
stateLabel:
|
|
23256
|
+
stateLabel: stageCatalog[member.stateKey]?.label ?? member.stateKey
|
|
23269
23257
|
};
|
|
23270
23258
|
}
|
|
23271
|
-
var LEAD_GEN_STAGE_CATALOG = getLeadGenStageCatalog(canonicalOrganizationModel);
|
|
23272
23259
|
function formatDateTime2(value) {
|
|
23273
23260
|
if (!value) return "Not yet";
|
|
23274
23261
|
return new Date(value).toLocaleString("en-US", {
|
|
@@ -23279,8 +23266,8 @@ function formatDateTime2(value) {
|
|
|
23279
23266
|
minute: "2-digit"
|
|
23280
23267
|
});
|
|
23281
23268
|
}
|
|
23282
|
-
function getMemberStateColor(stateKey) {
|
|
23283
|
-
const stage =
|
|
23269
|
+
function getMemberStateColor(stateKey, stageCatalog) {
|
|
23270
|
+
const stage = stageCatalog[stateKey];
|
|
23284
23271
|
if (stage?.entity === "contact") return "green";
|
|
23285
23272
|
if (stage?.entity === "company") return "blue";
|
|
23286
23273
|
return "gray";
|
|
@@ -23312,6 +23299,7 @@ function ArtifactsPanel({ listMemberId }) {
|
|
|
23312
23299
|
] }) }, artifact.id)) });
|
|
23313
23300
|
}
|
|
23314
23301
|
function ListMemberDrawerContent({ member, listId }) {
|
|
23302
|
+
const { stageCatalog = {} } = useLeadGenConfig();
|
|
23315
23303
|
const transitionMember = useTransitionListMember();
|
|
23316
23304
|
const statefulItem = useMemo(
|
|
23317
23305
|
() => ({
|
|
@@ -23324,15 +23312,15 @@ function ListMemberDrawerContent({ member, listId }) {
|
|
|
23324
23312
|
[member]
|
|
23325
23313
|
);
|
|
23326
23314
|
const derivedActions = useDeriveActions(statefulItem);
|
|
23327
|
-
const resolved = resolveLegacyListMemberPipelineLabel(member);
|
|
23315
|
+
const resolved = resolveLegacyListMemberPipelineLabel(member, stageCatalog);
|
|
23328
23316
|
const contactName = [member.contact?.firstName, member.contact?.lastName].filter(Boolean).join(" ").trim() || member.contact?.email || "\u2014";
|
|
23329
23317
|
return /* @__PURE__ */ jsxs(Stack, { gap: "md", p: "md", children: [
|
|
23330
23318
|
/* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
23331
23319
|
/* @__PURE__ */ jsx(Group, { gap: "xs", align: "center", children: resolved ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23332
23320
|
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "blue", children: resolved.stageLabel }),
|
|
23333
23321
|
/* @__PURE__ */ jsx(IconChevronRight, { size: 14, style: { color: "var(--color-text-dimmed)" } }),
|
|
23334
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getMemberStateColor(member.stateKey), children: resolved.stateLabel })
|
|
23335
|
-
] }) : /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getMemberStateColor(member.stateKey), children: member.stateKey }) }),
|
|
23322
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getMemberStateColor(member.stateKey, stageCatalog), children: resolved.stateLabel })
|
|
23323
|
+
] }) : /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getMemberStateColor(member.stateKey, stageCatalog), children: member.stateKey }) }),
|
|
23336
23324
|
/* @__PURE__ */ jsx(Title, { order: 4, children: contactName }),
|
|
23337
23325
|
member.contact?.email && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
23338
23326
|
/* @__PURE__ */ jsx(IconMail, { size: 14, style: { color: "var(--color-text-dimmed)" } }),
|
|
@@ -23415,257 +23403,11 @@ function ListMemberDrawer({ memberId, memberKind, listId, onClose }) {
|
|
|
23415
23403
|
}
|
|
23416
23404
|
);
|
|
23417
23405
|
}
|
|
23418
|
-
var LEAD_GEN_STAGE_CATALOG2 = getLeadGenStageCatalog(canonicalOrganizationModel);
|
|
23419
|
-
function formatEventTime(timestamp) {
|
|
23420
|
-
return new Date(timestamp).toLocaleTimeString("en-US", {
|
|
23421
|
-
hour12: false,
|
|
23422
|
-
hour: "2-digit",
|
|
23423
|
-
minute: "2-digit",
|
|
23424
|
-
second: "2-digit"
|
|
23425
|
-
});
|
|
23426
|
-
}
|
|
23427
|
-
function formatId(executionId) {
|
|
23428
|
-
return executionId.length > 10 ? `${executionId.slice(0, 8)}...` : executionId;
|
|
23429
|
-
}
|
|
23430
|
-
function getLogLevelColor(level) {
|
|
23431
|
-
switch (level) {
|
|
23432
|
-
case "error":
|
|
23433
|
-
return "red";
|
|
23434
|
-
case "warn":
|
|
23435
|
-
return "yellow";
|
|
23436
|
-
case "debug":
|
|
23437
|
-
return "gray";
|
|
23438
|
-
default:
|
|
23439
|
-
return "blue";
|
|
23440
|
-
}
|
|
23441
|
-
}
|
|
23442
|
-
function getStepStatusColor(status) {
|
|
23443
|
-
switch (status) {
|
|
23444
|
-
case "failed":
|
|
23445
|
-
return "red";
|
|
23446
|
-
case "done":
|
|
23447
|
-
return "green";
|
|
23448
|
-
default:
|
|
23449
|
-
return "blue";
|
|
23450
|
-
}
|
|
23451
|
-
}
|
|
23452
|
-
function getStepStatusLabel(status) {
|
|
23453
|
-
switch (status) {
|
|
23454
|
-
case "failed":
|
|
23455
|
-
return "Failed";
|
|
23456
|
-
case "done":
|
|
23457
|
-
return "Done";
|
|
23458
|
-
default:
|
|
23459
|
-
return "Running";
|
|
23460
|
-
}
|
|
23461
|
-
}
|
|
23462
|
-
function getEventColor(event) {
|
|
23463
|
-
switch (event.type) {
|
|
23464
|
-
case "new-execution":
|
|
23465
|
-
return "blue";
|
|
23466
|
-
case "execution-complete":
|
|
23467
|
-
return event.data.success ? "green" : "red";
|
|
23468
|
-
case "log":
|
|
23469
|
-
return getLogLevelColor(event.data.log.level);
|
|
23470
|
-
default:
|
|
23471
|
-
return "gray";
|
|
23472
|
-
}
|
|
23473
|
-
}
|
|
23474
|
-
function getEventLabel(event) {
|
|
23475
|
-
switch (event.type) {
|
|
23476
|
-
case "new-execution":
|
|
23477
|
-
return "Execution started";
|
|
23478
|
-
case "execution-complete":
|
|
23479
|
-
return event.data.success ? "Execution completed" : "Execution failed";
|
|
23480
|
-
case "log":
|
|
23481
|
-
return event.data.log.message;
|
|
23482
|
-
default:
|
|
23483
|
-
return "Stream connected";
|
|
23484
|
-
}
|
|
23485
|
-
}
|
|
23486
|
-
function hasExecutionId(event) {
|
|
23487
|
-
return event.type !== "connected" && typeof event.executionId === "string" && event.executionId.length > 0;
|
|
23488
|
-
}
|
|
23489
|
-
function toTimelineEvents(events) {
|
|
23490
|
-
return events.filter(hasExecutionId).map((event) => ({
|
|
23491
|
-
executionId: event.executionId,
|
|
23492
|
-
timestamp: event.timestamp,
|
|
23493
|
-
label: getEventLabel(event),
|
|
23494
|
-
color: getEventColor(event),
|
|
23495
|
-
detail: event.type === "execution-complete" ? event.data.error : void 0
|
|
23496
|
-
})).sort((a, b) => b.timestamp - a.timestamp).slice(0, 5);
|
|
23497
|
-
}
|
|
23498
|
-
function collectStepStatuses(events, streamingLogs) {
|
|
23499
|
-
const statuses = /* @__PURE__ */ new Map();
|
|
23500
|
-
const applyLog = (executionId, log) => {
|
|
23501
|
-
const context = log.context;
|
|
23502
|
-
if (!context || context.type !== "workflow") return;
|
|
23503
|
-
if (!("stepId" in context)) return;
|
|
23504
|
-
let status = null;
|
|
23505
|
-
if (isStepStartedContext(context)) status = "running";
|
|
23506
|
-
if (isStepCompletedContext(context)) status = "done";
|
|
23507
|
-
if (isStepFailedContext(context)) status = "failed";
|
|
23508
|
-
if (!status) return;
|
|
23509
|
-
statuses.set(executionId, {
|
|
23510
|
-
executionId,
|
|
23511
|
-
stepId: context.stepId,
|
|
23512
|
-
status,
|
|
23513
|
-
timestamp: log.timestamp,
|
|
23514
|
-
message: log.message
|
|
23515
|
-
});
|
|
23516
|
-
};
|
|
23517
|
-
events.forEach((event) => {
|
|
23518
|
-
if (event.type === "log") applyLog(event.executionId, event.data.log);
|
|
23519
|
-
});
|
|
23520
|
-
streamingLogs.forEach((logs, executionId) => {
|
|
23521
|
-
logs.forEach((log) => applyLog(executionId, log));
|
|
23522
|
-
});
|
|
23523
|
-
return Array.from(statuses.values()).sort((a, b) => b.timestamp - a.timestamp);
|
|
23524
|
-
}
|
|
23525
|
-
function getExecutionId(execution) {
|
|
23526
|
-
return "executionId" in execution ? execution.executionId : execution.id;
|
|
23527
|
-
}
|
|
23528
|
-
function getInFlightExecutions(data) {
|
|
23529
|
-
if (Array.isArray(data)) return data;
|
|
23530
|
-
if (data && typeof data === "object" && "executions" in data) {
|
|
23531
|
-
const executions = data.executions;
|
|
23532
|
-
return Array.isArray(executions) ? executions : [];
|
|
23533
|
-
}
|
|
23534
|
-
return [];
|
|
23535
|
-
}
|
|
23536
|
-
function getStageProgress(progress, stageKey) {
|
|
23537
|
-
return progress?.byCompanyStage[stageKey] ?? progress?.byContactStage[stageKey];
|
|
23538
|
-
}
|
|
23539
|
-
function getStageLabel(stageKey) {
|
|
23540
|
-
return LEAD_GEN_STAGE_CATALOG2[stageKey]?.label ?? stageKey;
|
|
23541
|
-
}
|
|
23542
|
-
function getDoneCount(stageProgress) {
|
|
23543
|
-
return stageProgress?.attempted ?? 0;
|
|
23544
|
-
}
|
|
23545
|
-
function LeadGenLiveStatusPanel({
|
|
23546
|
-
listId,
|
|
23547
|
-
resourceId,
|
|
23548
|
-
stageKey,
|
|
23549
|
-
stepLabel,
|
|
23550
|
-
enabled = true,
|
|
23551
|
-
onRunningChange
|
|
23552
|
-
}) {
|
|
23553
|
-
const sse = useExecutionSSE(resourceId, {
|
|
23554
|
-
enabled: enabled && Boolean(resourceId),
|
|
23555
|
-
listId
|
|
23556
|
-
});
|
|
23557
|
-
const inFlightQuery = useInFlightExecutions(resourceId, {
|
|
23558
|
-
enabled: enabled && Boolean(resourceId),
|
|
23559
|
-
limit: 5,
|
|
23560
|
-
refetchInterval: enabled && Boolean(resourceId) ? 2e3 : false
|
|
23561
|
-
});
|
|
23562
|
-
const inFlightExecutions = useMemo(() => getInFlightExecutions(inFlightQuery.data), [inFlightQuery.data]);
|
|
23563
|
-
const activeExecutionIds = useMemo(() => {
|
|
23564
|
-
const ids = new Set(sse.liveExecutions);
|
|
23565
|
-
inFlightExecutions.forEach((execution) => {
|
|
23566
|
-
const executionId = getExecutionId(execution);
|
|
23567
|
-
if (executionId) ids.add(executionId);
|
|
23568
|
-
});
|
|
23569
|
-
return Array.from(ids);
|
|
23570
|
-
}, [inFlightExecutions, sse.liveExecutions]);
|
|
23571
|
-
const running = enabled && activeExecutionIds.length > 0;
|
|
23572
|
-
const [showCompletedActivity, setShowCompletedActivity] = useState(false);
|
|
23573
|
-
const progressQuery = useListProgress(listId, {
|
|
23574
|
-
enabled: enabled && Boolean(listId),
|
|
23575
|
-
refetchInterval: running ? 2e3 : false
|
|
23576
|
-
});
|
|
23577
|
-
useEffect(() => {
|
|
23578
|
-
onRunningChange?.(running);
|
|
23579
|
-
}, [onRunningChange, running]);
|
|
23580
|
-
const stepStatuses = useMemo(
|
|
23581
|
-
() => collectStepStatuses(sse.events, sse.streamingLogs),
|
|
23582
|
-
[sse.events, sse.streamingLogs]
|
|
23583
|
-
);
|
|
23584
|
-
const latestStepStatus = stepStatuses[0];
|
|
23585
|
-
const lastEvents = useMemo(() => toTimelineEvents(sse.events), [sse.events]);
|
|
23586
|
-
const stageProgress = getStageProgress(progressQuery.data, stageKey);
|
|
23587
|
-
const doneCount = getDoneCount(stageProgress);
|
|
23588
|
-
const totalCount = stageProgress?.total ?? 0;
|
|
23589
|
-
const failed = Boolean(sse.error) || sse.events.some((event) => event.type === "execution-complete" && !event.data.success);
|
|
23590
|
-
const latestEvent = sse.latestEvent;
|
|
23591
|
-
useEffect(() => {
|
|
23592
|
-
if (running || failed || sse.error) {
|
|
23593
|
-
setShowCompletedActivity(true);
|
|
23594
|
-
return;
|
|
23595
|
-
}
|
|
23596
|
-
if (latestEvent?.type !== "execution-complete") return;
|
|
23597
|
-
setShowCompletedActivity(true);
|
|
23598
|
-
const timeoutId = window.setTimeout(() => setShowCompletedActivity(false), 1e4);
|
|
23599
|
-
return () => window.clearTimeout(timeoutId);
|
|
23600
|
-
}, [failed, latestEvent, running, sse.error]);
|
|
23601
|
-
const hasActivity = activeExecutionIds.length > 0 || sse.streamingLogs.size > 0 || showCompletedActivity || Boolean(sse.error);
|
|
23602
|
-
if (!enabled || !hasActivity && !sse.error && !failed) {
|
|
23603
|
-
return null;
|
|
23604
|
-
}
|
|
23605
|
-
return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
23606
|
-
/* @__PURE__ */ jsx(
|
|
23607
|
-
CardHeader,
|
|
23608
|
-
{
|
|
23609
|
-
icon: /* @__PURE__ */ jsx(IconTerminal2, { size: 16 }),
|
|
23610
|
-
title: stepLabel ? `${stepLabel} status` : "Live status",
|
|
23611
|
-
rightSection: /* @__PURE__ */ jsxs(Group, { gap: 6, children: [
|
|
23612
|
-
/* @__PURE__ */ jsx(
|
|
23613
|
-
Badge,
|
|
23614
|
-
{
|
|
23615
|
-
size: "xs",
|
|
23616
|
-
variant: "light",
|
|
23617
|
-
color: sse.connected ? "green" : running ? "yellow" : "gray",
|
|
23618
|
-
leftSection: sse.connected ? /* @__PURE__ */ jsx(IconCircleCheck, { size: 9 }) : /* @__PURE__ */ jsx(IconCircleDot, { size: 9 }),
|
|
23619
|
-
children: sse.connected ? "Connected" : running ? "Reconnecting" : "Idle"
|
|
23620
|
-
}
|
|
23621
|
-
),
|
|
23622
|
-
running ? /* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "filled", color: "blue", leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 9 }), children: [
|
|
23623
|
-
activeExecutionIds.length,
|
|
23624
|
-
" running"
|
|
23625
|
-
] }) : null
|
|
23626
|
-
] })
|
|
23627
|
-
}
|
|
23628
|
-
),
|
|
23629
|
-
sse.error ? /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 14 }), color: "red", variant: "light", p: "xs", children: /* @__PURE__ */ jsx(Text, { size: "xs", children: sse.error }) }) : null,
|
|
23630
|
-
activeExecutionIds.length > 0 ? /* @__PURE__ */ jsx(Group, { gap: 6, children: activeExecutionIds.map((executionId) => /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: "blue", ff: "monospace", children: formatId(executionId) }, executionId)) }) : null,
|
|
23631
|
-
/* @__PURE__ */ jsxs(Box, { p: "xs", bg: "var(--surface-primary-subtle)", style: { borderRadius: "var(--mantine-radius-sm)" }, children: [
|
|
23632
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
|
|
23633
|
-
/* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", style: { minWidth: 0 }, children: [
|
|
23634
|
-
/* @__PURE__ */ jsx(IconProgressCheck, { size: 14 }),
|
|
23635
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, truncate: "end", children: getStageLabel(stageKey) })
|
|
23636
|
-
] }),
|
|
23637
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", ff: "monospace", children: [
|
|
23638
|
-
doneCount,
|
|
23639
|
-
"/",
|
|
23640
|
-
totalCount,
|
|
23641
|
-
" done"
|
|
23642
|
-
] })
|
|
23643
|
-
] }),
|
|
23644
|
-
/* @__PURE__ */ jsx(
|
|
23645
|
-
Progress,
|
|
23646
|
-
{
|
|
23647
|
-
mt: 6,
|
|
23648
|
-
size: "xs",
|
|
23649
|
-
value: totalCount > 0 ? doneCount / totalCount * 100 : 0,
|
|
23650
|
-
color: stageProgress && stageProgress.error > 0 ? "red" : "blue"
|
|
23651
|
-
}
|
|
23652
|
-
)
|
|
23653
|
-
] }),
|
|
23654
|
-
latestStepStatus ? /* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
|
|
23655
|
-
/* @__PURE__ */ jsx(Badge, { size: "xs", color: getStepStatusColor(latestStepStatus.status), variant: "light", children: getStepStatusLabel(latestStepStatus.status) }),
|
|
23656
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 500, truncate: "end", children: latestStepStatus.stepId }),
|
|
23657
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: "end", style: { flex: 1 }, children: latestStepStatus.message })
|
|
23658
|
-
] }) : running ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Waiting for workflow step events." }) : null,
|
|
23659
|
-
lastEvents.length > 0 ? /* @__PURE__ */ jsx(Stack, { gap: 4, children: lastEvents.map((event) => /* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
|
|
23660
|
-
/* @__PURE__ */ jsx(Badge, { size: "xs", variant: "dot", color: event.color, miw: 68, children: formatEventTime(event.timestamp) }),
|
|
23661
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", miw: 62, children: formatId(event.executionId) }),
|
|
23662
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", truncate: "end", style: { flex: 1 }, children: event.detail ?? event.label })
|
|
23663
|
-
] }, `${event.executionId}-${event.timestamp}-${event.label}`)) }) : null
|
|
23664
|
-
] }) });
|
|
23665
|
-
}
|
|
23666
23406
|
var panelStyle = {
|
|
23667
23407
|
flex: 1,
|
|
23668
23408
|
minHeight: 0,
|
|
23409
|
+
minWidth: 0,
|
|
23410
|
+
overflowX: "hidden",
|
|
23669
23411
|
overflowY: "auto",
|
|
23670
23412
|
paddingTop: "var(--mantine-spacing-sm)"
|
|
23671
23413
|
};
|
|
@@ -23684,7 +23426,8 @@ function StepDetailRightColumn({
|
|
|
23684
23426
|
gap: "sm",
|
|
23685
23427
|
style: {
|
|
23686
23428
|
flex: 1,
|
|
23687
|
-
minHeight: 0
|
|
23429
|
+
minHeight: 0,
|
|
23430
|
+
minWidth: 0
|
|
23688
23431
|
},
|
|
23689
23432
|
children: [
|
|
23690
23433
|
/* @__PURE__ */ jsxs(
|
|
@@ -23699,6 +23442,7 @@ function StepDetailRightColumn({
|
|
|
23699
23442
|
style: {
|
|
23700
23443
|
flex: 1,
|
|
23701
23444
|
minHeight: 0,
|
|
23445
|
+
minWidth: 0,
|
|
23702
23446
|
display: "flex",
|
|
23703
23447
|
flexDirection: "column"
|
|
23704
23448
|
},
|
|
@@ -23716,590 +23460,11 @@ function StepDetailRightColumn({
|
|
|
23716
23460
|
]
|
|
23717
23461
|
}
|
|
23718
23462
|
),
|
|
23719
|
-
/* @__PURE__ */ jsx(Stack, { gap: "xs", style: { flexShrink: 0 }, children: action })
|
|
23463
|
+
/* @__PURE__ */ jsx(Stack, { gap: "xs", style: { flexShrink: 0, minWidth: 0, overflowX: "hidden" }, children: action })
|
|
23720
23464
|
]
|
|
23721
23465
|
}
|
|
23722
23466
|
);
|
|
23723
23467
|
}
|
|
23724
|
-
function ListBuilderIndexPage() {
|
|
23725
|
-
const navigate = useNavigate();
|
|
23726
|
-
const [query, setQuery] = useState("");
|
|
23727
|
-
const listsQuery = useLists();
|
|
23728
|
-
const lists = listsQuery.data ?? [];
|
|
23729
|
-
const filteredLists = useMemo(() => {
|
|
23730
|
-
const normalized = query.trim().toLowerCase();
|
|
23731
|
-
if (!normalized) return lists;
|
|
23732
|
-
return lists.filter((list) => list.name.toLowerCase().includes(normalized));
|
|
23733
|
-
}, [lists, query]);
|
|
23734
|
-
const openList = (listId) => {
|
|
23735
|
-
navigate({ to: "/lead-gen/list-builder/$listId", params: { listId } });
|
|
23736
|
-
};
|
|
23737
|
-
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
23738
|
-
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Builder", caption: "Choose a list to run lead-gen workflows and monitor progress." }),
|
|
23739
|
-
/* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
23740
|
-
/* @__PURE__ */ jsx(
|
|
23741
|
-
TextInput,
|
|
23742
|
-
{
|
|
23743
|
-
placeholder: "Search lists...",
|
|
23744
|
-
leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
|
|
23745
|
-
value: query,
|
|
23746
|
-
onChange: (event) => setQuery(event.currentTarget.value)
|
|
23747
|
-
}
|
|
23748
|
-
),
|
|
23749
|
-
listsQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : !filteredLists.length ? /* @__PURE__ */ jsx(
|
|
23750
|
-
EmptyState,
|
|
23751
|
-
{
|
|
23752
|
-
icon: IconLayoutDashboard,
|
|
23753
|
-
title: query.trim() ? "No lists match your search" : "No lists available",
|
|
23754
|
-
description: query.trim() ? void 0 : "Create a list first, then open it in the builder."
|
|
23755
|
-
}
|
|
23756
|
-
) : /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
|
|
23757
|
-
/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
23758
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
|
|
23759
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
|
|
23760
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Batches" }),
|
|
23761
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Created" })
|
|
23762
|
-
] }) }),
|
|
23763
|
-
/* @__PURE__ */ jsx(Table.Tbody, { children: filteredLists.map((list) => /* @__PURE__ */ jsxs(
|
|
23764
|
-
Table.Tr,
|
|
23765
|
-
{
|
|
23766
|
-
role: "button",
|
|
23767
|
-
tabIndex: 0,
|
|
23768
|
-
onClick: () => openList(list.id),
|
|
23769
|
-
onKeyDown: (event) => {
|
|
23770
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
23771
|
-
event.preventDefault();
|
|
23772
|
-
openList(list.id);
|
|
23773
|
-
}
|
|
23774
|
-
},
|
|
23775
|
-
style: { cursor: "pointer" },
|
|
23776
|
-
children: [
|
|
23777
|
-
/* @__PURE__ */ jsxs(Table.Td, { children: [
|
|
23778
|
-
/* @__PURE__ */ jsx(Text, { fw: 500, children: list.name }),
|
|
23779
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: list.description ?? list.id })
|
|
23780
|
-
] }),
|
|
23781
|
-
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStateKeyColor(list.status), children: list.status }) }),
|
|
23782
|
-
/* @__PURE__ */ jsx(Table.Td, { children: list.batchIds.length }),
|
|
23783
|
-
/* @__PURE__ */ jsx(Table.Td, { children: formatDate3(list.createdAt) })
|
|
23784
|
-
]
|
|
23785
|
-
},
|
|
23786
|
-
list.id
|
|
23787
|
-
)) })
|
|
23788
|
-
] })
|
|
23789
|
-
] }) })
|
|
23790
|
-
] }) }) });
|
|
23791
|
-
}
|
|
23792
|
-
|
|
23793
|
-
// src/lib/lead-gen/stage-colors.ts
|
|
23794
|
-
var FALLBACK_STAGE_COLORS = {
|
|
23795
|
-
accent: "var(--color-text-dimmed)",
|
|
23796
|
-
background: "color-mix(in srgb, var(--color-text-dimmed) 10%, transparent)",
|
|
23797
|
-
border: "color-mix(in srgb, var(--color-border) 85%, var(--color-text-dimmed))",
|
|
23798
|
-
text: "var(--color-text)"
|
|
23799
|
-
};
|
|
23800
|
-
var STAGE_COLOR_SETS = {
|
|
23801
|
-
scraped: {
|
|
23802
|
-
accent: "var(--color-text-subtle)",
|
|
23803
|
-
background: "color-mix(in srgb, var(--color-text-subtle) 12%, transparent)",
|
|
23804
|
-
border: "color-mix(in srgb, var(--color-border) 80%, var(--color-text-subtle))",
|
|
23805
|
-
text: "var(--color-text)"
|
|
23806
|
-
},
|
|
23807
|
-
populated: {
|
|
23808
|
-
accent: "var(--color-primary)",
|
|
23809
|
-
background: "color-mix(in srgb, var(--color-primary) 12%, transparent)",
|
|
23810
|
-
border: "color-mix(in srgb, var(--color-border) 70%, var(--color-primary))",
|
|
23811
|
-
text: "var(--color-text)"
|
|
23812
|
-
},
|
|
23813
|
-
crawled: {
|
|
23814
|
-
accent: "color-mix(in srgb, var(--color-primary) 70%, var(--color-text-subtle))",
|
|
23815
|
-
background: "color-mix(in srgb, var(--color-primary) 9%, transparent)",
|
|
23816
|
-
border: "color-mix(in srgb, var(--color-border) 72%, var(--color-primary))",
|
|
23817
|
-
text: "var(--color-text)"
|
|
23818
|
-
},
|
|
23819
|
-
extracted: {
|
|
23820
|
-
accent: "color-mix(in srgb, var(--color-primary) 78%, var(--color-success))",
|
|
23821
|
-
background: "color-mix(in srgb, var(--color-primary) 10%, transparent)",
|
|
23822
|
-
border: "color-mix(in srgb, var(--color-border) 65%, var(--color-primary))",
|
|
23823
|
-
text: "var(--color-text)"
|
|
23824
|
-
},
|
|
23825
|
-
enriched: {
|
|
23826
|
-
accent: "color-mix(in srgb, var(--color-success) 70%, var(--color-primary))",
|
|
23827
|
-
background: "color-mix(in srgb, var(--color-success) 12%, transparent)",
|
|
23828
|
-
border: "color-mix(in srgb, var(--color-border) 68%, var(--color-success))",
|
|
23829
|
-
text: "var(--color-text)"
|
|
23830
|
-
},
|
|
23831
|
-
"decision-makers-enriched": {
|
|
23832
|
-
accent: "color-mix(in srgb, var(--color-primary) 66%, var(--color-warning))",
|
|
23833
|
-
background: "color-mix(in srgb, var(--color-primary) 12%, transparent)",
|
|
23834
|
-
border: "color-mix(in srgb, var(--color-border) 66%, var(--color-primary))",
|
|
23835
|
-
text: "var(--color-text)"
|
|
23836
|
-
},
|
|
23837
|
-
discovered: {
|
|
23838
|
-
accent: "color-mix(in srgb, var(--color-primary) 70%, var(--color-warning))",
|
|
23839
|
-
background: "color-mix(in srgb, var(--color-warning) 10%, transparent)",
|
|
23840
|
-
border: "color-mix(in srgb, var(--color-border) 68%, var(--color-warning))",
|
|
23841
|
-
text: "var(--color-text)"
|
|
23842
|
-
},
|
|
23843
|
-
verified: {
|
|
23844
|
-
accent: "var(--color-success)",
|
|
23845
|
-
background: "color-mix(in srgb, var(--color-success) 12%, transparent)",
|
|
23846
|
-
border: "color-mix(in srgb, var(--color-border) 64%, var(--color-success))",
|
|
23847
|
-
text: "var(--color-text)"
|
|
23848
|
-
},
|
|
23849
|
-
qualified: {
|
|
23850
|
-
accent: "color-mix(in srgb, var(--color-success) 82%, var(--color-text))",
|
|
23851
|
-
background: "color-mix(in srgb, var(--color-success) 14%, transparent)",
|
|
23852
|
-
border: "color-mix(in srgb, var(--color-border) 62%, var(--color-success))",
|
|
23853
|
-
text: "var(--color-text)"
|
|
23854
|
-
},
|
|
23855
|
-
personalized: {
|
|
23856
|
-
accent: "color-mix(in srgb, var(--color-primary) 58%, var(--color-success))",
|
|
23857
|
-
background: "color-mix(in srgb, var(--color-primary) 11%, transparent)",
|
|
23858
|
-
border: "color-mix(in srgb, var(--color-border) 66%, var(--color-primary))",
|
|
23859
|
-
text: "var(--color-text)"
|
|
23860
|
-
},
|
|
23861
|
-
uploaded: {
|
|
23862
|
-
accent: "color-mix(in srgb, var(--color-warning) 72%, var(--color-primary))",
|
|
23863
|
-
background: "color-mix(in srgb, var(--color-warning) 12%, transparent)",
|
|
23864
|
-
border: "color-mix(in srgb, var(--color-border) 64%, var(--color-warning))",
|
|
23865
|
-
text: "var(--color-text)"
|
|
23866
|
-
},
|
|
23867
|
-
interested: {
|
|
23868
|
-
accent: "color-mix(in srgb, var(--color-success) 72%, var(--color-warning))",
|
|
23869
|
-
background: "color-mix(in srgb, var(--color-success) 15%, transparent)",
|
|
23870
|
-
border: "color-mix(in srgb, var(--color-border) 58%, var(--color-success))",
|
|
23871
|
-
text: "var(--color-text)"
|
|
23872
|
-
},
|
|
23873
|
-
disqualified: {
|
|
23874
|
-
accent: "var(--color-error)",
|
|
23875
|
-
background: "color-mix(in srgb, var(--color-error) 10%, transparent)",
|
|
23876
|
-
border: "color-mix(in srgb, var(--color-border) 66%, var(--color-error))",
|
|
23877
|
-
text: "var(--color-text)"
|
|
23878
|
-
},
|
|
23879
|
-
invalid: {
|
|
23880
|
-
accent: "color-mix(in srgb, var(--color-error) 72%, var(--color-text-dimmed))",
|
|
23881
|
-
background: "color-mix(in srgb, var(--color-error) 8%, transparent)",
|
|
23882
|
-
border: "color-mix(in srgb, var(--color-border) 78%, var(--color-error))",
|
|
23883
|
-
text: "var(--color-text)"
|
|
23884
|
-
}
|
|
23885
|
-
};
|
|
23886
|
-
function getLeadGenStageColor(stageKey) {
|
|
23887
|
-
return STAGE_COLOR_SETS[stageKey] ?? FALLBACK_STAGE_COLORS;
|
|
23888
|
-
}
|
|
23889
|
-
function getLeadGenStageColorVar(stageKey, tone = "accent") {
|
|
23890
|
-
return getLeadGenStageColor(stageKey)[tone];
|
|
23891
|
-
}
|
|
23892
|
-
var FALLBACK_STAGE_ORDER = 1e4;
|
|
23893
|
-
var LEAD_GEN_STAGE_CATALOG3 = getLeadGenStageCatalog(canonicalOrganizationModel);
|
|
23894
|
-
function unique(values) {
|
|
23895
|
-
return Array.from(new Set(values.filter(Boolean)));
|
|
23896
|
-
}
|
|
23897
|
-
function configuredStages(pipelineConfig) {
|
|
23898
|
-
return (pipelineConfig?.stages ?? []).filter((stage) => stage.enabled !== false).slice().sort((a, b) => {
|
|
23899
|
-
const aOrder = a.order ?? LEAD_GEN_STAGE_CATALOG3[a.key]?.order ?? FALLBACK_STAGE_ORDER;
|
|
23900
|
-
const bOrder = b.order ?? LEAD_GEN_STAGE_CATALOG3[b.key]?.order ?? FALLBACK_STAGE_ORDER;
|
|
23901
|
-
return aOrder - bOrder || a.key.localeCompare(b.key);
|
|
23902
|
-
});
|
|
23903
|
-
}
|
|
23904
|
-
function workflowStageKeys(actions) {
|
|
23905
|
-
return unique((actions ?? []).flatMap((action) => [...action.stagesAffected]));
|
|
23906
|
-
}
|
|
23907
|
-
function sourceFor(stageKey, observedKeys, configKeys, workflowKeys) {
|
|
23908
|
-
if (observedKeys.has(stageKey)) return "activity";
|
|
23909
|
-
if (configKeys.has(stageKey)) return "config";
|
|
23910
|
-
if (workflowKeys.has(stageKey)) return "workflow";
|
|
23911
|
-
return "activity";
|
|
23912
|
-
}
|
|
23913
|
-
function sortStageNodes(nodes) {
|
|
23914
|
-
return nodes.slice().sort((a, b) => a.order - b.order || a.key.localeCompare(b.key));
|
|
23915
|
-
}
|
|
23916
|
-
function buildLaneStages({
|
|
23917
|
-
entity,
|
|
23918
|
-
progress,
|
|
23919
|
-
pipelineConfig,
|
|
23920
|
-
actions
|
|
23921
|
-
}) {
|
|
23922
|
-
const stageMap = entity === "company" ? progress.byCompanyStage : progress.byContactStage;
|
|
23923
|
-
const observedKeys = new Set(Object.keys(stageMap));
|
|
23924
|
-
const configStages = configuredStages(pipelineConfig);
|
|
23925
|
-
const configStageByKey = new Map(configStages.map((stage) => [stage.key, stage]));
|
|
23926
|
-
const configKeys = new Set(configStages.map((stage) => stage.key));
|
|
23927
|
-
const workflowKeys = new Set(workflowStageKeys(actions));
|
|
23928
|
-
const stageKeys = unique([...observedKeys, ...configKeys, ...workflowKeys]);
|
|
23929
|
-
return sortStageNodes(
|
|
23930
|
-
stageKeys.flatMap((key) => {
|
|
23931
|
-
const catalogEntry = LEAD_GEN_STAGE_CATALOG3[key];
|
|
23932
|
-
const inferredEntity = catalogEntry?.entity ?? (observedKeys.has(key) ? entity : null);
|
|
23933
|
-
if (inferredEntity !== entity) return [];
|
|
23934
|
-
return [
|
|
23935
|
-
{
|
|
23936
|
-
key,
|
|
23937
|
-
label: configStageByKey.get(key)?.label ?? catalogEntry?.label ?? key,
|
|
23938
|
-
order: configStageByKey.get(key)?.order ?? catalogEntry?.order ?? FALLBACK_STAGE_ORDER,
|
|
23939
|
-
entity,
|
|
23940
|
-
source: sourceFor(key, observedKeys, configKeys, workflowKeys)
|
|
23941
|
-
}
|
|
23942
|
-
];
|
|
23943
|
-
})
|
|
23944
|
-
);
|
|
23945
|
-
}
|
|
23946
|
-
function getStageProgress2(progress, stageKey, entity) {
|
|
23947
|
-
const stageProgress = entity === "company" ? progress.byCompanyStage[stageKey] : progress.byContactStage[stageKey];
|
|
23948
|
-
const total = stageProgress?.total ?? (entity === "company" ? progress.totalCompanies : progress.totalMembers);
|
|
23949
|
-
return {
|
|
23950
|
-
total,
|
|
23951
|
-
attempted: stageProgress?.attempted ?? 0,
|
|
23952
|
-
success: stageProgress?.success ?? 0,
|
|
23953
|
-
noResult: stageProgress?.noResult ?? 0,
|
|
23954
|
-
skipped: stageProgress?.skipped ?? 0,
|
|
23955
|
-
error: stageProgress?.error ?? 0,
|
|
23956
|
-
other: stageProgress?.other ?? 0,
|
|
23957
|
-
notAttempted: stageProgress?.notAttempted ?? total
|
|
23958
|
-
};
|
|
23959
|
-
}
|
|
23960
|
-
function percent(value, total) {
|
|
23961
|
-
if (total <= 0) return 0;
|
|
23962
|
-
return Math.max(0, Math.min(100, value / total * 100));
|
|
23963
|
-
}
|
|
23964
|
-
function SourceBadge({ source }) {
|
|
23965
|
-
const label = source === "activity" ? "recorded" : source;
|
|
23966
|
-
const color = source === "activity" ? "green" : source === "config" ? "blue" : "gray";
|
|
23967
|
-
return /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color, children: label });
|
|
23968
|
-
}
|
|
23969
|
-
function ProgressRail({ counts, stageKey }) {
|
|
23970
|
-
const accent = getLeadGenStageColorVar(stageKey);
|
|
23971
|
-
const segments = [
|
|
23972
|
-
{ key: "success", value: counts.success, color: accent },
|
|
23973
|
-
{ key: "noResult", value: counts.noResult, color: "var(--color-text-subtle)" },
|
|
23974
|
-
{ key: "skipped", value: counts.skipped, color: "var(--color-warning)" },
|
|
23975
|
-
{ key: "error", value: counts.error, color: "var(--color-error)" },
|
|
23976
|
-
{ key: "other", value: counts.other, color: "var(--color-primary)" }
|
|
23977
|
-
].filter((segment) => segment.value > 0);
|
|
23978
|
-
return /* @__PURE__ */ jsx(
|
|
23979
|
-
Box,
|
|
23980
|
-
{
|
|
23981
|
-
h: 6,
|
|
23982
|
-
bg: "var(--color-surface-hover)",
|
|
23983
|
-
style: {
|
|
23984
|
-
borderRadius: 999,
|
|
23985
|
-
display: "flex",
|
|
23986
|
-
overflow: "hidden",
|
|
23987
|
-
opacity: counts.total > 0 ? 1 : 0.55
|
|
23988
|
-
},
|
|
23989
|
-
children: segments.length > 0 ? segments.map((segment) => /* @__PURE__ */ jsx(Box, { h: "100%", w: `${percent(segment.value, counts.total)}%`, bg: segment.color }, segment.key)) : /* @__PURE__ */ jsx(Box, { h: "100%", w: counts.total > 0 ? `${percent(counts.attempted, counts.total)}%` : "0%", bg: accent })
|
|
23990
|
-
}
|
|
23991
|
-
);
|
|
23992
|
-
}
|
|
23993
|
-
function TimelineLane({
|
|
23994
|
-
title,
|
|
23995
|
-
entity,
|
|
23996
|
-
total,
|
|
23997
|
-
stages,
|
|
23998
|
-
progress,
|
|
23999
|
-
emptyText
|
|
24000
|
-
}) {
|
|
24001
|
-
const Icon = entity === "company" ? IconBuilding : IconUsers;
|
|
24002
|
-
return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
24003
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", gap: "xs", children: [
|
|
24004
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
24005
|
-
/* @__PURE__ */ jsx(
|
|
24006
|
-
Box,
|
|
24007
|
-
{
|
|
24008
|
-
w: 28,
|
|
24009
|
-
h: 28,
|
|
24010
|
-
style: {
|
|
24011
|
-
alignItems: "center",
|
|
24012
|
-
background: "color-mix(in srgb, var(--color-primary) 14%, transparent)",
|
|
24013
|
-
border: "1px solid color-mix(in srgb, var(--color-border) 75%, var(--color-primary))",
|
|
24014
|
-
borderRadius: 999,
|
|
24015
|
-
color: "var(--color-primary)",
|
|
24016
|
-
display: "flex",
|
|
24017
|
-
justifyContent: "center"
|
|
24018
|
-
},
|
|
24019
|
-
children: /* @__PURE__ */ jsx(Icon, { size: 15 })
|
|
24020
|
-
}
|
|
24021
|
-
),
|
|
24022
|
-
/* @__PURE__ */ jsxs(Stack, { gap: 0, children: [
|
|
24023
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: title }),
|
|
24024
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
24025
|
-
total,
|
|
24026
|
-
" ",
|
|
24027
|
-
entity === "company" ? "companies" : "contacts"
|
|
24028
|
-
] })
|
|
24029
|
-
] })
|
|
24030
|
-
] }),
|
|
24031
|
-
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "outline", color: entity === "company" ? "blue" : "teal", children: [
|
|
24032
|
-
stages.length,
|
|
24033
|
-
" stages"
|
|
24034
|
-
] })
|
|
24035
|
-
] }),
|
|
24036
|
-
stages.length === 0 ? /* @__PURE__ */ jsx(
|
|
24037
|
-
Box,
|
|
24038
|
-
{
|
|
24039
|
-
p: "sm",
|
|
24040
|
-
style: {
|
|
24041
|
-
border: "1px dashed var(--color-border)",
|
|
24042
|
-
borderRadius: "var(--mantine-radius-md)"
|
|
24043
|
-
},
|
|
24044
|
-
children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: emptyText })
|
|
24045
|
-
}
|
|
24046
|
-
) : /* @__PURE__ */ jsx(ScrollArea, { type: "hover", offsetScrollbars: true, children: /* @__PURE__ */ jsx(
|
|
24047
|
-
Box,
|
|
24048
|
-
{
|
|
24049
|
-
style: {
|
|
24050
|
-
minWidth: Math.max(560, stages.length * 178),
|
|
24051
|
-
padding: "8px 2px 2px"
|
|
24052
|
-
},
|
|
24053
|
-
children: /* @__PURE__ */ jsx(
|
|
24054
|
-
Box,
|
|
24055
|
-
{
|
|
24056
|
-
style: {
|
|
24057
|
-
alignItems: "start",
|
|
24058
|
-
display: "grid",
|
|
24059
|
-
gap: 0,
|
|
24060
|
-
gridTemplateColumns: `repeat(${stages.length}, minmax(150px, 1fr))`,
|
|
24061
|
-
position: "relative"
|
|
24062
|
-
},
|
|
24063
|
-
children: stages.map((stage, index) => {
|
|
24064
|
-
const counts = getStageProgress2(progress, stage.key, entity);
|
|
24065
|
-
const accent = getLeadGenStageColorVar(stage.key);
|
|
24066
|
-
const completion = Math.round(percent(counts.success, counts.total));
|
|
24067
|
-
const attempted = Math.round(percent(counts.attempted, counts.total));
|
|
24068
|
-
return /* @__PURE__ */ jsxs(Stack, { gap: 8, px: "xs", style: { position: "relative", zIndex: 1 }, children: [
|
|
24069
|
-
/* @__PURE__ */ jsxs(Group, { gap: 8, wrap: "nowrap", children: [
|
|
24070
|
-
/* @__PURE__ */ jsx(
|
|
24071
|
-
Box,
|
|
24072
|
-
{
|
|
24073
|
-
w: 44,
|
|
24074
|
-
h: 44,
|
|
24075
|
-
style: {
|
|
24076
|
-
alignItems: "center",
|
|
24077
|
-
background: getLeadGenStageColorVar(stage.key, "background"),
|
|
24078
|
-
border: `1px solid ${getLeadGenStageColorVar(stage.key, "border")}`,
|
|
24079
|
-
borderRadius: 999,
|
|
24080
|
-
boxShadow: `0 0 0 4px ${getLeadGenStageColorVar(stage.key, "background")}`,
|
|
24081
|
-
color: accent,
|
|
24082
|
-
display: "flex",
|
|
24083
|
-
flexShrink: 0,
|
|
24084
|
-
fontSize: 13,
|
|
24085
|
-
fontWeight: 800,
|
|
24086
|
-
justifyContent: "center"
|
|
24087
|
-
},
|
|
24088
|
-
children: index + 1
|
|
24089
|
-
}
|
|
24090
|
-
),
|
|
24091
|
-
/* @__PURE__ */ jsxs(Stack, { gap: 1, style: { minWidth: 0 }, children: [
|
|
24092
|
-
/* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
|
|
24093
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, lineClamp: 1, children: stage.label }),
|
|
24094
|
-
/* @__PURE__ */ jsx(SourceBadge, { source: stage.source })
|
|
24095
|
-
] }),
|
|
24096
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 1, children: counts.total > 0 ? `${counts.attempted} / ${counts.total} attempted` : `Ready for ${entity === "company" ? "company" : "contact"} rows` })
|
|
24097
|
-
] })
|
|
24098
|
-
] }),
|
|
24099
|
-
/* @__PURE__ */ jsx(ProgressRail, { counts, stageKey: stage.key }),
|
|
24100
|
-
/* @__PURE__ */ jsxs(Group, { gap: 10, wrap: "nowrap", children: [
|
|
24101
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
24102
|
-
counts.success,
|
|
24103
|
-
" success"
|
|
24104
|
-
] }),
|
|
24105
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
24106
|
-
attempted,
|
|
24107
|
-
"% attempted"
|
|
24108
|
-
] }),
|
|
24109
|
-
counts.error > 0 ? /* @__PURE__ */ jsxs(Text, { size: "xs", c: "red", children: [
|
|
24110
|
-
counts.error,
|
|
24111
|
-
" errors"
|
|
24112
|
-
] }) : null
|
|
24113
|
-
] }),
|
|
24114
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
24115
|
-
completion,
|
|
24116
|
-
"% complete"
|
|
24117
|
-
] })
|
|
24118
|
-
] }, stage.key);
|
|
24119
|
-
})
|
|
24120
|
-
}
|
|
24121
|
-
)
|
|
24122
|
-
}
|
|
24123
|
-
) })
|
|
24124
|
-
] });
|
|
24125
|
-
}
|
|
24126
|
-
function PipelineFunnel({ progress, pipelineConfig, actions }) {
|
|
24127
|
-
const companyStages = buildLaneStages({ entity: "company", progress, pipelineConfig, actions });
|
|
24128
|
-
const contactStages = buildLaneStages({ entity: "contact", progress, pipelineConfig, actions });
|
|
24129
|
-
return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "lg", children: [
|
|
24130
|
-
/* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconListDetails, { size: 16 }), title: "Pipeline" }),
|
|
24131
|
-
/* @__PURE__ */ jsx(
|
|
24132
|
-
TimelineLane,
|
|
24133
|
-
{
|
|
24134
|
-
title: "Company pipeline",
|
|
24135
|
-
entity: "company",
|
|
24136
|
-
total: progress.totalCompanies,
|
|
24137
|
-
stages: companyStages,
|
|
24138
|
-
progress,
|
|
24139
|
-
emptyText: "No company stages are configured, runnable, or recorded yet."
|
|
24140
|
-
}
|
|
24141
|
-
),
|
|
24142
|
-
/* @__PURE__ */ jsx(
|
|
24143
|
-
TimelineLane,
|
|
24144
|
-
{
|
|
24145
|
-
title: "Contact pipeline",
|
|
24146
|
-
entity: "contact",
|
|
24147
|
-
total: progress.totalMembers,
|
|
24148
|
-
stages: contactStages,
|
|
24149
|
-
progress,
|
|
24150
|
-
emptyText: "No contact stages are configured, runnable, or recorded yet."
|
|
24151
|
-
}
|
|
24152
|
-
)
|
|
24153
|
-
] }) });
|
|
24154
|
-
}
|
|
24155
|
-
function asRecord(value) {
|
|
24156
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
24157
|
-
}
|
|
24158
|
-
function selectedCount(selection) {
|
|
24159
|
-
return selection.selectedCompanyIds.length + selection.selectedContactIds.length;
|
|
24160
|
-
}
|
|
24161
|
-
function buildInput(input, selection) {
|
|
24162
|
-
const base = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
24163
|
-
return {
|
|
24164
|
-
...base,
|
|
24165
|
-
selectedCompanyIds: selection.selectedCompanyIds,
|
|
24166
|
-
selectedContactIds: selection.selectedContactIds
|
|
24167
|
-
};
|
|
24168
|
-
}
|
|
24169
|
-
function RunWorkflowModal({
|
|
24170
|
-
opened,
|
|
24171
|
-
onClose,
|
|
24172
|
-
list,
|
|
24173
|
-
actions,
|
|
24174
|
-
selection,
|
|
24175
|
-
initialResourceId,
|
|
24176
|
-
title = "Run Workflow",
|
|
24177
|
-
description = "Start a workflow immediately for this list.",
|
|
24178
|
-
lockResourceSelection = false,
|
|
24179
|
-
onResourceChange,
|
|
24180
|
-
onSubmitted
|
|
24181
|
-
}) {
|
|
24182
|
-
const [selectedResourceId, setSelectedResourceId] = useState(
|
|
24183
|
-
initialResourceId ?? actions[0]?.resourceId ?? null
|
|
24184
|
-
);
|
|
24185
|
-
const selectedAction = useMemo(
|
|
24186
|
-
() => actions.find((action) => action.resourceId === selectedResourceId) ?? actions[0],
|
|
24187
|
-
[actions, selectedResourceId]
|
|
24188
|
-
);
|
|
24189
|
-
const execution = useWorkflowExecution({
|
|
24190
|
-
workflowId: selectedAction?.resourceId ?? "",
|
|
24191
|
-
listId: list.id
|
|
24192
|
-
});
|
|
24193
|
-
useEffect(() => {
|
|
24194
|
-
if (!opened) return;
|
|
24195
|
-
const nextResourceId = initialResourceId ?? actions[0]?.resourceId ?? null;
|
|
24196
|
-
setSelectedResourceId(nextResourceId);
|
|
24197
|
-
onResourceChange?.(nextResourceId);
|
|
24198
|
-
}, [actions, initialResourceId, onResourceChange, opened]);
|
|
24199
|
-
const actionOptions = actions.map((action) => ({
|
|
24200
|
-
value: action.resourceId,
|
|
24201
|
-
label: action.label
|
|
24202
|
-
}));
|
|
24203
|
-
const handleResourceChange = (value) => {
|
|
24204
|
-
setSelectedResourceId(value);
|
|
24205
|
-
onResourceChange?.(value);
|
|
24206
|
-
execution.reset();
|
|
24207
|
-
};
|
|
24208
|
-
const submitInput = async (input) => {
|
|
24209
|
-
if (!selectedAction) return;
|
|
24210
|
-
try {
|
|
24211
|
-
const result = await execution.execute({
|
|
24212
|
-
input: buildInput(input, selection)
|
|
24213
|
-
});
|
|
24214
|
-
onSubmitted?.(selectedAction.resourceId, result.executionId);
|
|
24215
|
-
onClose();
|
|
24216
|
-
} catch (error) {
|
|
24217
|
-
showApiErrorNotification(error);
|
|
24218
|
-
}
|
|
24219
|
-
};
|
|
24220
|
-
const count = selectedCount(selection);
|
|
24221
|
-
return /* @__PURE__ */ jsx(
|
|
24222
|
-
CustomModal,
|
|
24223
|
-
{
|
|
24224
|
-
opened,
|
|
24225
|
-
onClose: () => !execution.isPending && onClose(),
|
|
24226
|
-
size: "lg",
|
|
24227
|
-
loading: execution.isPending,
|
|
24228
|
-
children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
24229
|
-
/* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
24230
|
-
/* @__PURE__ */ jsx(IconBolt, { size: 22 }),
|
|
24231
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
24232
|
-
/* @__PURE__ */ jsx(Text, { fw: 600, children: title }),
|
|
24233
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: description })
|
|
24234
|
-
] })
|
|
24235
|
-
] }),
|
|
24236
|
-
!actions.length ? /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "No list builder workflows are registered." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
24237
|
-
/* @__PURE__ */ jsx(
|
|
24238
|
-
Select,
|
|
24239
|
-
{
|
|
24240
|
-
label: "Workflow",
|
|
24241
|
-
data: actionOptions,
|
|
24242
|
-
value: selectedAction?.resourceId ?? null,
|
|
24243
|
-
onChange: handleResourceChange,
|
|
24244
|
-
disabled: execution.isPending || lockResourceSelection,
|
|
24245
|
-
searchable: true
|
|
24246
|
-
}
|
|
24247
|
-
),
|
|
24248
|
-
selectedAction ? /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
24249
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
24250
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: selectedAction.category }),
|
|
24251
|
-
selectedAction.stagesAffected.map((stage) => /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "outline", color: "gray", children: stage }, stage))
|
|
24252
|
-
] }),
|
|
24253
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: selectedAction.description })
|
|
24254
|
-
] }) : null,
|
|
24255
|
-
count > 0 ? /* @__PURE__ */ jsxs(Alert, { color: "blue", variant: "light", children: [
|
|
24256
|
-
"This run includes ",
|
|
24257
|
-
selection.selectedCompanyIds.length,
|
|
24258
|
-
" selected companies and",
|
|
24259
|
-
" ",
|
|
24260
|
-
selection.selectedContactIds.length,
|
|
24261
|
-
" selected contacts."
|
|
24262
|
-
] }) : null,
|
|
24263
|
-
selectedAction ? /* @__PURE__ */ jsx(
|
|
24264
|
-
RunWorkflowConfigForm,
|
|
24265
|
-
{
|
|
24266
|
-
action: selectedAction,
|
|
24267
|
-
list,
|
|
24268
|
-
onSubmit: submitInput,
|
|
24269
|
-
isSubmitting: execution.isPending
|
|
24270
|
-
},
|
|
24271
|
-
selectedAction.resourceId
|
|
24272
|
-
) : null
|
|
24273
|
-
] })
|
|
24274
|
-
] })
|
|
24275
|
-
}
|
|
24276
|
-
);
|
|
24277
|
-
}
|
|
24278
|
-
function RunWorkflowConfigForm({ action, list, onSubmit, isSubmitting }) {
|
|
24279
|
-
const schema = action.schema;
|
|
24280
|
-
const layout = action.layout;
|
|
24281
|
-
const [config, setConfig] = useState(() => asRecord(action.defaultInput?.(list)));
|
|
24282
|
-
const handleChange = (next) => {
|
|
24283
|
-
setConfig(next);
|
|
24284
|
-
};
|
|
24285
|
-
const handleSubmit = async () => {
|
|
24286
|
-
await onSubmit(config);
|
|
24287
|
-
};
|
|
24288
|
-
return /* @__PURE__ */ jsx(Stack, { gap: "md", children: /* @__PURE__ */ jsx(
|
|
24289
|
-
StepConfigForm,
|
|
24290
|
-
{
|
|
24291
|
-
schema,
|
|
24292
|
-
layout,
|
|
24293
|
-
value: config,
|
|
24294
|
-
onChange: (v) => handleChange(asRecord(v)),
|
|
24295
|
-
actions: [{ id: "run", label: `Run ${action.label}`, loading: isSubmitting }],
|
|
24296
|
-
onAction: async () => {
|
|
24297
|
-
await handleSubmit();
|
|
24298
|
-
},
|
|
24299
|
-
disabled: isSubmitting
|
|
24300
|
-
}
|
|
24301
|
-
) });
|
|
24302
|
-
}
|
|
24303
23468
|
function formatDateTime3(value) {
|
|
24304
23469
|
if (!value) return "Not yet";
|
|
24305
23470
|
return new Date(value).toLocaleString("en-US", {
|
|
@@ -24470,150 +23635,10 @@ function WorkflowRunsPanel({
|
|
|
24470
23635
|
}
|
|
24471
23636
|
);
|
|
24472
23637
|
}
|
|
24473
|
-
|
|
24474
|
-
|
|
24475
|
-
|
|
24476
|
-
|
|
24477
|
-
function formatDateTime4(value) {
|
|
24478
|
-
if (!value) return "Not yet";
|
|
24479
|
-
return new Date(value).toLocaleString("en-US", {
|
|
24480
|
-
month: "short",
|
|
24481
|
-
day: "numeric",
|
|
24482
|
-
year: "numeric",
|
|
24483
|
-
hour: "numeric",
|
|
24484
|
-
minute: "2-digit"
|
|
24485
|
-
});
|
|
24486
|
-
}
|
|
24487
|
-
function getStatusColor6(status) {
|
|
24488
|
-
switch (status) {
|
|
24489
|
-
case "completed":
|
|
24490
|
-
case "success":
|
|
24491
|
-
case "launched":
|
|
24492
|
-
return "green";
|
|
24493
|
-
case "running":
|
|
24494
|
-
case "pending":
|
|
24495
|
-
case "enriching":
|
|
24496
|
-
return "blue";
|
|
24497
|
-
case "failed":
|
|
24498
|
-
case "error":
|
|
24499
|
-
case "archived":
|
|
24500
|
-
return "red";
|
|
24501
|
-
case "closing":
|
|
24502
|
-
return "yellow";
|
|
24503
|
-
default:
|
|
24504
|
-
return "gray";
|
|
24505
|
-
}
|
|
24506
|
-
}
|
|
24507
|
-
function ListBuilderPage({ listId }) {
|
|
24508
|
-
const navigate = useNavigate();
|
|
24509
|
-
const actions = useListActions();
|
|
24510
|
-
const [runModalOpen, setRunModalOpen] = useState(false);
|
|
24511
|
-
const [initialRunResourceId, setInitialRunResourceId] = useState(null);
|
|
24512
|
-
const listQuery = useList(listId);
|
|
24513
|
-
const progressQuery = useListProgress(listId);
|
|
24514
|
-
const executionsQuery = useListExecutions(listId);
|
|
24515
|
-
const isLoading = listQuery.isLoading || progressQuery.isLoading || executionsQuery.isLoading;
|
|
24516
|
-
const error = listQuery.error ?? progressQuery.error ?? executionsQuery.error;
|
|
24517
|
-
const executions = useMemo(() => executionsQuery.data ?? [], [executionsQuery.data]);
|
|
24518
|
-
const openRunModal = (resourceId) => {
|
|
24519
|
-
const nextResourceId = actions[0]?.resourceId ?? null;
|
|
24520
|
-
setInitialRunResourceId(nextResourceId);
|
|
24521
|
-
setRunModalOpen(true);
|
|
24522
|
-
};
|
|
24523
|
-
const closeRunModal = () => {
|
|
24524
|
-
setRunModalOpen(false);
|
|
24525
|
-
setInitialRunResourceId(null);
|
|
24526
|
-
};
|
|
24527
|
-
const copyListCommand = (id) => {
|
|
24528
|
-
void navigator.clipboard.writeText(`/acquisition --lead-gen list ${id}`);
|
|
24529
|
-
showSuccessNotification("Copied list command to clipboard");
|
|
24530
|
-
};
|
|
24531
|
-
const backButton = /* @__PURE__ */ jsx(
|
|
24532
|
-
Button,
|
|
24533
|
-
{
|
|
24534
|
-
variant: "light",
|
|
24535
|
-
size: "xs",
|
|
24536
|
-
leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
|
|
24537
|
-
onClick: () => navigate({ to: "/lead-gen/lists" }),
|
|
24538
|
-
children: "Lists"
|
|
24539
|
-
}
|
|
24540
|
-
);
|
|
24541
|
-
if (isLoading) {
|
|
24542
|
-
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
24543
|
-
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Builder", caption: "Lead-gen workspace", rightSection: backButton }),
|
|
24544
|
-
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) })
|
|
24545
|
-
] }) }) });
|
|
24546
|
-
}
|
|
24547
|
-
if (error) {
|
|
24548
|
-
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
24549
|
-
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Builder", caption: "Lead-gen workspace", rightSection: backButton }),
|
|
24550
|
-
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load list builder" }) })
|
|
24551
|
-
] }) }) });
|
|
24552
|
-
}
|
|
24553
|
-
if (!listQuery.data || !progressQuery.data) {
|
|
24554
|
-
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
24555
|
-
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Not Found", caption: "The requested lead-gen list is unavailable." }),
|
|
24556
|
-
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { h: 240, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "The requested list could not be found." }) }) })
|
|
24557
|
-
] }) }) });
|
|
24558
|
-
}
|
|
24559
|
-
const list = listQuery.data;
|
|
24560
|
-
const progress = progressQuery.data;
|
|
24561
|
-
return /* @__PURE__ */ jsxs(SubshellContentContainer, { children: [
|
|
24562
|
-
/* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
24563
|
-
/* @__PURE__ */ jsx(
|
|
24564
|
-
PageTitleCaption,
|
|
24565
|
-
{
|
|
24566
|
-
title: list.name,
|
|
24567
|
-
caption: list.description ?? "Lead-gen list builder",
|
|
24568
|
-
rightSection: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
24569
|
-
/* @__PURE__ */ jsx(Button, { size: "xs", leftSection: /* @__PURE__ */ jsx(IconBolt, { size: 16 }), onClick: () => openRunModal(), children: "Run Workflow" }),
|
|
24570
|
-
backButton
|
|
24571
|
-
] })
|
|
24572
|
-
}
|
|
24573
|
-
),
|
|
24574
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
24575
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
24576
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor6(list.status), children: list.status }),
|
|
24577
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
24578
|
-
"Created ",
|
|
24579
|
-
formatDateTime4(list.createdAt)
|
|
24580
|
-
] })
|
|
24581
|
-
] }),
|
|
24582
|
-
/* @__PURE__ */ jsx(Group, { gap: "xs", children: /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", onClick: () => copyListCommand(list.id), style: { cursor: "pointer" }, children: [
|
|
24583
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", children: list.id }),
|
|
24584
|
-
/* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", "aria-label": "Copy list command", children: /* @__PURE__ */ jsx(IconCopy, { size: 14 }) })
|
|
24585
|
-
] }) })
|
|
24586
|
-
] }),
|
|
24587
|
-
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2, lg: 4 }, children: [
|
|
24588
|
-
/* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
|
|
24589
|
-
/* @__PURE__ */ jsx(StatCard, { label: "Contacts", value: progress.totalMembers, icon: IconUsers }),
|
|
24590
|
-
/* @__PURE__ */ jsx(StatCard, { label: "Workflows", value: actions.length, icon: IconBolt }),
|
|
24591
|
-
/* @__PURE__ */ jsx(StatCard, { label: "Runs", value: executions.length, icon: IconPlayerPlay })
|
|
24592
|
-
] }),
|
|
24593
|
-
/* @__PURE__ */ jsx(PipelineFunnel, { progress, pipelineConfig: list.pipelineConfig, actions }),
|
|
24594
|
-
/* @__PURE__ */ jsx(WorkflowRunsPanel, { listId })
|
|
24595
|
-
] }) }),
|
|
24596
|
-
/* @__PURE__ */ jsx(
|
|
24597
|
-
RunWorkflowModal,
|
|
24598
|
-
{
|
|
24599
|
-
opened: runModalOpen,
|
|
24600
|
-
onClose: closeRunModal,
|
|
24601
|
-
list,
|
|
24602
|
-
actions,
|
|
24603
|
-
selection: EMPTY_SELECTION,
|
|
24604
|
-
initialResourceId: initialRunResourceId,
|
|
24605
|
-
onSubmitted: (_resourceId, executionId) => {
|
|
24606
|
-
showSuccessNotification(`Workflow run started: ${executionId}`);
|
|
24607
|
-
}
|
|
24608
|
-
}
|
|
24609
|
-
)
|
|
24610
|
-
] });
|
|
24611
|
-
}
|
|
24612
|
-
|
|
24613
|
-
// src/lib/lead-gen/processing-state.ts
|
|
24614
|
-
var LEAD_GEN_STAGE_CATALOG4 = getLeadGenStageCatalog(canonicalOrganizationModel);
|
|
24615
|
-
function isRecord(value) {
|
|
24616
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
23638
|
+
|
|
23639
|
+
// src/lib/lead-gen/processing-state.ts
|
|
23640
|
+
function isRecord(value) {
|
|
23641
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
24617
23642
|
}
|
|
24618
23643
|
function parseProcessingStageStatus(value) {
|
|
24619
23644
|
if (value === true || value === "success") return "success";
|
|
@@ -24624,7 +23649,7 @@ function parseProcessingStageStatus(value) {
|
|
|
24624
23649
|
if (typeof value === "string") return "other";
|
|
24625
23650
|
return null;
|
|
24626
23651
|
}
|
|
24627
|
-
function parseProcessingState(value) {
|
|
23652
|
+
function parseProcessingState(value, stageCatalog = {}) {
|
|
24628
23653
|
const parsed = {};
|
|
24629
23654
|
const stageStatuses = {};
|
|
24630
23655
|
const knownStageStatuses = {};
|
|
@@ -24639,7 +23664,7 @@ function parseProcessingState(value) {
|
|
|
24639
23664
|
}
|
|
24640
23665
|
for (const [key, rawStatus] of Object.entries(value)) {
|
|
24641
23666
|
const parsedStatus = parseProcessingStageStatus(rawStatus);
|
|
24642
|
-
const isKnownStage = Boolean(
|
|
23667
|
+
const isKnownStage = Boolean(stageCatalog[key]);
|
|
24643
23668
|
if (!parsedStatus) {
|
|
24644
23669
|
unknownFields[key] = rawStatus;
|
|
24645
23670
|
continue;
|
|
@@ -24668,16 +23693,16 @@ function readLeadGenStateKey(row) {
|
|
|
24668
23693
|
const stateKey = row.stateKey ?? row.state_key;
|
|
24669
23694
|
return typeof stateKey === "string" && stateKey.length > 0 ? stateKey : null;
|
|
24670
23695
|
}
|
|
24671
|
-
function getDisplayLeadGenStageStateFor(row, entity) {
|
|
24672
|
-
const parsed = parseProcessingState(readLeadGenProcessingState(row));
|
|
24673
|
-
const latest = Object.values(
|
|
23696
|
+
function getDisplayLeadGenStageStateFor(row, entity, stageCatalog = {}) {
|
|
23697
|
+
const parsed = parseProcessingState(readLeadGenProcessingState(row), stageCatalog);
|
|
23698
|
+
const latest = Object.values(stageCatalog).filter((stage) => stage.entity === entity && parsed.knownStageStatuses[stage.key]).sort((a, b) => b.order - a.order)[0];
|
|
24674
23699
|
if (latest) {
|
|
24675
23700
|
return {
|
|
24676
23701
|
stageKey: latest.key,
|
|
24677
23702
|
stageStatus: parsed.knownStageStatuses[latest.key]
|
|
24678
23703
|
};
|
|
24679
23704
|
}
|
|
24680
|
-
const unknownStageKey = Object.keys(parsed.stageStatuses).find((stageKey) => !
|
|
23705
|
+
const unknownStageKey = Object.keys(parsed.stageStatuses).find((stageKey) => !stageCatalog[stageKey]);
|
|
24681
23706
|
if (unknownStageKey) {
|
|
24682
23707
|
return {
|
|
24683
23708
|
stageKey: unknownStageKey,
|
|
@@ -24685,55 +23710,22 @@ function getDisplayLeadGenStageStateFor(row, entity) {
|
|
|
24685
23710
|
};
|
|
24686
23711
|
}
|
|
24687
23712
|
const stateKey = readLeadGenStateKey(row);
|
|
24688
|
-
return stateKey &&
|
|
23713
|
+
return stateKey && stageCatalog[stateKey] ? { stageKey: stateKey, stageStatus: null } : { stageKey: null, stageStatus: null };
|
|
24689
23714
|
}
|
|
24690
23715
|
|
|
24691
23716
|
// src/features/lead-gen/build-state.ts
|
|
24692
23717
|
var ORPHAN_STAGE_ORDER = 9999;
|
|
24693
|
-
|
|
24694
|
-
function asRecord2(value) {
|
|
23718
|
+
function asRecord(value) {
|
|
24695
23719
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
24696
23720
|
}
|
|
24697
|
-
function
|
|
24698
|
-
const description = "description" in step && typeof step.description === "string" ? step.description : `Run ${step.label.toLowerCase()} for this list.`;
|
|
24699
|
-
return {
|
|
24700
|
-
...step,
|
|
24701
|
-
description,
|
|
24702
|
-
emptyBlockedText
|
|
24703
|
-
};
|
|
24704
|
-
}
|
|
24705
|
-
var MVP_BUILD_STEPS = [
|
|
24706
|
-
defineMvpBuildStep(
|
|
24707
|
-
PROSPECTING_STEPS2.localServices.sourceCompanies,
|
|
24708
|
-
"No company source has been configured or populated yet."
|
|
24709
|
-
),
|
|
24710
|
-
defineMvpBuildStep(
|
|
24711
|
-
PROSPECTING_STEPS2.localServices.analyzeWebsites,
|
|
24712
|
-
"Source companies before website analysis can run."
|
|
24713
|
-
),
|
|
24714
|
-
defineMvpBuildStep(
|
|
24715
|
-
PROSPECTING_STEPS2.localServices.qualifyCompanies,
|
|
24716
|
-
"Analyze websites before qualification can run."
|
|
24717
|
-
),
|
|
24718
|
-
defineMvpBuildStep(
|
|
24719
|
-
PROSPECTING_STEPS2.localServices.findContacts,
|
|
24720
|
-
"Qualify companies before contact discovery can run."
|
|
24721
|
-
),
|
|
24722
|
-
defineMvpBuildStep(PROSPECTING_STEPS2.localServices.verifyEmails, "Find contacts before email verification can run."),
|
|
24723
|
-
defineMvpBuildStep(PROSPECTING_STEPS2.localServices.personalize, "Verify emails before personalization can run."),
|
|
24724
|
-
defineMvpBuildStep(
|
|
24725
|
-
PROSPECTING_STEPS2.localServices.review,
|
|
24726
|
-
"Personalize contacts before records are ready for review."
|
|
24727
|
-
)
|
|
24728
|
-
];
|
|
24729
|
-
function sortStageKeys(keys) {
|
|
23721
|
+
function sortStageKeys(keys, stageCatalog = {}) {
|
|
24730
23722
|
return keys.slice().sort((a, b) => {
|
|
24731
|
-
const oa =
|
|
24732
|
-
const ob =
|
|
23723
|
+
const oa = stageCatalog[a]?.order ?? ORPHAN_STAGE_ORDER;
|
|
23724
|
+
const ob = stageCatalog[b]?.order ?? ORPHAN_STAGE_ORDER;
|
|
24733
23725
|
return oa - ob || a.localeCompare(b);
|
|
24734
23726
|
});
|
|
24735
23727
|
}
|
|
24736
|
-
function
|
|
23728
|
+
function getStageProgress(progress, step) {
|
|
24737
23729
|
return step.primaryEntity === "company" ? progress.byCompanyStage[step.stageKey] : progress.byContactStage[step.stageKey];
|
|
24738
23730
|
}
|
|
24739
23731
|
function getEntityTotal(progress, entity) {
|
|
@@ -24742,8 +23734,8 @@ function getEntityTotal(progress, entity) {
|
|
|
24742
23734
|
function findActionForStep(actions, step) {
|
|
24743
23735
|
return actions.find((action) => action.actionKey === step.actionKey) ?? actions.find((action) => action.stagesAffected?.includes(step.stageKey));
|
|
24744
23736
|
}
|
|
24745
|
-
function normalizeBuildPlanStep(step) {
|
|
24746
|
-
const fallback =
|
|
23737
|
+
function normalizeBuildPlanStep(step, fallbackSteps = []) {
|
|
23738
|
+
const fallback = fallbackSteps.find((item) => item.id === step.id || item.stageKey === step.stageKey);
|
|
24747
23739
|
return {
|
|
24748
23740
|
id: step.id,
|
|
24749
23741
|
label: step.label,
|
|
@@ -24769,17 +23761,19 @@ function isCurrentBuildPlanStep(step) {
|
|
|
24769
23761
|
const candidate = step;
|
|
24770
23762
|
return (candidate.primaryEntity === "company" || candidate.primaryEntity === "contact") && Array.isArray(candidate.outputs) && candidate.outputs.length > 0 && candidate.dependencyMode === "per-record-eligibility";
|
|
24771
23763
|
}
|
|
24772
|
-
function resolveBuildPlanSteps(list) {
|
|
23764
|
+
function resolveBuildPlanSteps(list, defaultBuildSteps = [], buildTemplates = []) {
|
|
24773
23765
|
const snapshot = list.metadata.buildPlanSnapshot;
|
|
24774
23766
|
const snapshotSteps = snapshot?.steps;
|
|
24775
23767
|
if (snapshotSteps?.length && snapshotSteps.every(isCurrentBuildPlanStep)) {
|
|
24776
|
-
return snapshotSteps.map(normalizeBuildPlanStep);
|
|
23768
|
+
return snapshotSteps.map((step) => normalizeBuildPlanStep(step, defaultBuildSteps));
|
|
24777
23769
|
}
|
|
24778
23770
|
if (snapshot?.templateId) {
|
|
24779
|
-
const templateSnapshot = createBuildPlanSnapshotFromTemplateId(snapshot.templateId);
|
|
24780
|
-
if (templateSnapshot?.steps.length)
|
|
23771
|
+
const templateSnapshot = createBuildPlanSnapshotFromTemplateId(snapshot.templateId, buildTemplates);
|
|
23772
|
+
if (templateSnapshot?.steps.length) {
|
|
23773
|
+
return templateSnapshot.steps.map((step) => normalizeBuildPlanStep(step, defaultBuildSteps));
|
|
23774
|
+
}
|
|
24781
23775
|
}
|
|
24782
|
-
return
|
|
23776
|
+
return defaultBuildSteps;
|
|
24783
23777
|
}
|
|
24784
23778
|
function getPrerequisiteSteps(step, byStepId) {
|
|
24785
23779
|
return (step.dependsOn ?? []).flatMap((dependencyId) => {
|
|
@@ -24825,19 +23819,20 @@ function isStageComplete(entry) {
|
|
|
24825
23819
|
return entry.error === 0 && entry.attempted >= entry.total && entry.success + entry.noResult + entry.skipped + entry.other >= entry.total;
|
|
24826
23820
|
}
|
|
24827
23821
|
function getExecutionInput(run2) {
|
|
24828
|
-
return
|
|
23822
|
+
return asRecord(run2.input);
|
|
24829
23823
|
}
|
|
24830
23824
|
function isCompletedRun(run2) {
|
|
24831
|
-
return run2.status === "completed" || run2.status === "success" || run2.status === "succeeded";
|
|
23825
|
+
return run2.status === "completed" || run2.status === "warning" || run2.status === "success" || run2.status === "succeeded";
|
|
24832
23826
|
}
|
|
24833
23827
|
function getApprovedCompanyIds(run2) {
|
|
24834
23828
|
const input = getExecutionInput(run2);
|
|
24835
23829
|
const raw = input.approvedCompanyIds;
|
|
24836
23830
|
return Array.isArray(raw) ? raw.filter((value) => typeof value === "string") : [];
|
|
24837
23831
|
}
|
|
24838
|
-
function hasApprovedExportRun(executions) {
|
|
23832
|
+
function hasApprovedExportRun(executions, exportWorkflowId) {
|
|
23833
|
+
if (!exportWorkflowId) return false;
|
|
24839
23834
|
return executions.some((run2) => {
|
|
24840
|
-
if (!isCompletedRun(run2) || run2.resourceId !==
|
|
23835
|
+
if (!isCompletedRun(run2) || run2.resourceId !== exportWorkflowId) return false;
|
|
24841
23836
|
const input = getExecutionInput(run2);
|
|
24842
23837
|
return input.approved === true || getApprovedCompanyIds(run2).length > 0;
|
|
24843
23838
|
});
|
|
@@ -24845,10 +23840,10 @@ function hasApprovedExportRun(executions) {
|
|
|
24845
23840
|
function hasCompletedSourcingRun(step, action, executions) {
|
|
24846
23841
|
return executions.some((run2) => isCompletedRun(run2) && run2.resourceId === (action?.resourceId ?? step.actionKey));
|
|
24847
23842
|
}
|
|
24848
|
-
function deriveBusinessProgress(list, progress, actions = [], executions = []) {
|
|
23843
|
+
function deriveBusinessProgress(list, progress, actions = [], executions = [], config = {}) {
|
|
24849
23844
|
const byCompanyStage = { ...progress.byCompanyStage };
|
|
24850
23845
|
const byContactStage = { ...progress.byContactStage };
|
|
24851
|
-
const steps = resolveBuildPlanSteps(list);
|
|
23846
|
+
const steps = resolveBuildPlanSteps(list, config.defaultBuildSteps, config.buildTemplates);
|
|
24852
23847
|
for (const step of steps) {
|
|
24853
23848
|
const stageProgress = step.primaryEntity === "company" ? byCompanyStage[step.stageKey] : byContactStage[step.stageKey];
|
|
24854
23849
|
if (stageProgress || (step.dependsOn?.length ?? 0) > 0 || !step.outputs.includes("company")) continue;
|
|
@@ -24858,9 +23853,9 @@ function deriveBusinessProgress(list, progress, actions = [], executions = []) {
|
|
|
24858
23853
|
byCompanyStage[step.stageKey] = createCompleteStageCounts(progress.totalCompanies);
|
|
24859
23854
|
}
|
|
24860
23855
|
}
|
|
24861
|
-
if (!isStageComplete(byCompanyStage.uploaded) && hasApprovedExportRun(executions)) {
|
|
23856
|
+
if (!isStageComplete(byCompanyStage.uploaded) && hasApprovedExportRun(executions, config.exportWorkflowId)) {
|
|
24862
23857
|
const exportedCount = Math.max(
|
|
24863
|
-
...executions.filter((run2) => isCompletedRun(run2) && run2.resourceId ===
|
|
23858
|
+
...executions.filter((run2) => isCompletedRun(run2) && run2.resourceId === config.exportWorkflowId).map((run2) => getApprovedCompanyIds(run2).length),
|
|
24864
23859
|
0
|
|
24865
23860
|
);
|
|
24866
23861
|
const total = exportedCount > 0 ? exportedCount : progress.totalCompanies;
|
|
@@ -24882,10 +23877,10 @@ function getStepRecommendedAction(step, action, kind) {
|
|
|
24882
23877
|
maxSize: step.maxBatchSize
|
|
24883
23878
|
};
|
|
24884
23879
|
}
|
|
24885
|
-
function deriveBuildStepStates(list, progress, actions) {
|
|
23880
|
+
function deriveBuildStepStates(list, progress, actions, defaultBuildSteps = [], buildTemplates = []) {
|
|
24886
23881
|
const byStepId = /* @__PURE__ */ new Map();
|
|
24887
|
-
for (const step of resolveBuildPlanSteps(list)) {
|
|
24888
|
-
const stageProgress =
|
|
23882
|
+
for (const step of resolveBuildPlanSteps(list, defaultBuildSteps, buildTemplates)) {
|
|
23883
|
+
const stageProgress = getStageProgress(progress, step);
|
|
24889
23884
|
const entityTotal = getEntityTotal(progress, step.primaryEntity);
|
|
24890
23885
|
const prerequisites = getPrerequisiteSteps(step, byStepId);
|
|
24891
23886
|
const hasDependencies = (step.dependsOn?.length ?? 0) > 0;
|
|
@@ -24896,9 +23891,10 @@ function deriveBuildStepStates(list, progress, actions) {
|
|
|
24896
23891
|
const failed = stageProgress?.error ?? 0;
|
|
24897
23892
|
const ready = Math.max(0, eligibleTotal - complete - failed);
|
|
24898
23893
|
const blocked = hasDependencies ? Math.max(total - eligibleTotal - complete - failed, 0) : 0;
|
|
24899
|
-
const status = failed > 0 ? "failed" : ready > 0 ? "ready" : blocked > 0 || total === 0 ? "blocked" : "complete";
|
|
24900
23894
|
const action = findActionForStep(actions, step);
|
|
24901
23895
|
const nextActionKind = getStepActionKind(step, ready, failed, action);
|
|
23896
|
+
const isActionableEmptySeedStep = !hasDependencies && total === 0 && nextActionKind === "run_next_batch";
|
|
23897
|
+
const status = failed > 0 ? "failed" : ready > 0 || isActionableEmptySeedStep ? "ready" : blocked > 0 || total === 0 ? "blocked" : "complete";
|
|
24902
23898
|
const state = {
|
|
24903
23899
|
...step,
|
|
24904
23900
|
status,
|
|
@@ -24917,8 +23913,8 @@ function deriveBuildStepStates(list, progress, actions) {
|
|
|
24917
23913
|
function getRecommendedBuildStep(steps) {
|
|
24918
23914
|
return steps.find((step) => step.nextActionKind === "retry_failed") ?? steps.find((step) => step.nextActionKind === "run_next_batch") ?? null;
|
|
24919
23915
|
}
|
|
24920
|
-
function resolveBuildState(list, progress, actions) {
|
|
24921
|
-
const steps = deriveBuildStepStates(list, progress, actions);
|
|
23916
|
+
function resolveBuildState(list, progress, actions, config = {}) {
|
|
23917
|
+
const steps = deriveBuildStepStates(list, progress, actions, config.defaultBuildSteps, config.buildTemplates);
|
|
24922
23918
|
const recommendedStep = getRecommendedBuildStep(steps);
|
|
24923
23919
|
return {
|
|
24924
23920
|
steps,
|
|
@@ -24926,8 +23922,11 @@ function resolveBuildState(list, progress, actions) {
|
|
|
24926
23922
|
recommendedAction: recommendedStep?.recommendedAction ?? null
|
|
24927
23923
|
};
|
|
24928
23924
|
}
|
|
24929
|
-
var
|
|
24930
|
-
|
|
23925
|
+
var DATA_MODE_OPTIONS2 = [
|
|
23926
|
+
{ value: "mock", label: "Mock data" },
|
|
23927
|
+
{ value: "live", label: "Live data" }
|
|
23928
|
+
];
|
|
23929
|
+
function formatDateTime4(value) {
|
|
24931
23930
|
if (!value) return "Not yet";
|
|
24932
23931
|
return new Date(value).toLocaleString("en-US", {
|
|
24933
23932
|
month: "short",
|
|
@@ -24941,7 +23940,7 @@ function contactDisplayName(firstName, lastName) {
|
|
|
24941
23940
|
const full = [firstName, lastName].filter(Boolean).join(" ").trim();
|
|
24942
23941
|
return full || "\u2014";
|
|
24943
23942
|
}
|
|
24944
|
-
function
|
|
23943
|
+
function getStatusColor6(status) {
|
|
24945
23944
|
switch (status) {
|
|
24946
23945
|
case "draft":
|
|
24947
23946
|
return "gray";
|
|
@@ -24957,22 +23956,25 @@ function getStatusColor7(status) {
|
|
|
24957
23956
|
return "gray";
|
|
24958
23957
|
}
|
|
24959
23958
|
}
|
|
24960
|
-
function
|
|
24961
|
-
|
|
23959
|
+
function getListDataMode(list) {
|
|
23960
|
+
return list.pipelineConfig?.dataMode === "live" ? "live" : "mock";
|
|
23961
|
+
}
|
|
23962
|
+
function getMemberStateColor2(stateKey, stageCatalog) {
|
|
23963
|
+
const stage = stageCatalog[stateKey];
|
|
24962
23964
|
if (stage?.entity === "contact") return "green";
|
|
24963
23965
|
if (stage?.entity === "company") return "blue";
|
|
24964
23966
|
return "gray";
|
|
24965
23967
|
}
|
|
24966
|
-
function displayMemberStageFor(row, kind) {
|
|
24967
|
-
const stage = getDisplayLeadGenStageStateFor(row, kind);
|
|
23968
|
+
function displayMemberStageFor(row, kind, stageCatalog) {
|
|
23969
|
+
const stage = getDisplayLeadGenStageStateFor(row, kind, stageCatalog);
|
|
24968
23970
|
if (!stage.stageKey) return null;
|
|
24969
|
-
const catalogStage =
|
|
23971
|
+
const catalogStage = stageCatalog[stage.stageKey];
|
|
24970
23972
|
return {
|
|
24971
23973
|
key: stage.stageKey,
|
|
24972
23974
|
label: catalogStage?.label ?? stage.stageKey
|
|
24973
23975
|
};
|
|
24974
23976
|
}
|
|
24975
|
-
function
|
|
23977
|
+
function asRecord2(value) {
|
|
24976
23978
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
24977
23979
|
}
|
|
24978
23980
|
function valueAtPath(source, path) {
|
|
@@ -25025,14 +24027,14 @@ function getRecordColumnSource(row) {
|
|
|
25025
24027
|
}
|
|
25026
24028
|
function getStageEntry(row, stageKey) {
|
|
25027
24029
|
const entry = valueAtPath(row.processingState, stageKey);
|
|
25028
|
-
return
|
|
24030
|
+
return asRecord2(entry);
|
|
25029
24031
|
}
|
|
25030
24032
|
function getRecordStageStatus(row, stageKey) {
|
|
25031
24033
|
const status = getStageEntry(row, stageKey).status;
|
|
25032
24034
|
return typeof status === "string" ? status : "pending";
|
|
25033
24035
|
}
|
|
25034
24036
|
function getStageFailureReason(row, stageKey) {
|
|
25035
|
-
const data =
|
|
24037
|
+
const data = asRecord2(getStageEntry(row, stageKey).data);
|
|
25036
24038
|
const error = data.error ?? data.reason ?? data.failureReason ?? data.disqualifiedReason;
|
|
25037
24039
|
return compactText(error);
|
|
25038
24040
|
}
|
|
@@ -25060,7 +24062,7 @@ function renderRecordValue(value, column) {
|
|
|
25060
24062
|
case "badge":
|
|
25061
24063
|
return /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: column.badgeColor ?? getRecordStatusColor(String(value)), children: compactText(value) });
|
|
25062
24064
|
case "datetime":
|
|
25063
|
-
return compactText(typeof value === "string" ?
|
|
24065
|
+
return compactText(typeof value === "string" ? formatDateTime4(value) : value);
|
|
25064
24066
|
case "count":
|
|
25065
24067
|
return Array.isArray(value) ? value.length : compactText(value);
|
|
25066
24068
|
case "json":
|
|
@@ -25088,33 +24090,32 @@ function getRunStatusColor(status) {
|
|
|
25088
24090
|
return "gray";
|
|
25089
24091
|
}
|
|
25090
24092
|
}
|
|
24093
|
+
function isRunInFlight(status) {
|
|
24094
|
+
return status === "running" || status === "pending" || status === "queued";
|
|
24095
|
+
}
|
|
24096
|
+
function isRunTerminal(status) {
|
|
24097
|
+
return !isRunInFlight(status);
|
|
24098
|
+
}
|
|
25091
24099
|
function getRunInput(run2) {
|
|
25092
|
-
const payload =
|
|
24100
|
+
const payload = asRecord2(run2.payload);
|
|
25093
24101
|
return run2.input ?? run2.inputs ?? payload.input ?? payload.inputs;
|
|
25094
24102
|
}
|
|
25095
24103
|
function hasRunInput(run2) {
|
|
25096
24104
|
const input = getRunInput(run2);
|
|
25097
24105
|
return input !== void 0 && input !== null;
|
|
25098
24106
|
}
|
|
25099
|
-
function sanitizeStepInput(value,
|
|
25100
|
-
return value;
|
|
24107
|
+
function sanitizeStepInput(value, actionKey) {
|
|
24108
|
+
if (actionKey === "lead-gen.export.list") return value;
|
|
24109
|
+
const next = { ...value };
|
|
24110
|
+
delete next.mode;
|
|
24111
|
+
return next;
|
|
25101
24112
|
}
|
|
25102
24113
|
function getDefaultStepInput(list, action) {
|
|
25103
|
-
return
|
|
24114
|
+
return asRecord2(action?.defaultInput?.(list));
|
|
25104
24115
|
}
|
|
25105
24116
|
function getInitialStepInput(list, action) {
|
|
25106
24117
|
return getDefaultStepInput(list, action);
|
|
25107
24118
|
}
|
|
25108
|
-
function mergeStepRunInput(list, action, inputAtSubmit) {
|
|
25109
|
-
return {
|
|
25110
|
-
...getDefaultStepInput(list, action),
|
|
25111
|
-
...inputAtSubmit
|
|
25112
|
-
};
|
|
25113
|
-
}
|
|
25114
|
-
var EMPTY_SELECTION2 = {
|
|
25115
|
-
selectedCompanyIds: [],
|
|
25116
|
-
selectedContactIds: []
|
|
25117
|
-
};
|
|
25118
24119
|
function getStageStatus(entry) {
|
|
25119
24120
|
if (!entry || (entry.total ?? 0) === 0) return "not-started";
|
|
25120
24121
|
if ((entry.error ?? 0) > 0) return "errors";
|
|
@@ -25160,9 +24161,10 @@ function StageNode({
|
|
|
25160
24161
|
index,
|
|
25161
24162
|
stageKey,
|
|
25162
24163
|
fallbackLabel,
|
|
25163
|
-
entry
|
|
24164
|
+
entry,
|
|
24165
|
+
stageCatalog
|
|
25164
24166
|
}) {
|
|
25165
|
-
const label =
|
|
24167
|
+
const label = stageCatalog[stageKey]?.label ?? fallbackLabel ?? stageKey;
|
|
25166
24168
|
const status = getStageStatus(entry);
|
|
25167
24169
|
const colors = getStageColors(status);
|
|
25168
24170
|
const total = entry?.total ?? 0;
|
|
@@ -25234,9 +24236,10 @@ function StageNode({
|
|
|
25234
24236
|
function PipelineStepper({
|
|
25235
24237
|
plannedSteps,
|
|
25236
24238
|
byStage,
|
|
25237
|
-
emptyText
|
|
24239
|
+
emptyText,
|
|
24240
|
+
stageCatalog
|
|
25238
24241
|
}) {
|
|
25239
|
-
const stageKeys = plannedSteps.length > 0 ? plannedSteps.map((s) => s.stageKey) : sortStageKeys(Object.keys(byStage));
|
|
24242
|
+
const stageKeys = plannedSteps.length > 0 ? plannedSteps.map((s) => s.stageKey) : sortStageKeys(Object.keys(byStage), stageCatalog);
|
|
25240
24243
|
const labelByKey = new Map(plannedSteps.map((s) => [s.stageKey, s.label]));
|
|
25241
24244
|
if (stageKeys.length === 0) {
|
|
25242
24245
|
return /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: emptyText });
|
|
@@ -25265,13 +24268,28 @@ function PipelineStepper({
|
|
|
25265
24268
|
}
|
|
25266
24269
|
}
|
|
25267
24270
|
),
|
|
25268
|
-
stageKeys.map((key, index) => /* @__PURE__ */ jsx(
|
|
24271
|
+
stageKeys.map((key, index) => /* @__PURE__ */ jsx(
|
|
24272
|
+
StageNode,
|
|
24273
|
+
{
|
|
24274
|
+
index,
|
|
24275
|
+
stageKey: key,
|
|
24276
|
+
fallbackLabel: labelByKey.get(key),
|
|
24277
|
+
entry: byStage[key],
|
|
24278
|
+
stageCatalog
|
|
24279
|
+
},
|
|
24280
|
+
key
|
|
24281
|
+
))
|
|
25269
24282
|
]
|
|
25270
24283
|
}
|
|
25271
24284
|
) });
|
|
25272
24285
|
}
|
|
25273
|
-
function PipelineStagesCard({
|
|
25274
|
-
|
|
24286
|
+
function PipelineStagesCard({
|
|
24287
|
+
list,
|
|
24288
|
+
progress,
|
|
24289
|
+
leadGenConfig
|
|
24290
|
+
}) {
|
|
24291
|
+
const stageCatalog = leadGenConfig.stageCatalog ?? {};
|
|
24292
|
+
const plannedSteps = resolveBuildPlanSteps(list, leadGenConfig.defaultBuildSteps, leadGenConfig.buildTemplates);
|
|
25275
24293
|
const templateLabel = list.metadata.buildPlanSnapshot?.templateLabel;
|
|
25276
24294
|
const combinedByStage = { ...progress.byCompanyStage, ...progress.byContactStage };
|
|
25277
24295
|
const hasAnyContent = plannedSteps.length > 0 || Object.keys(combinedByStage).length > 0;
|
|
@@ -25285,14 +24303,14 @@ function PipelineStagesCard({ list, progress }) {
|
|
|
25285
24303
|
] })
|
|
25286
24304
|
] }),
|
|
25287
24305
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
25288
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color:
|
|
24306
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor6(list.status), children: list.status }),
|
|
25289
24307
|
list.launchedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
25290
24308
|
"Launched ",
|
|
25291
|
-
|
|
24309
|
+
formatDateTime4(list.launchedAt)
|
|
25292
24310
|
] }),
|
|
25293
24311
|
list.completedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
25294
24312
|
"Completed ",
|
|
25295
|
-
|
|
24313
|
+
formatDateTime4(list.completedAt)
|
|
25296
24314
|
] })
|
|
25297
24315
|
] })
|
|
25298
24316
|
] }),
|
|
@@ -25309,25 +24327,49 @@ function PipelineStagesCard({ list, progress }) {
|
|
|
25309
24327
|
{
|
|
25310
24328
|
plannedSteps,
|
|
25311
24329
|
byStage: combinedByStage,
|
|
25312
|
-
emptyText: "No pipeline activity recorded yet."
|
|
24330
|
+
emptyText: "No pipeline activity recorded yet.",
|
|
24331
|
+
stageCatalog
|
|
25313
24332
|
}
|
|
25314
24333
|
)
|
|
25315
24334
|
] })
|
|
25316
24335
|
] }) });
|
|
25317
24336
|
}
|
|
25318
24337
|
function ListConfigCard({ list }) {
|
|
24338
|
+
const updateListConfig = useUpdateListConfig(list.id);
|
|
25319
24339
|
const icp = list.icp ?? {};
|
|
25320
24340
|
const scraping = list.scrapingConfig ?? {};
|
|
25321
24341
|
const hasIcp = Object.values(icp).some((v) => v !== void 0 && v !== null && v !== "");
|
|
25322
24342
|
const hasScraping = Object.values(scraping).some((v) => v !== void 0 && v !== null && v !== "");
|
|
25323
|
-
|
|
25324
|
-
|
|
25325
|
-
|
|
25326
|
-
|
|
25327
|
-
|
|
25328
|
-
|
|
24343
|
+
const dataMode = getListDataMode(list);
|
|
24344
|
+
const handleDataModeChange = (value) => {
|
|
24345
|
+
if (value !== "mock" && value !== "live") return;
|
|
24346
|
+
if (value === dataMode) return;
|
|
24347
|
+
updateListConfig.mutate({
|
|
24348
|
+
pipelineConfig: {
|
|
24349
|
+
dataMode: value
|
|
24350
|
+
}
|
|
24351
|
+
});
|
|
24352
|
+
};
|
|
25329
24353
|
return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
25330
|
-
/* @__PURE__ */
|
|
24354
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-end", gap: "sm", children: [
|
|
24355
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
24356
|
+
/* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
|
|
24357
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Data Mode applies to sourcing, enrichment, and research steps." })
|
|
24358
|
+
] }),
|
|
24359
|
+
/* @__PURE__ */ jsx(
|
|
24360
|
+
Select,
|
|
24361
|
+
{
|
|
24362
|
+
label: "Data Mode",
|
|
24363
|
+
data: DATA_MODE_OPTIONS2,
|
|
24364
|
+
value: dataMode,
|
|
24365
|
+
onChange: handleDataModeChange,
|
|
24366
|
+
disabled: updateListConfig.isPending,
|
|
24367
|
+
w: 180,
|
|
24368
|
+
size: "xs"
|
|
24369
|
+
}
|
|
24370
|
+
)
|
|
24371
|
+
] }),
|
|
24372
|
+
!hasIcp && !hasScraping && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No ICP rubric or scraping criteria recorded for this list." }),
|
|
25331
24373
|
(hasIcp || hasScraping) && /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
|
|
25332
24374
|
hasIcp && /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
25333
24375
|
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "ICP Rubric" }),
|
|
@@ -25383,7 +24425,11 @@ function ListConfigCard({ list }) {
|
|
|
25383
24425
|
] })
|
|
25384
24426
|
] }) });
|
|
25385
24427
|
}
|
|
25386
|
-
function OverviewTab({
|
|
24428
|
+
function OverviewTab({
|
|
24429
|
+
list,
|
|
24430
|
+
progress,
|
|
24431
|
+
leadGenConfig
|
|
24432
|
+
}) {
|
|
25387
24433
|
const hasMetadata = list.metadata && Object.keys(list.metadata).length > 0;
|
|
25388
24434
|
return /* @__PURE__ */ jsxs(
|
|
25389
24435
|
TabSection,
|
|
@@ -25396,7 +24442,7 @@ function OverviewTab({ list, progress }) {
|
|
|
25396
24442
|
/* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
|
|
25397
24443
|
/* @__PURE__ */ jsx(StatCard, { label: "Members", value: progress.totalMembers, icon: IconUsers })
|
|
25398
24444
|
] }),
|
|
25399
|
-
/* @__PURE__ */ jsx(PipelineStagesCard, { list, progress }),
|
|
24445
|
+
/* @__PURE__ */ jsx(PipelineStagesCard, { list, progress, leadGenConfig }),
|
|
25400
24446
|
/* @__PURE__ */ jsx(ListConfigCard, { list }),
|
|
25401
24447
|
hasMetadata && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
25402
24448
|
/* @__PURE__ */ jsx(Title, { order: 5, children: "Metadata" }),
|
|
@@ -25458,7 +24504,14 @@ function StatusPill({ label, tone }) {
|
|
|
25458
24504
|
}
|
|
25459
24505
|
);
|
|
25460
24506
|
}
|
|
25461
|
-
function StepCounterLine({ step }) {
|
|
24507
|
+
function StepCounterLine({ step, isRunning = false }) {
|
|
24508
|
+
if (isRunning) {
|
|
24509
|
+
const processed = step.complete > 0 ? `${step.complete} processed` : "processing";
|
|
24510
|
+
return /* @__PURE__ */ jsxs(Text, { size: "xs", fw: 700, style: { color: "var(--color-primary)" }, children: [
|
|
24511
|
+
"Running - ",
|
|
24512
|
+
processed
|
|
24513
|
+
] });
|
|
24514
|
+
}
|
|
25462
24515
|
const items = [
|
|
25463
24516
|
step.ready > 0 ? { label: "ready", value: step.ready, color: "var(--color-primary)" } : null,
|
|
25464
24517
|
step.complete > 0 ? { label: "done", value: step.complete, color: "var(--color-success)" } : null,
|
|
@@ -25474,9 +24527,9 @@ function StepCounterLine({ step }) {
|
|
|
25474
24527
|
item.label
|
|
25475
24528
|
] }, item.label)) });
|
|
25476
24529
|
}
|
|
25477
|
-
function BuildStepProgressBar({ step }) {
|
|
24530
|
+
function BuildStepProgressBar({ step, isRunning = false }) {
|
|
25478
24531
|
const segments = [
|
|
25479
|
-
{ key: "complete", value: step.complete, color: "var(--color-success)" },
|
|
24532
|
+
{ key: "complete", value: step.complete, color: isRunning ? "var(--color-primary)" : "var(--color-success)" },
|
|
25480
24533
|
{ key: "ready", value: step.ready, color: "var(--color-primary)" },
|
|
25481
24534
|
{ key: "failed", value: step.failed, color: "var(--color-error)" },
|
|
25482
24535
|
{ key: "blocked", value: step.blocked, color: "var(--color-border)" }
|
|
@@ -25486,7 +24539,7 @@ function BuildStepProgressBar({ step }) {
|
|
|
25486
24539
|
Box,
|
|
25487
24540
|
{
|
|
25488
24541
|
h: 8,
|
|
25489
|
-
"aria-label": `${step.label} progress: ${step.complete} complete, ${step.ready} ready, ${step.failed} failed, ${step.blocked} blocked`,
|
|
24542
|
+
"aria-label": `${step.label} progress: ${step.complete} ${isRunning ? "processed" : "complete"}, ${step.ready} ready, ${step.failed} failed, ${step.blocked} blocked`,
|
|
25490
24543
|
style: {
|
|
25491
24544
|
backgroundColor: "color-mix(in srgb, var(--color-border) 65%, transparent)",
|
|
25492
24545
|
borderRadius: 999,
|
|
@@ -25500,8 +24553,9 @@ function BuildStepProgressBar({ step }) {
|
|
|
25500
24553
|
function getDisplayStep(steps, recommendedStep) {
|
|
25501
24554
|
return recommendedStep ?? steps.find((step) => step.status !== "complete") ?? steps[steps.length - 1] ?? null;
|
|
25502
24555
|
}
|
|
25503
|
-
function getBuildTabDescription(steps, currentStep) {
|
|
24556
|
+
function getBuildTabDescription(steps, currentStep, runningStep = null) {
|
|
25504
24557
|
if (!steps.length) return "No build steps are available for this list.";
|
|
24558
|
+
if (runningStep) return `${runningStep.label} is running.`;
|
|
25505
24559
|
if (steps.every((step) => step.status === "complete")) return "List build complete.";
|
|
25506
24560
|
if (!currentStep) return "No build steps need attention right now.";
|
|
25507
24561
|
if (currentStep.status === "ready") return `${currentStep.label} is ready to run.`;
|
|
@@ -25509,7 +24563,6 @@ function getBuildTabDescription(steps, currentStep) {
|
|
|
25509
24563
|
return `${currentStep.label} is waiting on earlier work.`;
|
|
25510
24564
|
}
|
|
25511
24565
|
var RECORDS_PAGE_SIZE = 25;
|
|
25512
|
-
var EXPORT_WORKFLOW_ID = "lgn-06-export-list-workflow";
|
|
25513
24566
|
function setValueAtInputPath(source, path, value) {
|
|
25514
24567
|
const segments = path.split(".").filter(Boolean);
|
|
25515
24568
|
if (!segments.length) return source;
|
|
@@ -25527,19 +24580,6 @@ function setValueAtInputPath(source, path, value) {
|
|
|
25527
24580
|
});
|
|
25528
24581
|
return next;
|
|
25529
24582
|
}
|
|
25530
|
-
function credentialMatchesRequirement(credential, requirement) {
|
|
25531
|
-
const provider = requirement.provider.toLowerCase();
|
|
25532
|
-
const credentialProvider = credential.provider?.toLowerCase() ?? "";
|
|
25533
|
-
const credentialType = credential.type.toLowerCase();
|
|
25534
|
-
const credentialName = credential.name.toLowerCase();
|
|
25535
|
-
if (credentialProvider === provider || credentialType === provider || credentialName.startsWith(`${provider}-`) || credentialName.includes(`-${provider}`) || credentialName.includes(`${provider}-`)) {
|
|
25536
|
-
return true;
|
|
25537
|
-
}
|
|
25538
|
-
return credentialType === requirement.credentialType;
|
|
25539
|
-
}
|
|
25540
|
-
function getMatchingCredentials(credentials, requirement) {
|
|
25541
|
-
return credentials.filter((credential) => credentialMatchesRequirement(credential, requirement));
|
|
25542
|
-
}
|
|
25543
24583
|
function getSelectedCredential(credentials, selections, requirement) {
|
|
25544
24584
|
const selectedId = selections[requirement.key];
|
|
25545
24585
|
return credentials.find((credential) => credential.id === selectedId) ?? null;
|
|
@@ -25577,6 +24617,7 @@ function CredentialRequirementsPanel({
|
|
|
25577
24617
|
requirements,
|
|
25578
24618
|
credentials,
|
|
25579
24619
|
credentialsLoading,
|
|
24620
|
+
credentialsError,
|
|
25580
24621
|
selections,
|
|
25581
24622
|
verificationByCredentialId,
|
|
25582
24623
|
verifyingCredentialId,
|
|
@@ -25587,9 +24628,9 @@ function CredentialRequirementsPanel({
|
|
|
25587
24628
|
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
25588
24629
|
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: "Credentials" }),
|
|
25589
24630
|
requirements.map((requirement) => {
|
|
25590
|
-
const matchingCredentials = getMatchingCredentials(credentials, requirement);
|
|
25591
24631
|
const selectedCredential = getSelectedCredential(credentials, selections, requirement);
|
|
25592
24632
|
const verification = selectedCredential ? verificationByCredentialId[selectedCredential.id] : null;
|
|
24633
|
+
const credentialsUnavailable = Boolean(credentialsError) && credentials.length === 0;
|
|
25593
24634
|
return /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
25594
24635
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", align: "flex-end", wrap: "nowrap", children: [
|
|
25595
24636
|
/* @__PURE__ */ jsx(
|
|
@@ -25597,8 +24638,8 @@ function CredentialRequirementsPanel({
|
|
|
25597
24638
|
{
|
|
25598
24639
|
label: requirement.label,
|
|
25599
24640
|
description: `${requirement.provider} credential for ${requirement.inputPath}`,
|
|
25600
|
-
placeholder: credentialsLoading ? "Loading credentials..." : "Select credential",
|
|
25601
|
-
data:
|
|
24641
|
+
placeholder: credentialsLoading ? "Loading credentials..." : credentialsUnavailable ? "Credentials unavailable" : "Select credential",
|
|
24642
|
+
data: credentials.map((credential) => ({
|
|
25602
24643
|
value: credential.id,
|
|
25603
24644
|
label: `${credential.name} (${credential.provider ?? credential.type})`
|
|
25604
24645
|
})),
|
|
@@ -25607,7 +24648,7 @@ function CredentialRequirementsPanel({
|
|
|
25607
24648
|
onSelect(requirement, credentials.find((credential) => credential.id === credentialId) ?? null);
|
|
25608
24649
|
},
|
|
25609
24650
|
required: requirement.required,
|
|
25610
|
-
disabled: credentialsLoading ||
|
|
24651
|
+
disabled: credentialsLoading || credentialsUnavailable || credentials.length === 0,
|
|
25611
24652
|
style: { flex: 1 }
|
|
25612
24653
|
}
|
|
25613
24654
|
),
|
|
@@ -25623,16 +24664,17 @@ function CredentialRequirementsPanel({
|
|
|
25623
24664
|
}
|
|
25624
24665
|
)
|
|
25625
24666
|
] }),
|
|
25626
|
-
|
|
24667
|
+
credentialsUnavailable ? /* @__PURE__ */ jsx(Alert, { color: "red", variant: "light", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
24668
|
+
"Credentials could not be loaded. ",
|
|
24669
|
+
credentialsError?.message ?? "Refresh the page and try again."
|
|
24670
|
+
] }) }) : !credentialsLoading && credentials.length === 0 ? /* @__PURE__ */ jsx(
|
|
25627
24671
|
Alert,
|
|
25628
24672
|
{
|
|
25629
24673
|
color: requirement.required ? "yellow" : "gray",
|
|
25630
24674
|
variant: "light",
|
|
25631
24675
|
icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }),
|
|
25632
24676
|
children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
25633
|
-
"No
|
|
25634
|
-
requirement.provider,
|
|
25635
|
-
" credentials found. Add one in",
|
|
24677
|
+
"No credentials found. Add one in",
|
|
25636
24678
|
" ",
|
|
25637
24679
|
/* @__PURE__ */ jsx(Text, { component: "a", href: "/settings/credentials", size: "sm", fw: 600, children: "Settings -> Credentials" }),
|
|
25638
24680
|
"."
|
|
@@ -25649,7 +24691,7 @@ function CredentialRequirementsPanel({
|
|
|
25649
24691
|
/* @__PURE__ */ jsx(Text, { size: "sm", children: verification.message }),
|
|
25650
24692
|
verification.checkedAt ? /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
25651
24693
|
"Checked ",
|
|
25652
|
-
|
|
24694
|
+
formatDateTime4(verification.checkedAt)
|
|
25653
24695
|
] }) : null,
|
|
25654
24696
|
formatCredentialVerificationDetails(verification.details) ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatCredentialVerificationDetails(verification.details) }) : null
|
|
25655
24697
|
] })
|
|
@@ -25660,32 +24702,54 @@ function CredentialRequirementsPanel({
|
|
|
25660
24702
|
] });
|
|
25661
24703
|
}
|
|
25662
24704
|
function BuildStepRunningWatcher({
|
|
24705
|
+
listId,
|
|
25663
24706
|
resourceId,
|
|
25664
24707
|
onRunningChange
|
|
25665
24708
|
}) {
|
|
24709
|
+
const queryClient = useQueryClient();
|
|
24710
|
+
const { workOSOrganizationId } = useElevasisServices();
|
|
24711
|
+
const [wasRunning, setWasRunning] = useState(false);
|
|
25666
24712
|
const inFlightQuery = useInFlightExecutions(resourceId, {
|
|
25667
24713
|
enabled: Boolean(resourceId),
|
|
25668
24714
|
limit: 5,
|
|
24715
|
+
listId,
|
|
25669
24716
|
refetchInterval: 2e3
|
|
25670
24717
|
});
|
|
25671
24718
|
const isRunning = (inFlightQuery.data?.executions.length ?? 0) > 0;
|
|
24719
|
+
useExecutionSSE(resourceId, {
|
|
24720
|
+
enabled: Boolean(resourceId) && isRunning,
|
|
24721
|
+
listId
|
|
24722
|
+
});
|
|
25672
24723
|
useEffect(() => {
|
|
24724
|
+
if (!inFlightQuery.isFetched) return;
|
|
25673
24725
|
onRunningChange(resourceId, isRunning);
|
|
24726
|
+
if (wasRunning && !isRunning) {
|
|
24727
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.executionsBase(workOSOrganizationId, listId) });
|
|
24728
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.progress(workOSOrganizationId, listId) });
|
|
24729
|
+
}
|
|
24730
|
+
setWasRunning(isRunning);
|
|
25674
24731
|
return () => onRunningChange(resourceId, false);
|
|
25675
|
-
}, [
|
|
24732
|
+
}, [
|
|
24733
|
+
inFlightQuery.isFetched,
|
|
24734
|
+
isRunning,
|
|
24735
|
+
listId,
|
|
24736
|
+
onRunningChange,
|
|
24737
|
+
queryClient,
|
|
24738
|
+
resourceId,
|
|
24739
|
+
wasRunning,
|
|
24740
|
+
workOSOrganizationId
|
|
24741
|
+
]);
|
|
25676
24742
|
return null;
|
|
25677
24743
|
}
|
|
25678
24744
|
function StepRecordsPanel({
|
|
25679
24745
|
list,
|
|
25680
24746
|
step,
|
|
25681
|
-
|
|
25682
|
-
|
|
25683
|
-
|
|
24747
|
+
exportWorkflowId,
|
|
24748
|
+
stageCatalog,
|
|
24749
|
+
approvalByCompanyId,
|
|
24750
|
+
onApprovalChange
|
|
25684
24751
|
}) {
|
|
25685
|
-
const queryClient = useQueryClient();
|
|
25686
24752
|
const [page, setPage] = useState(1);
|
|
25687
|
-
const [approvalByCompanyId, setApprovalByCompanyId] = useState({});
|
|
25688
|
-
const navigate = useNavigate();
|
|
25689
24753
|
const recordsStageKey = step.recordSourceStageKey ?? step.recordsStageKey ?? step.stageKey;
|
|
25690
24754
|
const recordsEntity = step.recordEntity ?? step.primaryEntity;
|
|
25691
24755
|
const columns = step.recordColumns?.[recordsEntity] ?? [];
|
|
@@ -25695,59 +24759,19 @@ function StepRecordsPanel({
|
|
|
25695
24759
|
limit: RECORDS_PAGE_SIZE,
|
|
25696
24760
|
offset: (page - 1) * RECORDS_PAGE_SIZE
|
|
25697
24761
|
});
|
|
25698
|
-
const exportWorkflowId = step.action?.resourceId ?? EXPORT_WORKFLOW_ID;
|
|
25699
|
-
const exportExecution = useWorkflowExecution({
|
|
25700
|
-
workflowId: exportWorkflowId,
|
|
25701
|
-
listId: list.id
|
|
25702
|
-
});
|
|
25703
24762
|
useEffect(() => {
|
|
25704
24763
|
setPage(1);
|
|
25705
|
-
setApprovalByCompanyId({});
|
|
25706
24764
|
}, [step.id]);
|
|
25707
24765
|
const rows = recordsQuery.data?.data ?? [];
|
|
25708
24766
|
const total = recordsQuery.data?.total ?? 0;
|
|
25709
24767
|
const totalPages = Math.max(1, Math.ceil(total / RECORDS_PAGE_SIZE));
|
|
25710
|
-
const isReviewExportStep = step.primaryEntity === "company" && (step.actionKey === "lead-gen.export.list" ||
|
|
24768
|
+
const isReviewExportStep = step.primaryEntity === "company" && (step.actionKey === "lead-gen.export.list" || step.action?.resourceId === exportWorkflowId);
|
|
25711
24769
|
const approvedCompanyIds = Object.entries(approvalByCompanyId).filter(([, status]) => status === "approved").map(([companyId]) => companyId);
|
|
25712
24770
|
const rejectedCompanyIds = Object.entries(approvalByCompanyId).filter(([, status]) => status === "rejected").map(([companyId]) => companyId);
|
|
25713
|
-
const clickupRequirement = getClickUpRequirement(step);
|
|
25714
|
-
const clickupCredential = clickupRequirement ? getSelectedCredential(credentials, credentialSelections, clickupRequirement) : null;
|
|
25715
|
-
const isClickUpExportPath = isReviewExportStep && Boolean(clickupRequirement);
|
|
25716
|
-
const normalizedClickupListId = clickupListId.trim();
|
|
25717
|
-
const canExport = approvedCompanyIds.length > 0 && (!isClickUpExportPath || Boolean(clickupCredential) && normalizedClickupListId.length > 0);
|
|
25718
|
-
const exportDisabledReason = approvedCompanyIds.length === 0 ? "Approve at least one company before export." : isClickUpExportPath && !clickupCredential ? "Select a ClickUp credential in Configuration." : isClickUpExportPath && !normalizedClickupListId ? "Enter a ClickUp List ID in Configuration." : null;
|
|
25719
24771
|
const setApproval = (companyId, status) => {
|
|
25720
|
-
|
|
25721
|
-
};
|
|
25722
|
-
const openRecordDetail = (row) => {
|
|
25723
|
-
if (row.entity === "company") {
|
|
25724
|
-
void navigate({ to: "/crm/companies/$companyId", params: { companyId: row.companyId } });
|
|
25725
|
-
return;
|
|
25726
|
-
}
|
|
25727
|
-
void navigate({ to: "/crm/contacts/$contactId", params: { contactId: row.contactId } });
|
|
25728
|
-
};
|
|
25729
|
-
const exportApproved = async () => {
|
|
25730
|
-
try {
|
|
25731
|
-
const result = await exportExecution.execute({
|
|
25732
|
-
input: {
|
|
25733
|
-
listId: list.id,
|
|
25734
|
-
mode: "export",
|
|
25735
|
-
approved: true,
|
|
25736
|
-
...isClickUpExportPath ? {
|
|
25737
|
-
destination: "clickup",
|
|
25738
|
-
clickupCredential: clickupCredential?.name,
|
|
25739
|
-
clickupListId: normalizedClickupListId
|
|
25740
|
-
} : {},
|
|
25741
|
-
approvedCompanyIds,
|
|
25742
|
-
rejectedCompanyIds
|
|
25743
|
-
}
|
|
25744
|
-
});
|
|
25745
|
-
showSuccessNotification(`Export workflow run started: ${result.executionId}`);
|
|
25746
|
-
await queryClient.invalidateQueries({ queryKey: acquisitionListKeys.all });
|
|
25747
|
-
} catch (error) {
|
|
25748
|
-
showApiErrorNotification(error);
|
|
25749
|
-
}
|
|
24772
|
+
onApprovalChange(companyId, status);
|
|
25750
24773
|
};
|
|
24774
|
+
const getRecordDetailHref = (row) => row.entity === "company" ? `/crm/companies/${row.companyId}` : `/crm/contacts/${row.contactId}`;
|
|
25751
24775
|
if (!columns.length) {
|
|
25752
24776
|
return /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No record columns are configured for this step." });
|
|
25753
24777
|
}
|
|
@@ -25760,7 +24784,7 @@ function StepRecordsPanel({
|
|
|
25760
24784
|
if (!rows.length) {
|
|
25761
24785
|
return /* @__PURE__ */ jsx(Stack, { gap: "xs", children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
25762
24786
|
"No records found for ",
|
|
25763
|
-
|
|
24787
|
+
stageCatalog[recordsStageKey]?.label ?? recordsStageKey,
|
|
25764
24788
|
"."
|
|
25765
24789
|
] }) });
|
|
25766
24790
|
}
|
|
@@ -25773,7 +24797,7 @@ function StepRecordsPanel({
|
|
|
25773
24797
|
" ",
|
|
25774
24798
|
recordsEntity,
|
|
25775
24799
|
" records from ",
|
|
25776
|
-
|
|
24800
|
+
stageCatalog[recordsStageKey]?.label ?? recordsStageKey
|
|
25777
24801
|
] })
|
|
25778
24802
|
] }),
|
|
25779
24803
|
recordsQuery.isFetching ? /* @__PURE__ */ jsx(Loader, { size: "xs" }) : null
|
|
@@ -25783,13 +24807,15 @@ function StepRecordsPanel({
|
|
|
25783
24807
|
columns.map((column) => /* @__PURE__ */ jsx(Table.Th, { style: column.width ? { width: column.width } : void 0, children: column.label }, column.key)),
|
|
25784
24808
|
/* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
|
|
25785
24809
|
/* @__PURE__ */ jsx(Table.Th, { children: "Failure reason" }),
|
|
25786
|
-
isReviewExportStep ? /* @__PURE__ */ jsx(Table.Th, { children: "Approval" }) : null
|
|
24810
|
+
isReviewExportStep ? /* @__PURE__ */ jsx(Table.Th, { children: "Approval" }) : null,
|
|
24811
|
+
/* @__PURE__ */ jsx(Table.Th, { w: 44, "aria-label": "Open record" })
|
|
25787
24812
|
] }) }),
|
|
25788
24813
|
/* @__PURE__ */ jsx(Table.Tbody, { children: rows.map((row) => {
|
|
25789
24814
|
const columnSource = getRecordColumnSource(row);
|
|
25790
24815
|
const status = getRecordStageStatus(row, recordsStageKey);
|
|
25791
24816
|
const companyId = row.entity === "company" ? row.companyId : null;
|
|
25792
|
-
|
|
24817
|
+
const recordHref = getRecordDetailHref(row);
|
|
24818
|
+
return /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
25793
24819
|
columns.map((column) => /* @__PURE__ */ jsx(Table.Td, { children: renderRecordValue(valueAtPath(columnSource, column.path), column) }, column.key)),
|
|
25794
24820
|
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getRecordStatusColor(status), children: status }) }),
|
|
25795
24821
|
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 2, children: getStageFailureReason(row, recordsStageKey) }) }),
|
|
@@ -25820,43 +24846,48 @@ function StepRecordsPanel({
|
|
|
25820
24846
|
children: "Reject"
|
|
25821
24847
|
}
|
|
25822
24848
|
)
|
|
25823
|
-
] }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "-" }) }) : null
|
|
24849
|
+
] }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "-" }) }) : null,
|
|
24850
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Tooltip, { label: "Open record", children: /* @__PURE__ */ jsx(
|
|
24851
|
+
ActionIcon,
|
|
24852
|
+
{
|
|
24853
|
+
component: "a",
|
|
24854
|
+
href: recordHref,
|
|
24855
|
+
target: "_blank",
|
|
24856
|
+
rel: "noopener noreferrer",
|
|
24857
|
+
size: "sm",
|
|
24858
|
+
variant: "subtle",
|
|
24859
|
+
"aria-label": `Open ${getRecordDisplayName(row)}`,
|
|
24860
|
+
children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
|
|
24861
|
+
}
|
|
24862
|
+
) }) })
|
|
25824
24863
|
] }, row.id);
|
|
25825
24864
|
}) })
|
|
25826
24865
|
] }) }),
|
|
25827
24866
|
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
25828
24867
|
/* @__PURE__ */ jsx(Pagination, { size: "sm", total: totalPages, value: page, onChange: setPage, disabled: recordsQuery.isFetching }),
|
|
25829
|
-
isReviewExportStep ? /* @__PURE__ */
|
|
25830
|
-
|
|
25831
|
-
|
|
25832
|
-
|
|
25833
|
-
|
|
25834
|
-
|
|
25835
|
-
] }),
|
|
25836
|
-
exportDisabledReason ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: exportDisabledReason }) : null,
|
|
25837
|
-
/* @__PURE__ */ jsx(
|
|
25838
|
-
Button,
|
|
25839
|
-
{
|
|
25840
|
-
size: "xs",
|
|
25841
|
-
leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 }),
|
|
25842
|
-
loading: exportExecution.isPending,
|
|
25843
|
-
disabled: !canExport,
|
|
25844
|
-
onClick: () => void exportApproved(),
|
|
25845
|
-
children: isClickUpExportPath ? "Export to ClickUp" : "Export approved"
|
|
25846
|
-
}
|
|
25847
|
-
)
|
|
25848
|
-
] }) : null
|
|
24868
|
+
isReviewExportStep ? /* @__PURE__ */ jsx(Group, { gap: "xs", children: /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
24869
|
+
approvedCompanyIds.length,
|
|
24870
|
+
" approved, ",
|
|
24871
|
+
rejectedCompanyIds.length,
|
|
24872
|
+
" rejected"
|
|
24873
|
+
] }) }) : null
|
|
25849
24874
|
] })
|
|
25850
24875
|
] });
|
|
25851
24876
|
}
|
|
25852
24877
|
function BuildTab({
|
|
25853
24878
|
list,
|
|
25854
24879
|
steps,
|
|
24880
|
+
executions,
|
|
25855
24881
|
recommendedStep,
|
|
24882
|
+
optimisticRuns,
|
|
24883
|
+
exportWorkflowId,
|
|
24884
|
+
stageCatalog,
|
|
25856
24885
|
onRunStep,
|
|
25857
24886
|
onRetryStep,
|
|
25858
24887
|
onViewRunLog
|
|
25859
24888
|
}) {
|
|
24889
|
+
const queryClient = useQueryClient();
|
|
24890
|
+
const { workOSOrganizationId } = useElevasisServices();
|
|
25860
24891
|
const [selectedStepId, setSelectedStepId] = useState(null);
|
|
25861
24892
|
const [stepInputFormState, setStepInputFormState] = useState({});
|
|
25862
24893
|
const [stepInputError, setStepInputError] = useState(null);
|
|
@@ -25865,7 +24896,9 @@ function BuildTab({
|
|
|
25865
24896
|
const [credentialSelections, setCredentialSelections] = useState({});
|
|
25866
24897
|
const [credentialVerificationById, setCredentialVerificationById] = useState({});
|
|
25867
24898
|
const [clickupListId, setClickupListId] = useState("");
|
|
24899
|
+
const [reviewExportApprovals, setReviewExportApprovals] = useState({});
|
|
25868
24900
|
const [runningResources, setRunningResources] = useState({});
|
|
24901
|
+
const lastObservedTerminalRunRef = useRef(null);
|
|
25869
24902
|
const [stepInputResetKey, setStepInputResetKey] = useState(0);
|
|
25870
24903
|
const currentStep = getDisplayStep(steps, recommendedStep);
|
|
25871
24904
|
const selectedStep = steps.find((step) => step.id === selectedStepId) ?? currentStep;
|
|
@@ -25876,6 +24909,8 @@ function BuildTab({
|
|
|
25876
24909
|
const stepSchema = selectedStep?.action?.schema;
|
|
25877
24910
|
const stepLayout = selectedStep?.action?.layout;
|
|
25878
24911
|
const credentialRequirements = selectedStep?.credentialRequirements ?? [];
|
|
24912
|
+
const selectedStepIsReviewExport = selectedStep?.primaryEntity === "company" && (selectedStep.actionKey === "lead-gen.export.list" || selectedStep.action?.resourceId === exportWorkflowId);
|
|
24913
|
+
const selectedExportWorkflowId = selectedStep?.action?.resourceId ?? exportWorkflowId ?? "";
|
|
25879
24914
|
const visibleStepLayout = useMemo(
|
|
25880
24915
|
() => filterCredentialRequirementFields(stepLayout, credentialRequirements),
|
|
25881
24916
|
[stepLayout, credentialRequirements]
|
|
@@ -25883,33 +24918,74 @@ function BuildTab({
|
|
|
25883
24918
|
const showMainStepConfig = stepSchema && hasMainConfigFields(visibleStepLayout);
|
|
25884
24919
|
const showAdvancedStepConfig = stepSchema && hasAdvancedConfigFields(visibleStepLayout);
|
|
25885
24920
|
const recentRunsQuery = useListExecutions(list.id, { resourceId: selectedResourceId, limit: 5 });
|
|
25886
|
-
const recentRuns = useMemo(() =>
|
|
24921
|
+
const recentRuns = useMemo(() => {
|
|
24922
|
+
const serverRuns = recentRunsQuery.data ?? [];
|
|
24923
|
+
const serverExecutionIds = new Set(serverRuns.map((run2) => run2.executionId));
|
|
24924
|
+
const pendingRuns = optimisticRuns.filter(
|
|
24925
|
+
(run2) => run2.resourceId === selectedResourceId && !serverExecutionIds.has(run2.executionId)
|
|
24926
|
+
);
|
|
24927
|
+
return [...pendingRuns, ...serverRuns].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()).slice(0, 5);
|
|
24928
|
+
}, [optimisticRuns, recentRunsQuery.data, selectedResourceId]);
|
|
24929
|
+
const runningResourceIds = useMemo(() => {
|
|
24930
|
+
const ids = /* @__PURE__ */ new Set();
|
|
24931
|
+
const serverExecutionIds = new Set(executions.map((run2) => run2.executionId));
|
|
24932
|
+
executions.forEach((run2) => {
|
|
24933
|
+
if (run2.resourceId && isRunInFlight(run2.status)) ids.add(run2.resourceId);
|
|
24934
|
+
});
|
|
24935
|
+
optimisticRuns.forEach((run2) => {
|
|
24936
|
+
if (serverExecutionIds.has(run2.executionId)) return;
|
|
24937
|
+
if (run2.resourceId && isRunInFlight(run2.status)) ids.add(run2.resourceId);
|
|
24938
|
+
});
|
|
24939
|
+
return ids;
|
|
24940
|
+
}, [executions, optimisticRuns]);
|
|
24941
|
+
const runningStep = steps.find((step) => {
|
|
24942
|
+
const resourceId = step.action?.resourceId;
|
|
24943
|
+
return resourceId ? (runningResources[resourceId] ?? false) || runningResourceIds.has(resourceId) : false;
|
|
24944
|
+
}) ?? null;
|
|
24945
|
+
const latestRecentRun = recentRuns[0] ?? null;
|
|
25887
24946
|
const credentialsQuery = useCredentials();
|
|
25888
24947
|
const credentials = credentialsQuery.data ?? [];
|
|
25889
24948
|
const verifyCredential = useVerifyCredential();
|
|
24949
|
+
const exportExecution = useWorkflowExecution({
|
|
24950
|
+
workflowId: selectedExportWorkflowId,
|
|
24951
|
+
listId: list.id
|
|
24952
|
+
});
|
|
24953
|
+
const approvedCompanyIds = Object.entries(reviewExportApprovals).filter(([, status]) => status === "approved").map(([companyId]) => companyId);
|
|
24954
|
+
const rejectedCompanyIds = Object.entries(reviewExportApprovals).filter(([, status]) => status === "rejected").map(([companyId]) => companyId);
|
|
24955
|
+
const selectedClickupRequirement = selectedStep ? getClickUpRequirement(selectedStep) : null;
|
|
24956
|
+
const selectedClickupCredential = selectedClickupRequirement ? getSelectedCredential(credentials, credentialSelections, selectedClickupRequirement) : null;
|
|
24957
|
+
const isSelectedClickUpExportPath = selectedStepIsReviewExport && Boolean(selectedClickupRequirement);
|
|
24958
|
+
const normalizedClickupListId = clickupListId.trim();
|
|
24959
|
+
const canExportSelectedRecords = selectedStepIsReviewExport && activeRightColumnTab === "records" && approvedCompanyIds.length > 0 && (!isSelectedClickUpExportPath || Boolean(selectedClickupCredential) && normalizedClickupListId.length > 0);
|
|
24960
|
+
const selectedExportDisabledReason = !selectedStepIsReviewExport || activeRightColumnTab !== "records" ? null : approvedCompanyIds.length === 0 ? "Approve records" : isSelectedClickUpExportPath && !selectedClickupCredential ? "Select ClickUp credential" : isSelectedClickUpExportPath && !normalizedClickupListId ? "Enter ClickUp List ID" : null;
|
|
25890
24961
|
const canRunSelectedAction = !!selectedStep?.action && (selectedActionKind === "retry_failed" || selectedActionKind === "run_next_batch");
|
|
25891
|
-
const selectedResourceIsRunning = selectedResourceId ? runningResources[selectedResourceId] ?? false : false;
|
|
25892
|
-
const selectedActionDisabled = !canRunSelectedAction || selectedResourceIsRunning;
|
|
25893
|
-
const selectedActionLabel = selectedResourceIsRunning ? "Running..." : selectedActionKind === "none" ? "No action" : getStepActionLabel(selectedActionKind);
|
|
25894
|
-
const selectedActionIcon = selectedActionKind === "retry_failed" ? /* @__PURE__ */ jsx(IconRefresh, { size: 14 }) : /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 });
|
|
24962
|
+
const selectedResourceIsRunning = selectedResourceId ? (runningResources[selectedResourceId] ?? false) || runningResourceIds.has(selectedResourceId) : false;
|
|
24963
|
+
const selectedActionDisabled = selectedStepIsReviewExport && activeRightColumnTab !== "records" ? false : selectedStepIsReviewExport ? !canExportSelectedRecords || exportExecution.isPending : !canRunSelectedAction || selectedResourceIsRunning;
|
|
24964
|
+
const selectedActionLabel = selectedResourceIsRunning ? "Running..." : selectedStepIsReviewExport && activeRightColumnTab !== "records" ? "Approve records" : selectedStepIsReviewExport ? selectedExportDisabledReason ?? (isSelectedClickUpExportPath ? "Export to ClickUp" : "Export approved") : selectedActionKind === "none" ? "No action" : getStepActionLabel(selectedActionKind);
|
|
24965
|
+
const selectedActionIcon = selectedStepIsReviewExport && activeRightColumnTab !== "records" ? /* @__PURE__ */ jsx(IconAddressBook, { size: 14 }) : selectedActionKind === "retry_failed" ? /* @__PURE__ */ jsx(IconRefresh, { size: 14 }) : /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 });
|
|
25895
24966
|
const handleResourceRunningChange = useCallback((resourceId, isRunning) => {
|
|
25896
24967
|
setRunningResources((current) => {
|
|
25897
24968
|
if (current[resourceId] === isRunning) return current;
|
|
25898
24969
|
return { ...current, [resourceId]: isRunning };
|
|
25899
24970
|
});
|
|
25900
24971
|
}, []);
|
|
25901
|
-
|
|
25902
|
-
(
|
|
25903
|
-
|
|
25904
|
-
|
|
25905
|
-
|
|
25906
|
-
|
|
25907
|
-
|
|
24972
|
+
useEffect(() => {
|
|
24973
|
+
if (!selectedResourceId || !latestRecentRun || !isRunTerminal(latestRecentRun.status)) return;
|
|
24974
|
+
if (lastObservedTerminalRunRef.current === latestRecentRun.executionId) return;
|
|
24975
|
+
lastObservedTerminalRunRef.current = latestRecentRun.executionId;
|
|
24976
|
+
handleResourceRunningChange(selectedResourceId, false);
|
|
24977
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.detail(workOSOrganizationId, list.id) });
|
|
24978
|
+
queryClient.invalidateQueries({ queryKey: acquisitionListKeys.progress(workOSOrganizationId, list.id) });
|
|
24979
|
+
queryClient.invalidateQueries({
|
|
24980
|
+
queryKey: [...acquisitionListKeys.all, "records", workOSOrganizationId, list.id]
|
|
24981
|
+
});
|
|
24982
|
+
}, [handleResourceRunningChange, latestRecentRun, list.id, queryClient, selectedResourceId, workOSOrganizationId]);
|
|
25908
24983
|
useEffect(() => {
|
|
25909
24984
|
setStepInputFormState(getInitialStepInput(list, selectedStep?.action));
|
|
25910
24985
|
setStepInputError(null);
|
|
25911
24986
|
setStepInputInitialized(false);
|
|
25912
24987
|
setStepInputResetKey((k) => k + 1);
|
|
24988
|
+
setReviewExportApprovals({});
|
|
25913
24989
|
}, [list, selectedStep?.action]);
|
|
25914
24990
|
useEffect(() => {
|
|
25915
24991
|
if (stepInputInitialized) return;
|
|
@@ -25917,7 +24993,7 @@ function BuildTab({
|
|
|
25917
24993
|
if (recentRuns.length > 0) {
|
|
25918
24994
|
const lastInput = getRunInput(recentRuns[0]);
|
|
25919
24995
|
if (lastInput) {
|
|
25920
|
-
setStepInputFormState(sanitizeStepInput(
|
|
24996
|
+
setStepInputFormState(sanitizeStepInput(asRecord2(lastInput), selectedCapabilityKey));
|
|
25921
24997
|
setStepInputResetKey((k) => k + 1);
|
|
25922
24998
|
}
|
|
25923
24999
|
}
|
|
@@ -25964,8 +25040,42 @@ function BuildTab({
|
|
|
25964
25040
|
setStepInputFormState((current) => setValueAtInputPath(current, "clickupListId", value));
|
|
25965
25041
|
if (stepInputError) setStepInputError(null);
|
|
25966
25042
|
};
|
|
25967
|
-
const
|
|
25043
|
+
const handleReviewExportApprovalChange = (companyId, status) => {
|
|
25044
|
+
setReviewExportApprovals((current) => ({ ...current, [companyId]: status }));
|
|
25045
|
+
if (stepInputError) setStepInputError(null);
|
|
25046
|
+
};
|
|
25047
|
+
const exportApprovedRecords = async () => {
|
|
25048
|
+
try {
|
|
25049
|
+
const result = await exportExecution.execute({
|
|
25050
|
+
input: {
|
|
25051
|
+
listId: list.id,
|
|
25052
|
+
mode: "export",
|
|
25053
|
+
approved: true,
|
|
25054
|
+
...isSelectedClickUpExportPath ? {
|
|
25055
|
+
destination: "clickup",
|
|
25056
|
+
clickupCredential: selectedClickupCredential?.name,
|
|
25057
|
+
clickupListId: normalizedClickupListId
|
|
25058
|
+
} : {},
|
|
25059
|
+
approvedCompanyIds,
|
|
25060
|
+
rejectedCompanyIds
|
|
25061
|
+
}
|
|
25062
|
+
});
|
|
25063
|
+
showSuccessNotification(`Export workflow run started: ${result.executionId}`);
|
|
25064
|
+
await queryClient.invalidateQueries({ queryKey: acquisitionListKeys.all });
|
|
25065
|
+
} catch (error) {
|
|
25066
|
+
showApiErrorNotification(error);
|
|
25067
|
+
}
|
|
25068
|
+
};
|
|
25069
|
+
const handleSelectedAction = async () => {
|
|
25968
25070
|
if (!selectedStep || selectedActionDisabled) return;
|
|
25071
|
+
if (selectedStepIsReviewExport && activeRightColumnTab !== "records") {
|
|
25072
|
+
setActiveRightColumnTab("records");
|
|
25073
|
+
return;
|
|
25074
|
+
}
|
|
25075
|
+
if (selectedStepIsReviewExport) {
|
|
25076
|
+
await exportApprovedRecords();
|
|
25077
|
+
return;
|
|
25078
|
+
}
|
|
25969
25079
|
if (stepSchema) {
|
|
25970
25080
|
const parsed = stepSchema.safeParse(stepInputFormState);
|
|
25971
25081
|
if (!parsed.success) {
|
|
@@ -25976,14 +25086,22 @@ function BuildTab({
|
|
|
25976
25086
|
}
|
|
25977
25087
|
setStepInputError(null);
|
|
25978
25088
|
const submittedInput = stepSchema ? stepInputFormState : {};
|
|
25979
|
-
|
|
25980
|
-
|
|
25981
|
-
|
|
25089
|
+
setActiveRightColumnTab("runs");
|
|
25090
|
+
const resourceId = selectedStep.action?.resourceId ?? null;
|
|
25091
|
+
try {
|
|
25092
|
+
let result = null;
|
|
25093
|
+
if (selectedActionKind === "retry_failed") {
|
|
25094
|
+
result = await onRetryStep(selectedStep, submittedInput);
|
|
25095
|
+
} else {
|
|
25096
|
+
result = await onRunStep(selectedStep, submittedInput);
|
|
25097
|
+
}
|
|
25098
|
+
if (resourceId && result?.executionId) handleResourceRunningChange(resourceId, true);
|
|
25099
|
+
} catch {
|
|
25100
|
+
if (resourceId) handleResourceRunningChange(resourceId, false);
|
|
25982
25101
|
}
|
|
25983
|
-
onRunStep(selectedStep, submittedInput);
|
|
25984
25102
|
};
|
|
25985
25103
|
const loadRecentRunInput = (run2) => {
|
|
25986
|
-
setStepInputFormState(sanitizeStepInput(
|
|
25104
|
+
setStepInputFormState(sanitizeStepInput(asRecord2(getRunInput(run2)), selectedCapabilityKey));
|
|
25987
25105
|
setStepInputResetKey((k) => k + 1);
|
|
25988
25106
|
setActiveRightColumnTab("configuration");
|
|
25989
25107
|
};
|
|
@@ -25992,242 +25110,231 @@ function BuildTab({
|
|
|
25992
25110
|
if (!resourceId) return;
|
|
25993
25111
|
onViewRunLog(resourceId, run2.executionId);
|
|
25994
25112
|
};
|
|
25995
|
-
return /* @__PURE__ */ jsx(
|
|
25996
|
-
|
|
25997
|
-
|
|
25998
|
-
|
|
25999
|
-
|
|
26000
|
-
|
|
26001
|
-
|
|
26002
|
-
|
|
26003
|
-
|
|
26004
|
-
|
|
26005
|
-
|
|
26006
|
-
),
|
|
26007
|
-
steps.map((step, index) => {
|
|
26008
|
-
const isCurrent = currentStep?.id === step.id;
|
|
26009
|
-
const isSelected = selectedStep?.id === step.id;
|
|
26010
|
-
const stepResourceId = step.action?.resourceId ?? null;
|
|
26011
|
-
const isStepRunning = stepResourceId ? runningResources[stepResourceId] ?? false : false;
|
|
26012
|
-
const isWaiting = step.status === "blocked";
|
|
26013
|
-
const isPassiveWaiting = isWaiting && !isSelected && !isCurrent;
|
|
26014
|
-
const stepTone = isStepRunning ? "ready" : isSelected || isCurrent ? step.status : step.status === "complete" || isWaiting ? step.status : "neutral";
|
|
26015
|
-
return /* @__PURE__ */ jsx(
|
|
26016
|
-
UnstyledButton,
|
|
26017
|
-
{
|
|
26018
|
-
onClick: () => setSelectedStepId(step.id),
|
|
26019
|
-
style: {
|
|
26020
|
-
backgroundColor: isSelected ? "var(--surface-primary-strong)" : isStepRunning ? "color-mix(in srgb, var(--color-primary) 12%, transparent)" : isPassiveWaiting ? "color-mix(in srgb, var(--color-surface-hover) 38%, transparent)" : "transparent",
|
|
26021
|
-
border: isSelected ? "var(--active-border)" : isStepRunning ? "1px solid var(--border-primary-muted)" : "1px solid var(--color-border)",
|
|
26022
|
-
borderStyle: isPassiveWaiting && !isStepRunning ? "dashed" : "solid",
|
|
26023
|
-
borderRadius: 8,
|
|
26024
|
-
display: "block",
|
|
26025
|
-
opacity: isPassiveWaiting && !isStepRunning ? 0.72 : 1,
|
|
26026
|
-
padding: 12,
|
|
26027
|
-
textAlign: "left",
|
|
26028
|
-
width: "100%"
|
|
26029
|
-
},
|
|
26030
|
-
children: /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", children: [
|
|
26031
|
-
/* @__PURE__ */ jsx(
|
|
26032
|
-
Box,
|
|
26033
|
-
{
|
|
26034
|
-
w: 28,
|
|
26035
|
-
h: 28,
|
|
26036
|
-
style: {
|
|
26037
|
-
alignItems: "center",
|
|
26038
|
-
...getBuildToneStyle(stepTone),
|
|
26039
|
-
borderRadius: 999,
|
|
26040
|
-
borderStyle: "solid",
|
|
26041
|
-
borderWidth: 1,
|
|
26042
|
-
display: "flex",
|
|
26043
|
-
flexShrink: 0,
|
|
26044
|
-
fontWeight: 700,
|
|
26045
|
-
justifyContent: "center"
|
|
26046
|
-
},
|
|
26047
|
-
children: index + 1
|
|
26048
|
-
}
|
|
26049
|
-
),
|
|
26050
|
-
/* @__PURE__ */ jsxs(Stack, { gap: 4, style: { minWidth: 0, flex: 1 }, children: [
|
|
26051
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "space-between", wrap: "nowrap", children: [
|
|
26052
|
-
/* @__PURE__ */ jsx(Text, { fw: 700, c: isPassiveWaiting && !isStepRunning ? "dimmed" : void 0, truncate: true, children: step.label }),
|
|
26053
|
-
isStepRunning ? /* @__PURE__ */ jsx(StatusPill, { label: "Running", tone: "ready" }) : null,
|
|
26054
|
-
!isStepRunning && isCurrent ? /* @__PURE__ */ jsx(StatusPill, { label: "Current", tone: step.status }) : null,
|
|
26055
|
-
!isStepRunning && !isCurrent && isWaiting ? /* @__PURE__ */ jsx(StatusPill, { label: "Waiting", tone: "blocked" }) : null
|
|
26056
|
-
] }),
|
|
26057
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: step.description }),
|
|
26058
|
-
/* @__PURE__ */ jsx(StepCounterLine, { step })
|
|
26059
|
-
] })
|
|
26060
|
-
] })
|
|
26061
|
-
},
|
|
26062
|
-
step.id
|
|
26063
|
-
);
|
|
26064
|
-
})
|
|
26065
|
-
] }) }),
|
|
26066
|
-
selectedStep ? /* @__PURE__ */ jsx(Card, { withBorder: true, style: { height: "100%", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", style: { flex: 1, minHeight: 0 }, children: [
|
|
26067
|
-
/* @__PURE__ */ jsxs(Stack, { gap: 2, style: { minWidth: 0, flexShrink: 0 }, children: [
|
|
26068
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: [
|
|
26069
|
-
"Step ",
|
|
26070
|
-
selectedStepIndex + 1,
|
|
26071
|
-
" details"
|
|
26072
|
-
] }),
|
|
26073
|
-
/* @__PURE__ */ jsx(Title, { order: 5, children: selectedStep.label })
|
|
26074
|
-
] }),
|
|
26075
|
-
/* @__PURE__ */ jsx(BuildStepProgressBar, { step: selectedStep }),
|
|
26076
|
-
/* @__PURE__ */ jsx(
|
|
26077
|
-
StepDetailRightColumn,
|
|
26078
|
-
{
|
|
26079
|
-
activeTab: activeRightColumnTab,
|
|
26080
|
-
onTabChange: setActiveRightColumnTab,
|
|
26081
|
-
configuration: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
26082
|
-
selectedResourceId && selectedStep.stageKey ? /* @__PURE__ */ jsx(
|
|
26083
|
-
LeadGenLiveStatusPanel,
|
|
25113
|
+
return /* @__PURE__ */ jsx(
|
|
25114
|
+
TabSection,
|
|
25115
|
+
{
|
|
25116
|
+
icon: /* @__PURE__ */ jsx(IconBolt, { size: 16 }),
|
|
25117
|
+
title: "Build",
|
|
25118
|
+
description: getBuildTabDescription(steps, currentStep, runningStep),
|
|
25119
|
+
children: /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
|
|
25120
|
+
/* @__PURE__ */ jsx(Card, { withBorder: true, style: { height: "100%", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", style: { flex: 1, minHeight: 0 }, children: [
|
|
25121
|
+
steps.map(
|
|
25122
|
+
(step) => step.action?.resourceId ? /* @__PURE__ */ jsx(
|
|
25123
|
+
BuildStepRunningWatcher,
|
|
26084
25124
|
{
|
|
26085
25125
|
listId: list.id,
|
|
26086
|
-
resourceId:
|
|
26087
|
-
|
|
26088
|
-
stepLabel: selectedStep.label,
|
|
26089
|
-
enabled: true,
|
|
26090
|
-
onRunningChange: handleSelectedResourceRunningChange
|
|
25126
|
+
resourceId: step.action.resourceId,
|
|
25127
|
+
onRunningChange: handleResourceRunningChange
|
|
26091
25128
|
},
|
|
26092
|
-
|
|
26093
|
-
) : null
|
|
26094
|
-
|
|
26095
|
-
|
|
26096
|
-
|
|
26097
|
-
|
|
26098
|
-
|
|
26099
|
-
|
|
26100
|
-
|
|
26101
|
-
|
|
26102
|
-
|
|
26103
|
-
|
|
26104
|
-
|
|
26105
|
-
StepConfigForm,
|
|
25129
|
+
`running-${step.id}`
|
|
25130
|
+
) : null
|
|
25131
|
+
),
|
|
25132
|
+
steps.map((step, index) => {
|
|
25133
|
+
const isCurrent = currentStep?.id === step.id;
|
|
25134
|
+
const isSelected = selectedStep?.id === step.id;
|
|
25135
|
+
const stepResourceId = step.action?.resourceId ?? null;
|
|
25136
|
+
const isStepRunning = stepResourceId ? (runningResources[stepResourceId] ?? false) || runningResourceIds.has(stepResourceId) : false;
|
|
25137
|
+
const isWaiting = step.status === "blocked";
|
|
25138
|
+
const isPassiveWaiting = isWaiting && !isSelected && !isCurrent;
|
|
25139
|
+
const stepTone = isStepRunning ? "ready" : isSelected || isCurrent ? step.status : step.status === "complete" || isWaiting ? step.status : "neutral";
|
|
25140
|
+
return /* @__PURE__ */ jsx(
|
|
25141
|
+
UnstyledButton,
|
|
26106
25142
|
{
|
|
26107
|
-
|
|
26108
|
-
|
|
26109
|
-
|
|
26110
|
-
|
|
26111
|
-
|
|
26112
|
-
|
|
25143
|
+
onClick: () => setSelectedStepId(step.id),
|
|
25144
|
+
style: {
|
|
25145
|
+
backgroundColor: isSelected ? "var(--surface-primary-strong)" : isStepRunning ? "color-mix(in srgb, var(--color-primary) 12%, transparent)" : isPassiveWaiting ? "color-mix(in srgb, var(--color-surface-hover) 38%, transparent)" : "transparent",
|
|
25146
|
+
border: isSelected ? "var(--active-border)" : isStepRunning ? "1px solid var(--border-primary-muted)" : "1px solid var(--color-border)",
|
|
25147
|
+
borderStyle: isPassiveWaiting && !isStepRunning ? "dashed" : "solid",
|
|
25148
|
+
borderRadius: 8,
|
|
25149
|
+
display: "block",
|
|
25150
|
+
opacity: isPassiveWaiting && !isStepRunning ? 0.72 : 1,
|
|
25151
|
+
padding: 12,
|
|
25152
|
+
textAlign: "left",
|
|
25153
|
+
width: "100%"
|
|
25154
|
+
},
|
|
25155
|
+
children: /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", children: [
|
|
25156
|
+
/* @__PURE__ */ jsx(
|
|
25157
|
+
Box,
|
|
25158
|
+
{
|
|
25159
|
+
w: 28,
|
|
25160
|
+
h: 28,
|
|
25161
|
+
style: {
|
|
25162
|
+
alignItems: "center",
|
|
25163
|
+
...getBuildToneStyle(stepTone),
|
|
25164
|
+
borderRadius: 999,
|
|
25165
|
+
borderStyle: "solid",
|
|
25166
|
+
borderWidth: 1,
|
|
25167
|
+
display: "flex",
|
|
25168
|
+
flexShrink: 0,
|
|
25169
|
+
fontWeight: 700,
|
|
25170
|
+
justifyContent: "center"
|
|
25171
|
+
},
|
|
25172
|
+
children: index + 1
|
|
25173
|
+
}
|
|
25174
|
+
),
|
|
25175
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 4, style: { minWidth: 0, flex: 1 }, children: [
|
|
25176
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "space-between", wrap: "nowrap", children: [
|
|
25177
|
+
/* @__PURE__ */ jsx(Text, { fw: 700, c: isPassiveWaiting && !isStepRunning ? "dimmed" : void 0, truncate: true, children: step.label }),
|
|
25178
|
+
!isStepRunning && isWaiting ? /* @__PURE__ */ jsx(StatusPill, { label: "Waiting", tone: "blocked" }) : null
|
|
25179
|
+
] }),
|
|
25180
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: step.description }),
|
|
25181
|
+
/* @__PURE__ */ jsx(StepCounterLine, { step, isRunning: isStepRunning })
|
|
25182
|
+
] })
|
|
25183
|
+
] })
|
|
26113
25184
|
},
|
|
26114
|
-
|
|
26115
|
-
)
|
|
26116
|
-
|
|
26117
|
-
|
|
26118
|
-
|
|
26119
|
-
|
|
26120
|
-
|
|
26121
|
-
|
|
26122
|
-
|
|
26123
|
-
|
|
26124
|
-
|
|
26125
|
-
|
|
26126
|
-
onVerify: handleVerifyCredential
|
|
26127
|
-
}
|
|
26128
|
-
),
|
|
26129
|
-
selectedStep.actionKey === "lead-gen.export.list" || getClickUpRequirement(selectedStep) ? /* @__PURE__ */ jsx(
|
|
26130
|
-
TextInput,
|
|
26131
|
-
{
|
|
26132
|
-
label: "ClickUp List ID",
|
|
26133
|
-
description: "Destination List ID for approved company tasks.",
|
|
26134
|
-
placeholder: "123456789",
|
|
26135
|
-
value: clickupListId,
|
|
26136
|
-
onChange: (event) => handleClickupListIdChange(event.currentTarget.value)
|
|
26137
|
-
}
|
|
26138
|
-
) : null
|
|
25185
|
+
step.id
|
|
25186
|
+
);
|
|
25187
|
+
})
|
|
25188
|
+
] }) }),
|
|
25189
|
+
selectedStep ? /* @__PURE__ */ jsx(Card, { withBorder: true, style: { height: "100%", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", style: { flex: 1, minHeight: 0 }, children: [
|
|
25190
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, style: { minWidth: 0, flexShrink: 0 }, children: [
|
|
25191
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: [
|
|
25192
|
+
"Step ",
|
|
25193
|
+
selectedStepIndex + 1,
|
|
25194
|
+
" details"
|
|
25195
|
+
] }),
|
|
25196
|
+
/* @__PURE__ */ jsx(Title, { order: 5, children: selectedStep.label })
|
|
26139
25197
|
] }),
|
|
26140
|
-
|
|
26141
|
-
|
|
26142
|
-
|
|
26143
|
-
slot: "advanced",
|
|
26144
|
-
schema: stepSchema,
|
|
26145
|
-
layout: visibleStepLayout,
|
|
26146
|
-
value: stepInputFormState,
|
|
26147
|
-
onChange: (v) => handleStepInputChange(asRecord3(v) ?? {}),
|
|
26148
|
-
disabled: !canRunSelectedAction
|
|
26149
|
-
},
|
|
26150
|
-
`${selectedResourceId ?? "none"}-advanced-${stepInputResetKey}`
|
|
26151
|
-
) : void 0,
|
|
26152
|
-
records: /* @__PURE__ */ jsx(
|
|
26153
|
-
StepRecordsPanel,
|
|
25198
|
+
/* @__PURE__ */ jsx(BuildStepProgressBar, { step: selectedStep, isRunning: selectedResourceIsRunning }),
|
|
25199
|
+
/* @__PURE__ */ jsx(
|
|
25200
|
+
StepDetailRightColumn,
|
|
26154
25201
|
{
|
|
26155
|
-
|
|
26156
|
-
|
|
26157
|
-
|
|
26158
|
-
|
|
26159
|
-
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26163
|
-
|
|
26164
|
-
|
|
26165
|
-
|
|
26166
|
-
|
|
26167
|
-
] }),
|
|
26168
|
-
!recentRuns.length && !recentRunsQuery.isLoading ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No runs yet for this step." }) : /* @__PURE__ */ jsx(Stack, { gap: 4, children: recentRuns.map((run2) => {
|
|
26169
|
-
const canUseSettings = hasRunInput(run2);
|
|
26170
|
-
return /* @__PURE__ */ jsx(
|
|
26171
|
-
Box,
|
|
26172
|
-
{
|
|
26173
|
-
style: {
|
|
26174
|
-
border: "1px solid var(--color-border)",
|
|
26175
|
-
borderRadius: 8,
|
|
26176
|
-
padding: "8px 10px",
|
|
26177
|
-
width: "100%"
|
|
25202
|
+
activeTab: activeRightColumnTab,
|
|
25203
|
+
onTabChange: setActiveRightColumnTab,
|
|
25204
|
+
configuration: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
25205
|
+
showMainStepConfig && visibleStepLayout ? /* @__PURE__ */ jsx(
|
|
25206
|
+
StepConfigForm,
|
|
25207
|
+
{
|
|
25208
|
+
slot: "main",
|
|
25209
|
+
schema: stepSchema,
|
|
25210
|
+
layout: visibleStepLayout,
|
|
25211
|
+
value: stepInputFormState,
|
|
25212
|
+
onChange: (v) => handleStepInputChange(asRecord2(v) ?? {}),
|
|
25213
|
+
disabled: !canRunSelectedAction
|
|
26178
25214
|
},
|
|
26179
|
-
|
|
26180
|
-
|
|
26181
|
-
|
|
26182
|
-
|
|
26183
|
-
|
|
26184
|
-
|
|
26185
|
-
|
|
26186
|
-
|
|
26187
|
-
|
|
26188
|
-
|
|
26189
|
-
|
|
26190
|
-
|
|
26191
|
-
|
|
26192
|
-
|
|
26193
|
-
|
|
26194
|
-
|
|
26195
|
-
|
|
26196
|
-
|
|
26197
|
-
|
|
26198
|
-
|
|
26199
|
-
|
|
26200
|
-
|
|
26201
|
-
|
|
26202
|
-
|
|
26203
|
-
|
|
26204
|
-
|
|
26205
|
-
|
|
25215
|
+
`${selectedResourceId ?? "none"}-main-${stepInputResetKey}`
|
|
25216
|
+
) : !credentialRequirements.length ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No configuration for this step." }) : null,
|
|
25217
|
+
/* @__PURE__ */ jsx(
|
|
25218
|
+
CredentialRequirementsPanel,
|
|
25219
|
+
{
|
|
25220
|
+
requirements: credentialRequirements,
|
|
25221
|
+
credentials,
|
|
25222
|
+
credentialsLoading: credentialsQuery.isLoading,
|
|
25223
|
+
credentialsError: credentialsQuery.error instanceof Error ? credentialsQuery.error : null,
|
|
25224
|
+
selections: credentialSelections,
|
|
25225
|
+
verificationByCredentialId: credentialVerificationById,
|
|
25226
|
+
verifyingCredentialId: verifyCredential.isPending ? verifyCredential.variables ?? null : null,
|
|
25227
|
+
onSelect: handleCredentialSelect,
|
|
25228
|
+
onVerify: handleVerifyCredential
|
|
25229
|
+
}
|
|
25230
|
+
),
|
|
25231
|
+
selectedStep.actionKey === "lead-gen.export.list" || getClickUpRequirement(selectedStep) ? /* @__PURE__ */ jsx(
|
|
25232
|
+
TextInput,
|
|
25233
|
+
{
|
|
25234
|
+
label: "ClickUp List ID",
|
|
25235
|
+
description: "Destination List ID for approved company tasks.",
|
|
25236
|
+
placeholder: "123456789",
|
|
25237
|
+
value: clickupListId,
|
|
25238
|
+
onChange: (event) => handleClickupListIdChange(event.currentTarget.value)
|
|
25239
|
+
}
|
|
25240
|
+
) : null
|
|
25241
|
+
] }),
|
|
25242
|
+
advanced: showAdvancedStepConfig && visibleStepLayout ? /* @__PURE__ */ jsx(
|
|
25243
|
+
StepConfigForm,
|
|
25244
|
+
{
|
|
25245
|
+
slot: "advanced",
|
|
25246
|
+
schema: stepSchema,
|
|
25247
|
+
layout: visibleStepLayout,
|
|
25248
|
+
value: stepInputFormState,
|
|
25249
|
+
onChange: (v) => handleStepInputChange(asRecord2(v) ?? {}),
|
|
25250
|
+
disabled: !canRunSelectedAction
|
|
26206
25251
|
},
|
|
26207
|
-
|
|
26208
|
-
)
|
|
26209
|
-
|
|
26210
|
-
|
|
26211
|
-
|
|
26212
|
-
|
|
26213
|
-
|
|
26214
|
-
|
|
26215
|
-
|
|
26216
|
-
|
|
26217
|
-
|
|
26218
|
-
|
|
26219
|
-
|
|
26220
|
-
|
|
26221
|
-
|
|
26222
|
-
|
|
26223
|
-
|
|
26224
|
-
|
|
26225
|
-
|
|
26226
|
-
|
|
25252
|
+
`${selectedResourceId ?? "none"}-advanced-${stepInputResetKey}`
|
|
25253
|
+
) : void 0,
|
|
25254
|
+
records: /* @__PURE__ */ jsx(
|
|
25255
|
+
StepRecordsPanel,
|
|
25256
|
+
{
|
|
25257
|
+
list,
|
|
25258
|
+
step: selectedStep,
|
|
25259
|
+
exportWorkflowId,
|
|
25260
|
+
stageCatalog,
|
|
25261
|
+
approvalByCompanyId: reviewExportApprovals,
|
|
25262
|
+
onApprovalChange: handleReviewExportApprovalChange
|
|
25263
|
+
},
|
|
25264
|
+
selectedStep.id
|
|
25265
|
+
),
|
|
25266
|
+
runs: selectedResourceId ? /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
25267
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
25268
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: "Recent runs" }),
|
|
25269
|
+
recentRunsQuery.isFetching ? /* @__PURE__ */ jsx(Loader, { size: "xs" }) : null
|
|
25270
|
+
] }),
|
|
25271
|
+
!recentRuns.length && !recentRunsQuery.isLoading ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No runs yet for this step." }) : /* @__PURE__ */ jsx(Stack, { gap: 4, children: recentRuns.map((run2) => {
|
|
25272
|
+
const canUseSettings = hasRunInput(run2);
|
|
25273
|
+
return /* @__PURE__ */ jsx(
|
|
25274
|
+
Box,
|
|
25275
|
+
{
|
|
25276
|
+
style: {
|
|
25277
|
+
border: "1px solid var(--color-border)",
|
|
25278
|
+
borderRadius: 8,
|
|
25279
|
+
padding: "8px 10px",
|
|
25280
|
+
width: "100%"
|
|
25281
|
+
},
|
|
25282
|
+
children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
|
|
25283
|
+
/* @__PURE__ */ jsx(
|
|
25284
|
+
UnstyledButton,
|
|
25285
|
+
{
|
|
25286
|
+
onClick: () => openRecentRunLog(run2),
|
|
25287
|
+
style: { flex: 1, minWidth: 0, textAlign: "left" },
|
|
25288
|
+
children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
|
|
25289
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, style: { minWidth: 0 }, children: [
|
|
25290
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, truncate: true, children: formatDateTime4(run2.createdAt) }),
|
|
25291
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", truncate: true, children: run2.executionId })
|
|
25292
|
+
] }),
|
|
25293
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getRunStatusColor(run2.status), children: run2.status })
|
|
25294
|
+
] })
|
|
25295
|
+
}
|
|
25296
|
+
),
|
|
25297
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Use this run's settings", children: /* @__PURE__ */ jsx(
|
|
25298
|
+
Button,
|
|
25299
|
+
{
|
|
25300
|
+
size: "xs",
|
|
25301
|
+
variant: "subtle",
|
|
25302
|
+
leftSection: /* @__PURE__ */ jsx(IconSettings, { size: 12 }),
|
|
25303
|
+
disabled: !canUseSettings,
|
|
25304
|
+
onClick: () => loadRecentRunInput(run2),
|
|
25305
|
+
children: "Use settings"
|
|
25306
|
+
}
|
|
25307
|
+
) })
|
|
25308
|
+
] })
|
|
25309
|
+
},
|
|
25310
|
+
run2.executionId
|
|
25311
|
+
);
|
|
25312
|
+
}) })
|
|
25313
|
+
] }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No runs available for this step." }),
|
|
25314
|
+
action: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
25315
|
+
stepInputError ? /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), variant: "light", children: stepInputError }) : null,
|
|
25316
|
+
/* @__PURE__ */ jsx(Group, { gap: "xs", justify: "flex-end", wrap: "nowrap", style: { minWidth: 0, overflowX: "hidden" }, children: /* @__PURE__ */ jsx(Tooltip, { label: selectedExportDisabledReason, disabled: !selectedExportDisabledReason, children: /* @__PURE__ */ jsx(
|
|
25317
|
+
Button,
|
|
25318
|
+
{
|
|
25319
|
+
leftSection: selectedActionIcon,
|
|
25320
|
+
disabled: selectedActionDisabled,
|
|
25321
|
+
onClick: handleSelectedAction,
|
|
25322
|
+
style: { maxWidth: "100%" },
|
|
25323
|
+
children: selectedActionLabel
|
|
25324
|
+
}
|
|
25325
|
+
) }) })
|
|
25326
|
+
] })
|
|
25327
|
+
}
|
|
25328
|
+
)
|
|
25329
|
+
] }) }) : null
|
|
25330
|
+
] })
|
|
25331
|
+
}
|
|
25332
|
+
);
|
|
26227
25333
|
}
|
|
26228
25334
|
function MembersTab({
|
|
26229
25335
|
listId,
|
|
26230
25336
|
progress,
|
|
25337
|
+
stageCatalog,
|
|
26231
25338
|
onMemberClick
|
|
26232
25339
|
}) {
|
|
26233
25340
|
const [memberTab, setMemberTab] = useState("contacts");
|
|
@@ -26235,6 +25342,9 @@ function MembersTab({
|
|
|
26235
25342
|
const companiesQuery = useCompanies({ listId, limit: 100, offset: 0 });
|
|
26236
25343
|
const contacts = contactsQuery.data?.data ?? [];
|
|
26237
25344
|
const companies = companiesQuery.data?.data ?? [];
|
|
25345
|
+
const activeQuery = memberTab === "contacts" ? contactsQuery : companiesQuery;
|
|
25346
|
+
const activeError = activeQuery.error ?? activeQuery.failureReason;
|
|
25347
|
+
const activeIsInitialLoading = activeQuery.isLoading && !activeError;
|
|
26238
25348
|
return /* @__PURE__ */ jsxs(
|
|
26239
25349
|
TabSection,
|
|
26240
25350
|
{
|
|
@@ -26254,7 +25364,7 @@ function MembersTab({
|
|
|
26254
25364
|
}
|
|
26255
25365
|
),
|
|
26256
25366
|
children: [
|
|
26257
|
-
memberTab === "contacts" && /* @__PURE__ */ jsx(Fragment, { children:
|
|
25367
|
+
memberTab === "contacts" && /* @__PURE__ */ jsx(Fragment, { children: activeError ? /* @__PURE__ */ jsx(CenteredErrorState, { error: activeError, title: "Failed to load members", h: 160 }) : activeIsInitialLoading ? /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !contacts.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No contacts attached to this list yet." }) : /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
|
|
26258
25368
|
/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
26259
25369
|
/* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
|
|
26260
25370
|
/* @__PURE__ */ jsx(Table.Th, { children: "Email" }),
|
|
@@ -26266,19 +25376,19 @@ function MembersTab({
|
|
|
26266
25376
|
] }) }),
|
|
26267
25377
|
/* @__PURE__ */ jsx(Table.Tbody, { children: contacts.map((contact) => {
|
|
26268
25378
|
const handleRowClick = () => onMemberClick?.(contact.id, "contact");
|
|
26269
|
-
const memberStage = displayMemberStageFor(contact, "contact");
|
|
25379
|
+
const memberStage = displayMemberStageFor(contact, "contact", stageCatalog);
|
|
26270
25380
|
return /* @__PURE__ */ jsxs(Table.Tr, { onClick: handleRowClick, style: { cursor: "pointer" }, children: [
|
|
26271
25381
|
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: contactDisplayName(contact.firstName, contact.lastName) }) }),
|
|
26272
25382
|
/* @__PURE__ */ jsx(Table.Td, { children: contact.email }),
|
|
26273
25383
|
/* @__PURE__ */ jsx(Table.Td, { children: contact.title ?? "\u2014" }),
|
|
26274
25384
|
/* @__PURE__ */ jsx(Table.Td, { children: contact.company?.name ?? "\u2014" }),
|
|
26275
|
-
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color:
|
|
26276
|
-
/* @__PURE__ */ jsx(Table.Td, { children: memberStage ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "dot", color: getMemberStateColor2(memberStage.key), children: memberStage.label }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" }) }),
|
|
26277
|
-
/* @__PURE__ */ jsx(Table.Td, { children:
|
|
25385
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor6(contact.status), children: contact.status }) }),
|
|
25386
|
+
/* @__PURE__ */ jsx(Table.Td, { children: memberStage ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "dot", color: getMemberStateColor2(memberStage.key, stageCatalog), children: memberStage.label }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" }) }),
|
|
25387
|
+
/* @__PURE__ */ jsx(Table.Td, { children: formatDateTime4(contact.createdAt) })
|
|
26278
25388
|
] }, contact.id);
|
|
26279
25389
|
}) })
|
|
26280
25390
|
] }) }),
|
|
26281
|
-
memberTab === "companies" && /* @__PURE__ */ jsx(Fragment, { children:
|
|
25391
|
+
memberTab === "companies" && /* @__PURE__ */ jsx(Fragment, { children: activeError ? /* @__PURE__ */ jsx(CenteredErrorState, { error: activeError, title: "Failed to load companies", h: 160 }) : activeIsInitialLoading ? /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !companies.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No companies attached to this list yet." }) : /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
|
|
26282
25392
|
/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
26283
25393
|
/* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
|
|
26284
25394
|
/* @__PURE__ */ jsx(Table.Th, { children: "Domain" }),
|
|
@@ -26290,15 +25400,15 @@ function MembersTab({
|
|
|
26290
25400
|
] }) }),
|
|
26291
25401
|
/* @__PURE__ */ jsx(Table.Tbody, { children: companies.map((company) => {
|
|
26292
25402
|
const handleRowClick = () => onMemberClick?.(company.id, "company");
|
|
26293
|
-
const memberStage = displayMemberStageFor(company, "company");
|
|
25403
|
+
const memberStage = displayMemberStageFor(company, "company", stageCatalog);
|
|
26294
25404
|
return /* @__PURE__ */ jsxs(Table.Tr, { onClick: handleRowClick, style: { cursor: "pointer" }, children: [
|
|
26295
25405
|
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: company.name }) }),
|
|
26296
25406
|
/* @__PURE__ */ jsx(Table.Td, { children: company.domain ?? "\u2014" }),
|
|
26297
25407
|
/* @__PURE__ */ jsx(Table.Td, { children: company.segment ?? "\u2014" }),
|
|
26298
25408
|
/* @__PURE__ */ jsx(Table.Td, { children: company.contactCount }),
|
|
26299
|
-
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color:
|
|
26300
|
-
/* @__PURE__ */ jsx(Table.Td, { children: memberStage ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "dot", color: getMemberStateColor2(memberStage.key), children: memberStage.label }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" }) }),
|
|
26301
|
-
/* @__PURE__ */ jsx(Table.Td, { children:
|
|
25409
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor6(company.status), children: company.status }) }),
|
|
25410
|
+
/* @__PURE__ */ jsx(Table.Td, { children: memberStage ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "dot", color: getMemberStateColor2(memberStage.key, stageCatalog), children: memberStage.label }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" }) }),
|
|
25411
|
+
/* @__PURE__ */ jsx(Table.Td, { children: formatDateTime4(company.createdAt) })
|
|
26302
25412
|
] }, company.id);
|
|
26303
25413
|
}) })
|
|
26304
25414
|
] }) })
|
|
@@ -26316,6 +25426,8 @@ function ListDetailHeader({
|
|
|
26316
25426
|
function LeadGenListDetailPage({ listId }) {
|
|
26317
25427
|
const navigate = useNavigate();
|
|
26318
25428
|
const actions = useListActions();
|
|
25429
|
+
const leadGenConfig = useLeadGenConfig();
|
|
25430
|
+
const stageCatalog = leadGenConfig.stageCatalog ?? {};
|
|
26319
25431
|
const rawSearch = useSearch({ strict: false });
|
|
26320
25432
|
const memberId = rawSearch.member ?? null;
|
|
26321
25433
|
const memberKind = rawSearch.memberKind ?? null;
|
|
@@ -26336,22 +25448,13 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
26336
25448
|
const progressQuery = useListProgress(listId);
|
|
26337
25449
|
const executionsQuery = useListExecutions(listId);
|
|
26338
25450
|
const deleteListMutation = useDeleteList();
|
|
25451
|
+
const executeAsync = useExecuteAsync();
|
|
25452
|
+
const queryClient = useQueryClient();
|
|
25453
|
+
const { workOSOrganizationId } = useElevasisServices();
|
|
26339
25454
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
|
26340
|
-
const [runModalOpen, setRunModalOpen] = useState(false);
|
|
26341
25455
|
const [activeTab, setActiveTab] = useState("overview");
|
|
26342
25456
|
const [runsResourceFilter, setRunsResourceFilter] = useState(null);
|
|
26343
|
-
const [
|
|
26344
|
-
const [pendingStepRunInput, setPendingStepRunInput] = useState(null);
|
|
26345
|
-
const runModalActions = useMemo(() => {
|
|
26346
|
-
if (!pendingStepRunInput) return actions;
|
|
26347
|
-
return actions.map((action) => {
|
|
26348
|
-
if (action.resourceId !== pendingStepRunInput.resourceId) return action;
|
|
26349
|
-
return {
|
|
26350
|
-
...action,
|
|
26351
|
-
defaultInput: (nextList) => mergeStepRunInput(nextList, action, pendingStepRunInput.inputAtSubmit)
|
|
26352
|
-
};
|
|
26353
|
-
});
|
|
26354
|
-
}, [actions, pendingStepRunInput]);
|
|
25457
|
+
const [optimisticRuns, setOptimisticRuns] = useState([]);
|
|
26355
25458
|
const isLoading = listQuery.isLoading || progressQuery.isLoading || executionsQuery.isLoading;
|
|
26356
25459
|
const error = listQuery.error ?? progressQuery.error ?? executionsQuery.error;
|
|
26357
25460
|
const backButton = /* @__PURE__ */ jsx(
|
|
@@ -26406,31 +25509,42 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
26406
25509
|
const list = listQuery.data;
|
|
26407
25510
|
const progress = progressQuery.data;
|
|
26408
25511
|
const executions = executionsQuery.data ?? [];
|
|
26409
|
-
const businessProgress = deriveBusinessProgress(list, progress, actions, executions);
|
|
25512
|
+
const businessProgress = deriveBusinessProgress(list, progress, actions, executions, leadGenConfig);
|
|
26410
25513
|
const currentBuildTemplateLabel = list.metadata.buildPlanSnapshot?.templateLabel ?? "Default lead generation";
|
|
26411
|
-
const buildResolution = resolveBuildState(list, businessProgress, actions);
|
|
25514
|
+
const buildResolution = resolveBuildState(list, businessProgress, actions, leadGenConfig);
|
|
26412
25515
|
const buildSteps = buildResolution.steps;
|
|
26413
25516
|
const recommendedBuildStep = buildResolution.recommendedStep;
|
|
26414
|
-
const
|
|
26415
|
-
const
|
|
26416
|
-
|
|
26417
|
-
|
|
26418
|
-
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26422
|
-
|
|
26423
|
-
};
|
|
26424
|
-
const openStepRun = (step, inputAtSubmit) => {
|
|
26425
|
-
if (step.action?.schema) {
|
|
26426
|
-
setPendingStepRunInput({
|
|
26427
|
-
resourceId: step.action.resourceId,
|
|
26428
|
-
inputAtSubmit
|
|
25517
|
+
const runStep = async (step, inputAtSubmit) => {
|
|
25518
|
+
const resourceId = step.action?.resourceId;
|
|
25519
|
+
if (!resourceId) return null;
|
|
25520
|
+
try {
|
|
25521
|
+
const result = await executeAsync.mutateAsync({
|
|
25522
|
+
resourceId,
|
|
25523
|
+
resourceType: "workflow",
|
|
25524
|
+
input: inputAtSubmit,
|
|
25525
|
+
listId: list.id
|
|
26429
25526
|
});
|
|
26430
|
-
|
|
26431
|
-
|
|
25527
|
+
showSuccessNotification(`Workflow run started: ${result.executionId}`);
|
|
25528
|
+
setOptimisticRuns((current) => [
|
|
25529
|
+
{
|
|
25530
|
+
executionId: result.executionId,
|
|
25531
|
+
resourceId,
|
|
25532
|
+
status: result.status || "running",
|
|
25533
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25534
|
+
completedAt: null,
|
|
25535
|
+
durationMs: null,
|
|
25536
|
+
input: inputAtSubmit
|
|
25537
|
+
},
|
|
25538
|
+
...current.filter((run2) => run2.executionId !== result.executionId)
|
|
25539
|
+
]);
|
|
25540
|
+
queryClient.invalidateQueries({
|
|
25541
|
+
queryKey: acquisitionListKeys.executionsBase(workOSOrganizationId, list.id)
|
|
25542
|
+
});
|
|
25543
|
+
return result;
|
|
25544
|
+
} catch (error2) {
|
|
25545
|
+
showApiErrorNotification(error2);
|
|
25546
|
+
throw error2;
|
|
26432
25547
|
}
|
|
26433
|
-
openRunModal(step.action?.resourceId ?? null);
|
|
26434
25548
|
};
|
|
26435
25549
|
const handleCopyListCommand = () => {
|
|
26436
25550
|
void navigator.clipboard.writeText(`/acquisition --lead-gen list ${list.id}`);
|
|
@@ -26455,11 +25569,11 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
26455
25569
|
),
|
|
26456
25570
|
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
|
|
26457
25571
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
26458
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color:
|
|
25572
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor6(list.status), children: list.status }),
|
|
26459
25573
|
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "violet", children: currentBuildTemplateLabel }),
|
|
26460
25574
|
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
26461
25575
|
"Created ",
|
|
26462
|
-
|
|
25576
|
+
formatDateTime4(list.createdAt)
|
|
26463
25577
|
] })
|
|
26464
25578
|
] }),
|
|
26465
25579
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
@@ -26482,23 +25596,35 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
26482
25596
|
backButton
|
|
26483
25597
|
] })
|
|
26484
25598
|
] }),
|
|
26485
|
-
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onChange: setActiveTab, children: [
|
|
25599
|
+
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onChange: setActiveTab, keepMounted: false, children: [
|
|
26486
25600
|
/* @__PURE__ */ jsxs(Tabs.List, { children: [
|
|
26487
25601
|
/* @__PURE__ */ jsx(Tabs.Tab, { value: "overview", leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 14 }), children: "Overview" }),
|
|
26488
25602
|
/* @__PURE__ */ jsx(Tabs.Tab, { value: "members", leftSection: /* @__PURE__ */ jsx(IconUsers, { size: 14 }), children: "Members" }),
|
|
26489
25603
|
/* @__PURE__ */ jsx(Tabs.Tab, { value: "build", leftSection: /* @__PURE__ */ jsx(IconBolt, { size: 14 }), children: "Build" }),
|
|
26490
25604
|
/* @__PURE__ */ jsx(Tabs.Tab, { value: "runs", leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 }), children: "Runs" })
|
|
26491
25605
|
] }),
|
|
26492
|
-
/* @__PURE__ */ jsx(Tabs.Panel, { value: "overview", pt: "sm", children: /* @__PURE__ */ jsx(OverviewTab, { list, progress: businessProgress }) }),
|
|
26493
|
-
/* @__PURE__ */ jsx(Tabs.Panel, { value: "members", pt: "sm", children: /* @__PURE__ */ jsx(
|
|
25606
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "overview", pt: "sm", children: /* @__PURE__ */ jsx(OverviewTab, { list, progress: businessProgress, leadGenConfig }) }),
|
|
25607
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "members", pt: "sm", children: /* @__PURE__ */ jsx(
|
|
25608
|
+
MembersTab,
|
|
25609
|
+
{
|
|
25610
|
+
listId,
|
|
25611
|
+
progress: businessProgress,
|
|
25612
|
+
stageCatalog,
|
|
25613
|
+
onMemberClick: handleMemberClick
|
|
25614
|
+
}
|
|
25615
|
+
) }),
|
|
26494
25616
|
/* @__PURE__ */ jsx(Tabs.Panel, { value: "build", pt: "sm", children: /* @__PURE__ */ jsx(
|
|
26495
25617
|
BuildTab,
|
|
26496
25618
|
{
|
|
26497
25619
|
list,
|
|
26498
25620
|
steps: buildSteps,
|
|
25621
|
+
executions,
|
|
26499
25622
|
recommendedStep: recommendedBuildStep,
|
|
26500
|
-
|
|
26501
|
-
|
|
25623
|
+
optimisticRuns,
|
|
25624
|
+
exportWorkflowId: leadGenConfig.exportWorkflowId,
|
|
25625
|
+
stageCatalog,
|
|
25626
|
+
onRunStep: runStep,
|
|
25627
|
+
onRetryStep: runStep,
|
|
26502
25628
|
onViewRunLog: (resourceId, executionId) => {
|
|
26503
25629
|
void navigate({
|
|
26504
25630
|
to: "/operations/resources/workflow/$workflowId",
|
|
@@ -26545,25 +25671,551 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
26545
25671
|
] })
|
|
26546
25672
|
] })
|
|
26547
25673
|
}
|
|
25674
|
+
)
|
|
25675
|
+
] });
|
|
25676
|
+
}
|
|
25677
|
+
function ListBuilderIndexPage() {
|
|
25678
|
+
const navigate = useNavigate();
|
|
25679
|
+
const [query, setQuery] = useState("");
|
|
25680
|
+
const listsQuery = useLists();
|
|
25681
|
+
const lists = listsQuery.data ?? [];
|
|
25682
|
+
const filteredLists = useMemo(() => {
|
|
25683
|
+
const normalized = query.trim().toLowerCase();
|
|
25684
|
+
if (!normalized) return lists;
|
|
25685
|
+
return lists.filter((list) => list.name.toLowerCase().includes(normalized));
|
|
25686
|
+
}, [lists, query]);
|
|
25687
|
+
const openList = (listId) => {
|
|
25688
|
+
navigate({ to: "/lead-gen/list-builder/$listId", params: { listId } });
|
|
25689
|
+
};
|
|
25690
|
+
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
25691
|
+
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Builder", caption: "Choose a list to run lead-gen workflows and monitor progress." }),
|
|
25692
|
+
/* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
25693
|
+
/* @__PURE__ */ jsx(
|
|
25694
|
+
TextInput,
|
|
25695
|
+
{
|
|
25696
|
+
placeholder: "Search lists...",
|
|
25697
|
+
leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
|
|
25698
|
+
value: query,
|
|
25699
|
+
onChange: (event) => setQuery(event.currentTarget.value)
|
|
25700
|
+
}
|
|
25701
|
+
),
|
|
25702
|
+
listsQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : !filteredLists.length ? /* @__PURE__ */ jsx(
|
|
25703
|
+
EmptyState,
|
|
25704
|
+
{
|
|
25705
|
+
icon: IconLayoutDashboard,
|
|
25706
|
+
title: query.trim() ? "No lists match your search" : "No lists available",
|
|
25707
|
+
description: query.trim() ? void 0 : "Create a list first, then open it in the builder."
|
|
25708
|
+
}
|
|
25709
|
+
) : /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
|
|
25710
|
+
/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
25711
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
|
|
25712
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
|
|
25713
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Batches" }),
|
|
25714
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Created" })
|
|
25715
|
+
] }) }),
|
|
25716
|
+
/* @__PURE__ */ jsx(Table.Tbody, { children: filteredLists.map((list) => /* @__PURE__ */ jsxs(
|
|
25717
|
+
Table.Tr,
|
|
25718
|
+
{
|
|
25719
|
+
role: "button",
|
|
25720
|
+
tabIndex: 0,
|
|
25721
|
+
onClick: () => openList(list.id),
|
|
25722
|
+
onKeyDown: (event) => {
|
|
25723
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
25724
|
+
event.preventDefault();
|
|
25725
|
+
openList(list.id);
|
|
25726
|
+
}
|
|
25727
|
+
},
|
|
25728
|
+
style: { cursor: "pointer" },
|
|
25729
|
+
children: [
|
|
25730
|
+
/* @__PURE__ */ jsxs(Table.Td, { children: [
|
|
25731
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: list.name }),
|
|
25732
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: list.description ?? list.id })
|
|
25733
|
+
] }),
|
|
25734
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStateKeyColor(list.status), children: list.status }) }),
|
|
25735
|
+
/* @__PURE__ */ jsx(Table.Td, { children: list.batchIds.length }),
|
|
25736
|
+
/* @__PURE__ */ jsx(Table.Td, { children: formatDate3(list.createdAt) })
|
|
25737
|
+
]
|
|
25738
|
+
},
|
|
25739
|
+
list.id
|
|
25740
|
+
)) })
|
|
25741
|
+
] })
|
|
25742
|
+
] }) })
|
|
25743
|
+
] }) }) });
|
|
25744
|
+
}
|
|
25745
|
+
|
|
25746
|
+
// src/lib/lead-gen/stage-colors.ts
|
|
25747
|
+
var FALLBACK_STAGE_COLORS = {
|
|
25748
|
+
accent: "var(--color-text-dimmed)",
|
|
25749
|
+
background: "color-mix(in srgb, var(--color-text-dimmed) 10%, transparent)",
|
|
25750
|
+
border: "color-mix(in srgb, var(--color-border) 85%, var(--color-text-dimmed))",
|
|
25751
|
+
text: "var(--color-text)"
|
|
25752
|
+
};
|
|
25753
|
+
var STAGE_COLOR_SETS = {
|
|
25754
|
+
scraped: {
|
|
25755
|
+
accent: "var(--color-text-subtle)",
|
|
25756
|
+
background: "color-mix(in srgb, var(--color-text-subtle) 12%, transparent)",
|
|
25757
|
+
border: "color-mix(in srgb, var(--color-border) 80%, var(--color-text-subtle))",
|
|
25758
|
+
text: "var(--color-text)"
|
|
25759
|
+
},
|
|
25760
|
+
populated: {
|
|
25761
|
+
accent: "var(--color-primary)",
|
|
25762
|
+
background: "color-mix(in srgb, var(--color-primary) 12%, transparent)",
|
|
25763
|
+
border: "color-mix(in srgb, var(--color-border) 70%, var(--color-primary))",
|
|
25764
|
+
text: "var(--color-text)"
|
|
25765
|
+
},
|
|
25766
|
+
crawled: {
|
|
25767
|
+
accent: "color-mix(in srgb, var(--color-primary) 70%, var(--color-text-subtle))",
|
|
25768
|
+
background: "color-mix(in srgb, var(--color-primary) 9%, transparent)",
|
|
25769
|
+
border: "color-mix(in srgb, var(--color-border) 72%, var(--color-primary))",
|
|
25770
|
+
text: "var(--color-text)"
|
|
25771
|
+
},
|
|
25772
|
+
extracted: {
|
|
25773
|
+
accent: "color-mix(in srgb, var(--color-primary) 78%, var(--color-success))",
|
|
25774
|
+
background: "color-mix(in srgb, var(--color-primary) 10%, transparent)",
|
|
25775
|
+
border: "color-mix(in srgb, var(--color-border) 65%, var(--color-primary))",
|
|
25776
|
+
text: "var(--color-text)"
|
|
25777
|
+
},
|
|
25778
|
+
enriched: {
|
|
25779
|
+
accent: "color-mix(in srgb, var(--color-success) 70%, var(--color-primary))",
|
|
25780
|
+
background: "color-mix(in srgb, var(--color-success) 12%, transparent)",
|
|
25781
|
+
border: "color-mix(in srgb, var(--color-border) 68%, var(--color-success))",
|
|
25782
|
+
text: "var(--color-text)"
|
|
25783
|
+
},
|
|
25784
|
+
"decision-makers-enriched": {
|
|
25785
|
+
accent: "color-mix(in srgb, var(--color-primary) 66%, var(--color-warning))",
|
|
25786
|
+
background: "color-mix(in srgb, var(--color-primary) 12%, transparent)",
|
|
25787
|
+
border: "color-mix(in srgb, var(--color-border) 66%, var(--color-primary))",
|
|
25788
|
+
text: "var(--color-text)"
|
|
25789
|
+
},
|
|
25790
|
+
discovered: {
|
|
25791
|
+
accent: "color-mix(in srgb, var(--color-primary) 70%, var(--color-warning))",
|
|
25792
|
+
background: "color-mix(in srgb, var(--color-warning) 10%, transparent)",
|
|
25793
|
+
border: "color-mix(in srgb, var(--color-border) 68%, var(--color-warning))",
|
|
25794
|
+
text: "var(--color-text)"
|
|
25795
|
+
},
|
|
25796
|
+
verified: {
|
|
25797
|
+
accent: "var(--color-success)",
|
|
25798
|
+
background: "color-mix(in srgb, var(--color-success) 12%, transparent)",
|
|
25799
|
+
border: "color-mix(in srgb, var(--color-border) 64%, var(--color-success))",
|
|
25800
|
+
text: "var(--color-text)"
|
|
25801
|
+
},
|
|
25802
|
+
qualified: {
|
|
25803
|
+
accent: "color-mix(in srgb, var(--color-success) 82%, var(--color-text))",
|
|
25804
|
+
background: "color-mix(in srgb, var(--color-success) 14%, transparent)",
|
|
25805
|
+
border: "color-mix(in srgb, var(--color-border) 62%, var(--color-success))",
|
|
25806
|
+
text: "var(--color-text)"
|
|
25807
|
+
},
|
|
25808
|
+
personalized: {
|
|
25809
|
+
accent: "color-mix(in srgb, var(--color-primary) 58%, var(--color-success))",
|
|
25810
|
+
background: "color-mix(in srgb, var(--color-primary) 11%, transparent)",
|
|
25811
|
+
border: "color-mix(in srgb, var(--color-border) 66%, var(--color-primary))",
|
|
25812
|
+
text: "var(--color-text)"
|
|
25813
|
+
},
|
|
25814
|
+
uploaded: {
|
|
25815
|
+
accent: "color-mix(in srgb, var(--color-warning) 72%, var(--color-primary))",
|
|
25816
|
+
background: "color-mix(in srgb, var(--color-warning) 12%, transparent)",
|
|
25817
|
+
border: "color-mix(in srgb, var(--color-border) 64%, var(--color-warning))",
|
|
25818
|
+
text: "var(--color-text)"
|
|
25819
|
+
},
|
|
25820
|
+
interested: {
|
|
25821
|
+
accent: "color-mix(in srgb, var(--color-success) 72%, var(--color-warning))",
|
|
25822
|
+
background: "color-mix(in srgb, var(--color-success) 15%, transparent)",
|
|
25823
|
+
border: "color-mix(in srgb, var(--color-border) 58%, var(--color-success))",
|
|
25824
|
+
text: "var(--color-text)"
|
|
25825
|
+
},
|
|
25826
|
+
disqualified: {
|
|
25827
|
+
accent: "var(--color-error)",
|
|
25828
|
+
background: "color-mix(in srgb, var(--color-error) 10%, transparent)",
|
|
25829
|
+
border: "color-mix(in srgb, var(--color-border) 66%, var(--color-error))",
|
|
25830
|
+
text: "var(--color-text)"
|
|
25831
|
+
},
|
|
25832
|
+
invalid: {
|
|
25833
|
+
accent: "color-mix(in srgb, var(--color-error) 72%, var(--color-text-dimmed))",
|
|
25834
|
+
background: "color-mix(in srgb, var(--color-error) 8%, transparent)",
|
|
25835
|
+
border: "color-mix(in srgb, var(--color-border) 78%, var(--color-error))",
|
|
25836
|
+
text: "var(--color-text)"
|
|
25837
|
+
}
|
|
25838
|
+
};
|
|
25839
|
+
function getLeadGenStageColor(stageKey) {
|
|
25840
|
+
return STAGE_COLOR_SETS[stageKey] ?? FALLBACK_STAGE_COLORS;
|
|
25841
|
+
}
|
|
25842
|
+
function getLeadGenStageColorVar(stageKey, tone = "accent") {
|
|
25843
|
+
return getLeadGenStageColor(stageKey)[tone];
|
|
25844
|
+
}
|
|
25845
|
+
var FALLBACK_STAGE_ORDER = 1e4;
|
|
25846
|
+
function unique(values) {
|
|
25847
|
+
return Array.from(new Set(values.filter(Boolean)));
|
|
25848
|
+
}
|
|
25849
|
+
function configuredStages(pipelineConfig, stageCatalog) {
|
|
25850
|
+
return (pipelineConfig?.stages ?? []).filter((stage) => stage.enabled !== false).slice().sort((a, b) => {
|
|
25851
|
+
const aOrder = a.order ?? stageCatalog[a.key]?.order ?? FALLBACK_STAGE_ORDER;
|
|
25852
|
+
const bOrder = b.order ?? stageCatalog[b.key]?.order ?? FALLBACK_STAGE_ORDER;
|
|
25853
|
+
return aOrder - bOrder || a.key.localeCompare(b.key);
|
|
25854
|
+
});
|
|
25855
|
+
}
|
|
25856
|
+
function workflowStageKeys(actions) {
|
|
25857
|
+
return unique((actions ?? []).flatMap((action) => [...action.stagesAffected]));
|
|
25858
|
+
}
|
|
25859
|
+
function sourceFor(stageKey, observedKeys, configKeys, workflowKeys) {
|
|
25860
|
+
if (observedKeys.has(stageKey)) return "activity";
|
|
25861
|
+
if (configKeys.has(stageKey)) return "config";
|
|
25862
|
+
if (workflowKeys.has(stageKey)) return "workflow";
|
|
25863
|
+
return "activity";
|
|
25864
|
+
}
|
|
25865
|
+
function sortStageNodes(nodes) {
|
|
25866
|
+
return nodes.slice().sort((a, b) => a.order - b.order || a.key.localeCompare(b.key));
|
|
25867
|
+
}
|
|
25868
|
+
function buildLaneStages({
|
|
25869
|
+
entity,
|
|
25870
|
+
progress,
|
|
25871
|
+
pipelineConfig,
|
|
25872
|
+
actions,
|
|
25873
|
+
stageCatalog
|
|
25874
|
+
}) {
|
|
25875
|
+
const stageMap = entity === "company" ? progress.byCompanyStage : progress.byContactStage;
|
|
25876
|
+
const observedKeys = new Set(Object.keys(stageMap));
|
|
25877
|
+
const configStages = configuredStages(pipelineConfig, stageCatalog);
|
|
25878
|
+
const configStageByKey = new Map(configStages.map((stage) => [stage.key, stage]));
|
|
25879
|
+
const configKeys = new Set(configStages.map((stage) => stage.key));
|
|
25880
|
+
const workflowKeys = new Set(workflowStageKeys(actions));
|
|
25881
|
+
const stageKeys = unique([...observedKeys, ...configKeys, ...workflowKeys]);
|
|
25882
|
+
return sortStageNodes(
|
|
25883
|
+
stageKeys.flatMap((key) => {
|
|
25884
|
+
const catalogEntry = stageCatalog[key];
|
|
25885
|
+
const inferredEntity = catalogEntry?.entity ?? (observedKeys.has(key) ? entity : null);
|
|
25886
|
+
if (inferredEntity !== entity) return [];
|
|
25887
|
+
return [
|
|
25888
|
+
{
|
|
25889
|
+
key,
|
|
25890
|
+
label: configStageByKey.get(key)?.label ?? catalogEntry?.label ?? key,
|
|
25891
|
+
order: configStageByKey.get(key)?.order ?? catalogEntry?.order ?? FALLBACK_STAGE_ORDER,
|
|
25892
|
+
entity,
|
|
25893
|
+
source: sourceFor(key, observedKeys, configKeys, workflowKeys)
|
|
25894
|
+
}
|
|
25895
|
+
];
|
|
25896
|
+
})
|
|
25897
|
+
);
|
|
25898
|
+
}
|
|
25899
|
+
function getStageProgress2(progress, stageKey, entity) {
|
|
25900
|
+
const stageProgress = entity === "company" ? progress.byCompanyStage[stageKey] : progress.byContactStage[stageKey];
|
|
25901
|
+
const total = stageProgress?.total ?? (entity === "company" ? progress.totalCompanies : progress.totalMembers);
|
|
25902
|
+
return {
|
|
25903
|
+
total,
|
|
25904
|
+
attempted: stageProgress?.attempted ?? 0,
|
|
25905
|
+
success: stageProgress?.success ?? 0,
|
|
25906
|
+
noResult: stageProgress?.noResult ?? 0,
|
|
25907
|
+
skipped: stageProgress?.skipped ?? 0,
|
|
25908
|
+
error: stageProgress?.error ?? 0,
|
|
25909
|
+
other: stageProgress?.other ?? 0,
|
|
25910
|
+
notAttempted: stageProgress?.notAttempted ?? total
|
|
25911
|
+
};
|
|
25912
|
+
}
|
|
25913
|
+
function percent(value, total) {
|
|
25914
|
+
if (total <= 0) return 0;
|
|
25915
|
+
return Math.max(0, Math.min(100, value / total * 100));
|
|
25916
|
+
}
|
|
25917
|
+
function SourceBadge({ source }) {
|
|
25918
|
+
const label = source === "activity" ? "recorded" : source;
|
|
25919
|
+
const color = source === "activity" ? "green" : source === "config" ? "blue" : "gray";
|
|
25920
|
+
return /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color, children: label });
|
|
25921
|
+
}
|
|
25922
|
+
function ProgressRail({ counts, stageKey }) {
|
|
25923
|
+
const accent = getLeadGenStageColorVar(stageKey);
|
|
25924
|
+
const segments = [
|
|
25925
|
+
{ key: "success", value: counts.success, color: accent },
|
|
25926
|
+
{ key: "noResult", value: counts.noResult, color: "var(--color-text-subtle)" },
|
|
25927
|
+
{ key: "skipped", value: counts.skipped, color: "var(--color-warning)" },
|
|
25928
|
+
{ key: "error", value: counts.error, color: "var(--color-error)" },
|
|
25929
|
+
{ key: "other", value: counts.other, color: "var(--color-primary)" }
|
|
25930
|
+
].filter((segment) => segment.value > 0);
|
|
25931
|
+
return /* @__PURE__ */ jsx(
|
|
25932
|
+
Box,
|
|
25933
|
+
{
|
|
25934
|
+
h: 6,
|
|
25935
|
+
bg: "var(--color-surface-hover)",
|
|
25936
|
+
style: {
|
|
25937
|
+
borderRadius: 999,
|
|
25938
|
+
display: "flex",
|
|
25939
|
+
overflow: "hidden",
|
|
25940
|
+
opacity: counts.total > 0 ? 1 : 0.55
|
|
25941
|
+
},
|
|
25942
|
+
children: segments.length > 0 ? segments.map((segment) => /* @__PURE__ */ jsx(Box, { h: "100%", w: `${percent(segment.value, counts.total)}%`, bg: segment.color }, segment.key)) : /* @__PURE__ */ jsx(Box, { h: "100%", w: counts.total > 0 ? `${percent(counts.attempted, counts.total)}%` : "0%", bg: accent })
|
|
25943
|
+
}
|
|
25944
|
+
);
|
|
25945
|
+
}
|
|
25946
|
+
function TimelineLane({
|
|
25947
|
+
title,
|
|
25948
|
+
entity,
|
|
25949
|
+
total,
|
|
25950
|
+
stages,
|
|
25951
|
+
progress,
|
|
25952
|
+
emptyText
|
|
25953
|
+
}) {
|
|
25954
|
+
const Icon = entity === "company" ? IconBuilding : IconUsers;
|
|
25955
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
25956
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", gap: "xs", children: [
|
|
25957
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
25958
|
+
/* @__PURE__ */ jsx(
|
|
25959
|
+
Box,
|
|
25960
|
+
{
|
|
25961
|
+
w: 28,
|
|
25962
|
+
h: 28,
|
|
25963
|
+
style: {
|
|
25964
|
+
alignItems: "center",
|
|
25965
|
+
background: "color-mix(in srgb, var(--color-primary) 14%, transparent)",
|
|
25966
|
+
border: "1px solid color-mix(in srgb, var(--color-border) 75%, var(--color-primary))",
|
|
25967
|
+
borderRadius: 999,
|
|
25968
|
+
color: "var(--color-primary)",
|
|
25969
|
+
display: "flex",
|
|
25970
|
+
justifyContent: "center"
|
|
25971
|
+
},
|
|
25972
|
+
children: /* @__PURE__ */ jsx(Icon, { size: 15 })
|
|
25973
|
+
}
|
|
25974
|
+
),
|
|
25975
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 0, children: [
|
|
25976
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: title }),
|
|
25977
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
25978
|
+
total,
|
|
25979
|
+
" ",
|
|
25980
|
+
entity === "company" ? "companies" : "contacts"
|
|
25981
|
+
] })
|
|
25982
|
+
] })
|
|
25983
|
+
] }),
|
|
25984
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "outline", color: entity === "company" ? "blue" : "teal", children: [
|
|
25985
|
+
stages.length,
|
|
25986
|
+
" stages"
|
|
25987
|
+
] })
|
|
25988
|
+
] }),
|
|
25989
|
+
stages.length === 0 ? /* @__PURE__ */ jsx(
|
|
25990
|
+
Box,
|
|
25991
|
+
{
|
|
25992
|
+
p: "sm",
|
|
25993
|
+
style: {
|
|
25994
|
+
border: "1px dashed var(--color-border)",
|
|
25995
|
+
borderRadius: "var(--mantine-radius-md)"
|
|
25996
|
+
},
|
|
25997
|
+
children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: emptyText })
|
|
25998
|
+
}
|
|
25999
|
+
) : /* @__PURE__ */ jsx(ScrollArea, { type: "hover", offsetScrollbars: true, children: /* @__PURE__ */ jsx(
|
|
26000
|
+
Box,
|
|
26001
|
+
{
|
|
26002
|
+
style: {
|
|
26003
|
+
minWidth: Math.max(560, stages.length * 178),
|
|
26004
|
+
padding: "8px 2px 2px"
|
|
26005
|
+
},
|
|
26006
|
+
children: /* @__PURE__ */ jsx(
|
|
26007
|
+
Box,
|
|
26008
|
+
{
|
|
26009
|
+
style: {
|
|
26010
|
+
alignItems: "start",
|
|
26011
|
+
display: "grid",
|
|
26012
|
+
gap: 0,
|
|
26013
|
+
gridTemplateColumns: `repeat(${stages.length}, minmax(150px, 1fr))`,
|
|
26014
|
+
position: "relative"
|
|
26015
|
+
},
|
|
26016
|
+
children: stages.map((stage, index) => {
|
|
26017
|
+
const counts = getStageProgress2(progress, stage.key, entity);
|
|
26018
|
+
const accent = getLeadGenStageColorVar(stage.key);
|
|
26019
|
+
const completion = Math.round(percent(counts.success, counts.total));
|
|
26020
|
+
const attempted = Math.round(percent(counts.attempted, counts.total));
|
|
26021
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: 8, px: "xs", style: { position: "relative", zIndex: 1 }, children: [
|
|
26022
|
+
/* @__PURE__ */ jsxs(Group, { gap: 8, wrap: "nowrap", children: [
|
|
26023
|
+
/* @__PURE__ */ jsx(
|
|
26024
|
+
Box,
|
|
26025
|
+
{
|
|
26026
|
+
w: 44,
|
|
26027
|
+
h: 44,
|
|
26028
|
+
style: {
|
|
26029
|
+
alignItems: "center",
|
|
26030
|
+
background: getLeadGenStageColorVar(stage.key, "background"),
|
|
26031
|
+
border: `1px solid ${getLeadGenStageColorVar(stage.key, "border")}`,
|
|
26032
|
+
borderRadius: 999,
|
|
26033
|
+
boxShadow: `0 0 0 4px ${getLeadGenStageColorVar(stage.key, "background")}`,
|
|
26034
|
+
color: accent,
|
|
26035
|
+
display: "flex",
|
|
26036
|
+
flexShrink: 0,
|
|
26037
|
+
fontSize: 13,
|
|
26038
|
+
fontWeight: 800,
|
|
26039
|
+
justifyContent: "center"
|
|
26040
|
+
},
|
|
26041
|
+
children: index + 1
|
|
26042
|
+
}
|
|
26043
|
+
),
|
|
26044
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 1, style: { minWidth: 0 }, children: [
|
|
26045
|
+
/* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
|
|
26046
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, lineClamp: 1, children: stage.label }),
|
|
26047
|
+
/* @__PURE__ */ jsx(SourceBadge, { source: stage.source })
|
|
26048
|
+
] }),
|
|
26049
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 1, children: counts.total > 0 ? `${counts.attempted} / ${counts.total} attempted` : `Ready for ${entity === "company" ? "company" : "contact"} rows` })
|
|
26050
|
+
] })
|
|
26051
|
+
] }),
|
|
26052
|
+
/* @__PURE__ */ jsx(ProgressRail, { counts, stageKey: stage.key }),
|
|
26053
|
+
/* @__PURE__ */ jsxs(Group, { gap: 10, wrap: "nowrap", children: [
|
|
26054
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
26055
|
+
counts.success,
|
|
26056
|
+
" success"
|
|
26057
|
+
] }),
|
|
26058
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
26059
|
+
attempted,
|
|
26060
|
+
"% attempted"
|
|
26061
|
+
] }),
|
|
26062
|
+
counts.error > 0 ? /* @__PURE__ */ jsxs(Text, { size: "xs", c: "red", children: [
|
|
26063
|
+
counts.error,
|
|
26064
|
+
" errors"
|
|
26065
|
+
] }) : null
|
|
26066
|
+
] }),
|
|
26067
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
26068
|
+
completion,
|
|
26069
|
+
"% complete"
|
|
26070
|
+
] })
|
|
26071
|
+
] }, stage.key);
|
|
26072
|
+
})
|
|
26073
|
+
}
|
|
26074
|
+
)
|
|
26075
|
+
}
|
|
26076
|
+
) })
|
|
26077
|
+
] });
|
|
26078
|
+
}
|
|
26079
|
+
function PipelineFunnel({ progress, pipelineConfig, actions }) {
|
|
26080
|
+
const { stageCatalog = {} } = useLeadGenConfig();
|
|
26081
|
+
const companyStages = buildLaneStages({ entity: "company", progress, pipelineConfig, actions, stageCatalog });
|
|
26082
|
+
const contactStages = buildLaneStages({ entity: "contact", progress, pipelineConfig, actions, stageCatalog });
|
|
26083
|
+
return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "lg", children: [
|
|
26084
|
+
/* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconListDetails, { size: 16 }), title: "Pipeline" }),
|
|
26085
|
+
/* @__PURE__ */ jsx(
|
|
26086
|
+
TimelineLane,
|
|
26087
|
+
{
|
|
26088
|
+
title: "Company pipeline",
|
|
26089
|
+
entity: "company",
|
|
26090
|
+
total: progress.totalCompanies,
|
|
26091
|
+
stages: companyStages,
|
|
26092
|
+
progress,
|
|
26093
|
+
emptyText: "No company stages are configured, runnable, or recorded yet."
|
|
26094
|
+
}
|
|
26548
26095
|
),
|
|
26549
26096
|
/* @__PURE__ */ jsx(
|
|
26550
|
-
|
|
26097
|
+
TimelineLane,
|
|
26551
26098
|
{
|
|
26552
|
-
|
|
26553
|
-
|
|
26554
|
-
|
|
26555
|
-
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
title: "Run build step",
|
|
26559
|
-
description: "Run the selected bounded build workflow for this list.",
|
|
26560
|
-
lockResourceSelection: true,
|
|
26561
|
-
onSubmitted: (_, executionId) => {
|
|
26562
|
-
showSuccessNotification(`Workflow run started: ${executionId}`);
|
|
26563
|
-
}
|
|
26099
|
+
title: "Contact pipeline",
|
|
26100
|
+
entity: "contact",
|
|
26101
|
+
total: progress.totalMembers,
|
|
26102
|
+
stages: contactStages,
|
|
26103
|
+
progress,
|
|
26104
|
+
emptyText: "No contact stages are configured, runnable, or recorded yet."
|
|
26564
26105
|
}
|
|
26565
26106
|
)
|
|
26566
|
-
] });
|
|
26107
|
+
] }) });
|
|
26108
|
+
}
|
|
26109
|
+
function formatDateTime5(value) {
|
|
26110
|
+
if (!value) return "Not yet";
|
|
26111
|
+
return new Date(value).toLocaleString("en-US", {
|
|
26112
|
+
month: "short",
|
|
26113
|
+
day: "numeric",
|
|
26114
|
+
year: "numeric",
|
|
26115
|
+
hour: "numeric",
|
|
26116
|
+
minute: "2-digit"
|
|
26117
|
+
});
|
|
26118
|
+
}
|
|
26119
|
+
function getStatusColor7(status) {
|
|
26120
|
+
switch (status) {
|
|
26121
|
+
case "completed":
|
|
26122
|
+
case "success":
|
|
26123
|
+
case "launched":
|
|
26124
|
+
return "green";
|
|
26125
|
+
case "running":
|
|
26126
|
+
case "pending":
|
|
26127
|
+
case "enriching":
|
|
26128
|
+
return "blue";
|
|
26129
|
+
case "failed":
|
|
26130
|
+
case "error":
|
|
26131
|
+
case "archived":
|
|
26132
|
+
return "red";
|
|
26133
|
+
case "closing":
|
|
26134
|
+
return "yellow";
|
|
26135
|
+
default:
|
|
26136
|
+
return "gray";
|
|
26137
|
+
}
|
|
26138
|
+
}
|
|
26139
|
+
function ListBuilderPage({ listId }) {
|
|
26140
|
+
const navigate = useNavigate();
|
|
26141
|
+
const actions = useListActions();
|
|
26142
|
+
const listQuery = useList(listId);
|
|
26143
|
+
const progressQuery = useListProgress(listId);
|
|
26144
|
+
const executionsQuery = useListExecutions(listId);
|
|
26145
|
+
const isLoading = listQuery.isLoading || progressQuery.isLoading || executionsQuery.isLoading;
|
|
26146
|
+
const error = listQuery.error ?? progressQuery.error ?? executionsQuery.error;
|
|
26147
|
+
const executions = useMemo(() => executionsQuery.data ?? [], [executionsQuery.data]);
|
|
26148
|
+
const openListDetail = () => {
|
|
26149
|
+
void navigate({ to: "/lead-gen/lists/$listId", params: { listId } });
|
|
26150
|
+
};
|
|
26151
|
+
const copyListCommand = (id) => {
|
|
26152
|
+
void navigator.clipboard.writeText(`/acquisition --lead-gen list ${id}`);
|
|
26153
|
+
showSuccessNotification("Copied list command to clipboard");
|
|
26154
|
+
};
|
|
26155
|
+
const backButton = /* @__PURE__ */ jsx(
|
|
26156
|
+
Button,
|
|
26157
|
+
{
|
|
26158
|
+
variant: "light",
|
|
26159
|
+
size: "xs",
|
|
26160
|
+
leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
|
|
26161
|
+
onClick: () => navigate({ to: "/lead-gen/lists" }),
|
|
26162
|
+
children: "Lists"
|
|
26163
|
+
}
|
|
26164
|
+
);
|
|
26165
|
+
if (isLoading) {
|
|
26166
|
+
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
26167
|
+
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Builder", caption: "Lead-gen workspace", rightSection: backButton }),
|
|
26168
|
+
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) })
|
|
26169
|
+
] }) }) });
|
|
26170
|
+
}
|
|
26171
|
+
if (error) {
|
|
26172
|
+
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
26173
|
+
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Builder", caption: "Lead-gen workspace", rightSection: backButton }),
|
|
26174
|
+
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load list builder" }) })
|
|
26175
|
+
] }) }) });
|
|
26176
|
+
}
|
|
26177
|
+
if (!listQuery.data || !progressQuery.data) {
|
|
26178
|
+
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
26179
|
+
/* @__PURE__ */ jsx(PageTitleCaption, { title: "List Not Found", caption: "The requested lead-gen list is unavailable." }),
|
|
26180
|
+
/* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { h: 240, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "The requested list could not be found." }) }) })
|
|
26181
|
+
] }) }) });
|
|
26182
|
+
}
|
|
26183
|
+
const list = listQuery.data;
|
|
26184
|
+
const progress = progressQuery.data;
|
|
26185
|
+
return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
26186
|
+
/* @__PURE__ */ jsx(
|
|
26187
|
+
PageTitleCaption,
|
|
26188
|
+
{
|
|
26189
|
+
title: list.name,
|
|
26190
|
+
caption: list.description ?? "Lead-gen list builder",
|
|
26191
|
+
rightSection: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
26192
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", leftSection: /* @__PURE__ */ jsx(IconBolt, { size: 16 }), onClick: openListDetail, children: "Open Build" }),
|
|
26193
|
+
backButton
|
|
26194
|
+
] })
|
|
26195
|
+
}
|
|
26196
|
+
),
|
|
26197
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
26198
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
26199
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor7(list.status), children: list.status }),
|
|
26200
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
26201
|
+
"Created ",
|
|
26202
|
+
formatDateTime5(list.createdAt)
|
|
26203
|
+
] })
|
|
26204
|
+
] }),
|
|
26205
|
+
/* @__PURE__ */ jsx(Group, { gap: "xs", children: /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", onClick: () => copyListCommand(list.id), style: { cursor: "pointer" }, children: [
|
|
26206
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", children: list.id }),
|
|
26207
|
+
/* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", "aria-label": "Copy list command", children: /* @__PURE__ */ jsx(IconCopy, { size: 14 }) })
|
|
26208
|
+
] }) })
|
|
26209
|
+
] }),
|
|
26210
|
+
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2, lg: 4 }, children: [
|
|
26211
|
+
/* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
|
|
26212
|
+
/* @__PURE__ */ jsx(StatCard, { label: "Contacts", value: progress.totalMembers, icon: IconUsers }),
|
|
26213
|
+
/* @__PURE__ */ jsx(StatCard, { label: "Workflows", value: actions.length, icon: IconBolt }),
|
|
26214
|
+
/* @__PURE__ */ jsx(StatCard, { label: "Runs", value: executions.length, icon: IconPlayerPlay })
|
|
26215
|
+
] }),
|
|
26216
|
+
/* @__PURE__ */ jsx(PipelineFunnel, { progress, pipelineConfig: list.pipelineConfig, actions }),
|
|
26217
|
+
/* @__PURE__ */ jsx(WorkflowRunsPanel, { listId })
|
|
26218
|
+
] }) }) });
|
|
26567
26219
|
}
|
|
26568
26220
|
var PAGE_SIZE_DEFAULT3 = 20;
|
|
26569
26221
|
function LeadGenCompaniesPage() {
|
|
@@ -41446,4 +41098,4 @@ function createUseOrgInitialization(useOrganizations, useApiClient2) {
|
|
|
41446
41098
|
};
|
|
41447
41099
|
}
|
|
41448
41100
|
|
|
41449
|
-
export { AbsoluteScheduleForm, AccountSettings, ActionModal, ActivityCard, ActivityFeed, ActivityFeedWidget, ActivityFilters, ActivityLog, ActivityTable, AgentDefinitionDisplay, AgentExecutionLogs, AgentExecutionPanel, AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, AgentSessionGroup, AllTasksPage, ApiKeyDisplayModal, ApiKeyList, ApiKeyService, ApiKeySettings, AppErrorBoundary, AppearanceSettings, BaseEdge, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates, BaseNode, Breadcrumbs, BusinessImpactCard, CRM_ITEMS, Can, Checklist, CheckpointGroup, CollapsibleJsonSection, CommandQueueDetailPage, CommandQueuePage, CommandQueueShell, CommandQueueSidebar, CommandQueueSidebarMiddle, CommandQueueSidebarTop, CommandQueueTaskRow, CommandViewPage, CompanyDetailPage, ConfigCard, ConfirmationInputModal, ConfirmationModal, ContactDetailPage, ContentSections, ContextUsageBadge, ContractDisplay, ConversationThread, CostAnalytics, CostBreakdownCard, CostByModelTable, CostMetricsCard, CrashErrorFallback, CreateApiKeyModal, CreateCredentialModal, CreateDeliveryEntityModal, CreateRoleModal, CreateScheduleModal, CreateWebhookEndpointModal, CredentialList, CredentialService, CredentialSettings, CrmActionsProvider, CrmOverview, CrmSettingsPage, CrmSidebar, CrmSidebarMiddle, CrmSidebarTop, CustomModal, DEAL_STAGES, DEAL_STAGE_COLORS, DEAL_STAGE_OPTIONS, DEFAULT_KANBAN_CONFIG, DELIVERY_COMMUNICATION_ITEMS, DELIVERY_PROJECT_ITEMS, DELIVERY_WORK_ITEMS, Dashboard, DashboardOperationsOverview, DealDetailPage, DealKanbanCard, DealsListPage, DeleteScheduleModal, DeploymentDetailModal, DeploymentList, DeploymentService, DeploymentSettings, DeploymentStatusBadge, EMPTY_LIST_ACTIONS, EditApiKeyModal, EditCredentialModal, EditWebhookEndpointModal, ElevasisCoreProvider, ElevasisSystemsProvider, ElevasisUIProvider, EmptyVisualizer, ErrorAnalysisCard, ErrorBreakdownTable, ErrorDetailsModal, ErrorReportCard, ExecuteWorkflowModal, ExecutionBreakdownTable, ExecutionErrorSection, ExecutionHealth, ExecutionHealthCard, ExecutionLogsFilters, ExecutionLogsPage, ExecutionLogsTable, ExecutionPanel, ExecutionStats, ExecutionStatusBadge, FilterBar, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, HealthStatusCard, KanbanBoard, LEAD_GEN_ITEMS, LEAD_GEN_ROUTE_LINKS, LeadGenCompaniesPage, LeadGenContactsPage, LeadGenListDetailPage, LeadGenListsPage, LeadGenOverviewPage, LeadGenRouteShell, LeadGenSidebar, LeadGenSidebarMiddle, LeadGenSidebarTop, ListActionsProvider, ListBuilderIndexPage, ListBuilderPage, LogEntry, LogGroup, MdxRenderer, MemberAccessModal, MemberConfigModal, MembershipFeaturePanel, MembershipStatusBadge, MetricsStrip, MilestoneTimeline, MyTasksPanel, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, NoAccessState, NotificationBell, NotificationCenter, NotificationItem, NotificationList, NotificationPanel, NotificationProvider, OAuthConnectModal, OAuthIntegrationsCard, ORGANIZATION_GRAPH_NODE_KIND_LABELS, ORPHAN_STAGE_ORDER, OperationsOverview, OperationsService, OperationsSidebar, OperationsSidebarMiddle, OperationsSidebarTop, OrgMembersList, OrganizationGraphPage, OrganizationMembershipService, OrganizationMembershipsList, OrganizationProvider, OrganizationSettings, OrganizationSwitcher, OrganizationSwitcherConnected, PIPELINE_FUNNEL_ORDER, PermissionMatrix, PipelineFunnelWidget, ProjectDetailPage, ProjectsListPage, ProjectsSidebar, ProjectsSidebarMiddle, ProjectsSidebarTop, QuickCreateActions, RecentExecutionsByResource, RecurringScheduleForm, RelativeScheduleForm, ResourceDefinitionSection, ResourceDetailPage, ResourceErrorState, ResourceFilter, ResourceHeader, ResourceHealthChart, ResourceHealthPanel, ResourceNotFoundState, ResourceOverview, ResourcesPage, ResourcesSidebar, RichTextEditor, RoleBadge, RunResourceButton, RunWorkflowModal, SAVED_VIEW_PRESETS, SavedViewsPanel, ScheduleCard, ScheduleDetailModal, ScheduleTypeSelector, SessionChatArea, SessionChatInterface, SessionChatPage, SessionDetailsSidebar, SessionExecutionLogs, SessionHeader, SessionListItem, SessionMemory, SessionsPage, SessionsSidebar, SortableHeader, StepConfigForm, SystemOpsView, SystemShell, TabSection, TableSelectionToolbar, TaskCard, TaskScheduler, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, ToolsListDisplay, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, UnresolvedErrorsTeaser, UpcomingMilestonesPage, VisualizerContainer, WebhookEndpointList, WebhookEndpointService, WebhookEndpointSettings, WebhookUrlDisplayModal, WorkflowDefinitionDisplay, WorkflowExecutionLogs, WorkflowExecutionPanel, WorkflowExecutionTimeline, ZodFormRenderer, acquisitionListKeys, aggregateSystemMetrics, buildErrorReport, calculateProgress, clientsKeys, collectResourceFilterFacets, companyKeys, contactKeys, createFeatureAccessHook, createOrganizationsSlice, createTestSystemsProvider, createUseOrgInitialization, createUseOrganizations, crmManifest, crmPrioritySettingsKeys, dealKeys, dealNoteKeys, dealTaskKeys, deliveryManifest, deriveBusinessProgress, executionsKeys, filterByDomainFilters, findListActionByAction, formatDate3 as formatDate, formatDealStageLabel, formatResourceAttribution, formatStatusLabel, getEnrichmentColor, getEnrichmentStatus, getExecutionStatusConfig, getGraphBackgroundStyles, getHealthColor, getIcon, getListActionWorkflowId, getLogLevelConfig, getResourceFilterFacetIds, getStateKeyColor, getStatusColor4 as getStatusColor, getStepActionLabel, iconMap, isSessionCapable, labelResourceFilterFacet, leadGenArtifactKeys, leadGenListCompanyKeys, leadGenListMemberKeys, leadGenManifest, mdxComponents, milestoneKeys, milestoneStatusColors, monitoringManifest, noteKeys, noteTypeColors, operationsKeys, operationsManifest, projectActivityKeys, projectKeys, projectStatusColors, requestsKeys, resolveBuildPlanSteps, resolveBuildState, scheduleKeys, sessionsKeys, settingsManifest, showApiErrorNotification, showAuthError, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, sortData, sortStageKeys, taskKeys, taskStatusColors, taskTypeColors, useActivateDeployment, useActivities, useActivitiesRealtime, useActivityFilters, useActivityTrend, useAddCompaniesToList, useAddContactsToList, useArchiveSession, useArchivedLogs, useArtifacts, useAssignRole, useBatchDelete, useBatchTelemetry, useBatchedResourcesHealth, useBreadcrumbs, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCheckpointTasks, useClient, useClientStatus, useClients, useCommandQueue, useCommandQueueTotals, useCommandViewData, useCommandViewDomainFilters, useCommandViewStats, useCommandViewStore, useCompanies, useCompany, useCompanyFacets, useCompleteDealTask, useContact, useContacts, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateApiKey, useCreateArtifact, useCreateClient, useCreateCompany, useCreateContact, useCreateCredential, useCreateDealNote, useCreateDealTask, useCreateList, useCreateMilestone, useCreateNote, useCreateOrgRole, useCreateProject, useCreateSchedule, useCreateSession, useCreateTask, useCreateWebhookEndpoint, useCredentials, useCrmActions, useCrmPipelineSummary, useCrmPrioritySettings, useCrmQuickMetrics, useDashboardMetrics, useDeactivateDeployment, useDeactivateMembership, useDealDetail, useDealNotes, useDealTasks, useDealTasksDue, useDeals, useDealsLookup, useDealsSummary, useDeleteApiKey, useDeleteClient, useDeleteCompanies, useDeleteContacts, useDeleteCredential, useDeleteDeal, useDeleteDeployment, useDeleteExecution, useDeleteList, useDeleteLists, useDeleteMilestone, useDeleteOrgRole, useDeleteProject, useDeleteRequest, useDeleteSchedule, useDeleteSession, useDeleteTask, useDeleteTask2, useDeleteWebhookEndpoint, useDeriveActions, useEffectivePermissions, useElevasisSystems, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useExecuteAction, useExecuteAsync, useExecuteResource, useExecution, useExecutionHealth, useExecutionLogSSE, useExecutionLogs, useExecutionLogsFilters, useExecutionPanelState, useExecutionSSE, useExecutions, useGetExecutionHistory, useGetSchedule, useGraphBackgroundStyles, useGraphTheme, useHasPermission, useInFlightExecutions, useList, useListActions, useListApiKeys, useListDeployments, useListExecutions, useListMember, useListMembers, useListProgress, useListRecords, useListSchedules, useListWebhookEndpoints, useLists, useListsTelemetry, useMarkAllAsRead, useMarkAsRead, useMilestones, useNewKnowledgeMapLayout, useNotificationAdapter, useNotificationCount, useNotifications, useOptionalElevasisSystems, useOrgRoles, useOrganizationMembers, useOrganizationPermissions, usePaginationState, usePatchTask, usePauseSchedule, usePermissionCatalog, useProject, useProjectActivities, useProjectMilestones, useProjectNotes, useProjectRealtime, useProjectTasks, useProjects, useReactivateMembership, useRecentCrmActivity, useRecentExecutionsByResource, useRemoveCompaniesFromList, useRequest, useRequestsList, useResetCrmPrioritySettings, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResolvedOrganizationModel, useResourceDefinition, useResourceErrors, useResourceExecutions, useResourceSearch, useResources, useResourcesDomainFilters, useResourcesHealth, useResumeSchedule, useRetryExecution, useRevokeRole, useSSEConnection, useScheduledTasks, useSession, useSessionExecution, useSessionExecutions, useSessionMessages, useSessionWebSocket, useSessions, useSortedData, useStatusFilter, useSubmitAction, useSuccessNotification, useSystemHealth, useTableSelection, useTableSort, useTasks, useTestNotification, useTimeRangeDates, useTopFailingResources, useTransitionItem, useTransitionListCompany, useTransitionListMember, useTransitionState, useUnresolveError, useUnresolvedErrors, useUpdateAnchor, useUpdateApiKey, useUpdateClient, useUpdateCompany, useUpdateContact, useUpdateCredential, useUpdateCrmPrioritySettings, useUpdateList, useUpdateListConfig, useUpdateListStatus, useUpdateMemberConfig, useUpdateMilestone, useUpdateOrgRole, useUpdateProject, useUpdateRequestStatus, useUpdateSchedule, useUpdateTask, useUpdateWebhookEndpoint, useUserMemberships, useVerifyCredential, useVisibleResources, useWarningNotification, useWorkflowExecution };
|
|
41101
|
+
export { AbsoluteScheduleForm, AccountSettings, ActionModal, ActivityCard, ActivityFeed, ActivityFeedWidget, ActivityFilters, ActivityLog, ActivityTable, AgentDefinitionDisplay, AgentExecutionLogs, AgentExecutionPanel, AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, AgentSessionGroup, AllTasksPage, ApiKeyDisplayModal, ApiKeyList, ApiKeyService, ApiKeySettings, AppErrorBoundary, AppearanceSettings, BaseEdge, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates, BaseNode, Breadcrumbs, BusinessImpactCard, CRM_ITEMS, Can, Checklist, CheckpointGroup, CollapsibleJsonSection, CommandQueueDetailPage, CommandQueuePage, CommandQueueShell, CommandQueueSidebar, CommandQueueSidebarMiddle, CommandQueueSidebarTop, CommandQueueTaskRow, CommandViewPage, CompanyDetailPage, ConfigCard, ConfirmationInputModal, ConfirmationModal, ContactDetailPage, ContentSections, ContextUsageBadge, ContractDisplay, ConversationThread, CostAnalytics, CostBreakdownCard, CostByModelTable, CostMetricsCard, CrashErrorFallback, CreateApiKeyModal, CreateCredentialModal, CreateDeliveryEntityModal, CreateRoleModal, CreateScheduleModal, CreateWebhookEndpointModal, CredentialList, CredentialService, CredentialSettings, CrmActionsProvider, CrmOverview, CrmSettingsPage, CrmSidebar, CrmSidebarMiddle, CrmSidebarTop, CustomModal, DEAL_STAGES, DEAL_STAGE_COLORS, DEAL_STAGE_OPTIONS, DEFAULT_KANBAN_CONFIG, DELIVERY_COMMUNICATION_ITEMS, DELIVERY_PROJECT_ITEMS, DELIVERY_WORK_ITEMS, Dashboard, DashboardOperationsOverview, DealDetailPage, DealKanbanCard, DealsListPage, DeleteScheduleModal, DeploymentDetailModal, DeploymentList, DeploymentService, DeploymentSettings, DeploymentStatusBadge, EMPTY_LIST_ACTIONS, EditApiKeyModal, EditCredentialModal, EditWebhookEndpointModal, ElevasisCoreProvider, ElevasisSystemsProvider, ElevasisUIProvider, EmptyVisualizer, ErrorAnalysisCard, ErrorBreakdownTable, ErrorDetailsModal, ErrorReportCard, ExecuteWorkflowModal, ExecutionBreakdownTable, ExecutionErrorSection, ExecutionHealth, ExecutionHealthCard, ExecutionLogsFilters, ExecutionLogsPage, ExecutionLogsTable, ExecutionPanel, ExecutionStats, ExecutionStatusBadge, FilterBar, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, HealthStatusCard, KanbanBoard, LEAD_GEN_ITEMS, LEAD_GEN_ROUTE_LINKS, LeadGenCompaniesPage, LeadGenContactsPage, LeadGenListDetailPage, LeadGenListsPage, LeadGenOverviewPage, LeadGenRouteShell, LeadGenSidebar, LeadGenSidebarMiddle, LeadGenSidebarTop, ListActionsProvider, ListBuilderIndexPage, ListBuilderPage, LogEntry, LogGroup, MdxRenderer, MemberAccessModal, MemberConfigModal, MembershipFeaturePanel, MembershipStatusBadge, MetricsStrip, MilestoneTimeline, MyTasksPanel, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, NoAccessState, NotificationBell, NotificationCenter, NotificationItem, NotificationList, NotificationPanel, NotificationProvider, OAuthConnectModal, OAuthIntegrationsCard, ORGANIZATION_GRAPH_NODE_KIND_LABELS, ORPHAN_STAGE_ORDER, OperationsOverview, OperationsService, OperationsSidebar, OperationsSidebarMiddle, OperationsSidebarTop, OrgMembersList, OrganizationGraphPage, OrganizationMembershipService, OrganizationMembershipsList, OrganizationProvider, OrganizationSettings, OrganizationSwitcher, OrganizationSwitcherConnected, PIPELINE_FUNNEL_ORDER, PermissionMatrix, PipelineFunnelWidget, ProjectDetailPage, ProjectsListPage, ProjectsSidebar, ProjectsSidebarMiddle, ProjectsSidebarTop, QuickCreateActions, RecentExecutionsByResource, RecurringScheduleForm, RelativeScheduleForm, ResourceDefinitionSection, ResourceDetailPage, ResourceErrorState, ResourceFilter, ResourceHeader, ResourceHealthChart, ResourceHealthPanel, ResourceNotFoundState, ResourceOverview, ResourcesPage, ResourcesSidebar, RichTextEditor, RoleBadge, RunResourceButton, SAVED_VIEW_PRESETS, SavedViewsPanel, ScheduleCard, ScheduleDetailModal, ScheduleTypeSelector, SessionChatArea, SessionChatInterface, SessionChatPage, SessionDetailsSidebar, SessionExecutionLogs, SessionHeader, SessionListItem, SessionMemory, SessionsPage, SessionsSidebar, SortableHeader, StepConfigForm, SystemOpsView, SystemShell, TabSection, TableSelectionToolbar, TaskCard, TaskScheduler, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, ToolsListDisplay, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, UnresolvedErrorsTeaser, UpcomingMilestonesPage, VisualizerContainer, WebhookEndpointList, WebhookEndpointService, WebhookEndpointSettings, WebhookUrlDisplayModal, WorkflowDefinitionDisplay, WorkflowExecutionLogs, WorkflowExecutionPanel, WorkflowExecutionTimeline, ZodFormRenderer, acquisitionListKeys, aggregateSystemMetrics, buildErrorReport, calculateProgress, clientsKeys, collectResourceFilterFacets, companyKeys, contactKeys, createFeatureAccessHook, createOrganizationsSlice, createTestSystemsProvider, createUseOrgInitialization, createUseOrganizations, crmManifest, crmPrioritySettingsKeys, dealKeys, dealNoteKeys, dealTaskKeys, deliveryManifest, deriveBusinessProgress, executionsKeys, filterByDomainFilters, findListActionByAction, formatDate3 as formatDate, formatDealStageLabel, formatResourceAttribution, formatStatusLabel, getEnrichmentColor, getEnrichmentStatus, getExecutionStatusConfig, getGraphBackgroundStyles, getHealthColor, getIcon, getListActionWorkflowId, getLogLevelConfig, getResourceFilterFacetIds, getStateKeyColor, getStatusColor4 as getStatusColor, getStepActionLabel, iconMap, isSessionCapable, labelResourceFilterFacet, leadGenArtifactKeys, leadGenListCompanyKeys, leadGenListMemberKeys, leadGenManifest, mdxComponents, milestoneKeys, milestoneStatusColors, monitoringManifest, noteKeys, noteTypeColors, operationsKeys, operationsManifest, projectActivityKeys, projectKeys, projectStatusColors, requestsKeys, resolveBuildPlanSteps, resolveBuildState, scheduleKeys, sessionsKeys, settingsManifest, showApiErrorNotification, showAuthError, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, sortData, sortStageKeys, taskKeys, taskStatusColors, taskTypeColors, useActivateDeployment, useActivities, useActivitiesRealtime, useActivityFilters, useActivityTrend, useAddCompaniesToList, useAddContactsToList, useArchiveSession, useArchivedLogs, useArtifacts, useAssignRole, useBatchDelete, useBatchTelemetry, useBatchedResourcesHealth, useBreadcrumbs, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCheckpointTasks, useClient, useClientStatus, useClients, useCommandQueue, useCommandQueueTotals, useCommandViewData, useCommandViewDomainFilters, useCommandViewStats, useCommandViewStore, useCompanies, useCompany, useCompanyFacets, useCompleteDealTask, useContact, useContacts, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateApiKey, useCreateArtifact, useCreateClient, useCreateCompany, useCreateContact, useCreateCredential, useCreateDealNote, useCreateDealTask, useCreateList, useCreateMilestone, useCreateNote, useCreateOrgRole, useCreateProject, useCreateSchedule, useCreateSession, useCreateTask, useCreateWebhookEndpoint, useCredentials, useCrmActions, useCrmPipelineSummary, useCrmPrioritySettings, useCrmQuickMetrics, useDashboardMetrics, useDeactivateDeployment, useDeactivateMembership, useDealDetail, useDealNotes, useDealTasks, useDealTasksDue, useDeals, useDealsLookup, useDealsSummary, useDeleteApiKey, useDeleteClient, useDeleteCompanies, useDeleteContacts, useDeleteCredential, useDeleteDeal, useDeleteDeployment, useDeleteExecution, useDeleteList, useDeleteLists, useDeleteMilestone, useDeleteOrgRole, useDeleteProject, useDeleteRequest, useDeleteSchedule, useDeleteSession, useDeleteTask, useDeleteTask2, useDeleteWebhookEndpoint, useDeriveActions, useEffectivePermissions, useElevasisSystems, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useExecuteAction, useExecuteAsync, useExecuteResource, useExecution, useExecutionHealth, useExecutionLogSSE, useExecutionLogs, useExecutionLogsFilters, useExecutionPanelState, useExecutionSSE, useExecutions, useGetExecutionHistory, useGetSchedule, useGraphBackgroundStyles, useGraphTheme, useHasPermission, useInFlightExecutions, useLeadGenConfig, useList, useListActions, useListApiKeys, useListDeployments, useListExecutions, useListMember, useListMembers, useListProgress, useListRecords, useListSchedules, useListWebhookEndpoints, useLists, useListsTelemetry, useMarkAllAsRead, useMarkAsRead, useMilestones, useNewKnowledgeMapLayout, useNotificationAdapter, useNotificationCount, useNotifications, useOptionalElevasisSystems, useOrgRoles, useOrganizationMembers, useOrganizationPermissions, usePaginationState, usePatchTask, usePauseSchedule, usePermissionCatalog, useProject, useProjectActivities, useProjectMilestones, useProjectNotes, useProjectRealtime, useProjectTasks, useProjects, useReactivateMembership, useRecentCrmActivity, useRecentExecutionsByResource, useRemoveCompaniesFromList, useRequest, useRequestsList, useResetCrmPrioritySettings, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResolvedOrganizationModel, useResourceDefinition, useResourceErrors, useResourceExecutions, useResourceSearch, useResources, useResourcesDomainFilters, useResourcesHealth, useResumeSchedule, useRetryExecution, useRevokeRole, useSSEConnection, useScheduledTasks, useSession, useSessionExecution, useSessionExecutions, useSessionMessages, useSessionWebSocket, useSessions, useSortedData, useStatusFilter, useSubmitAction, useSuccessNotification, useSystemHealth, useTableSelection, useTableSort, useTasks, useTestNotification, useTimeRangeDates, useTopFailingResources, useTransitionItem, useTransitionListCompany, useTransitionListMember, useTransitionState, useUnresolveError, useUnresolvedErrors, useUpdateAnchor, useUpdateApiKey, useUpdateClient, useUpdateCompany, useUpdateContact, useUpdateCredential, useUpdateCrmPrioritySettings, useUpdateList, useUpdateListConfig, useUpdateListStatus, useUpdateMemberConfig, useUpdateMilestone, useUpdateOrgRole, useUpdateProject, useUpdateRequestStatus, useUpdateSchedule, useUpdateTask, useUpdateWebhookEndpoint, useUserMemberships, useVerifyCredential, useVisibleResources, useWarningNotification, useWorkflowExecution };
|