@elevasis/ui 2.25.6 → 2.26.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/api/index.js +2 -2
- package/dist/app/index.css +15 -5
- package/dist/app/index.d.ts +61 -14
- package/dist/app/index.js +6 -6
- package/dist/charts/index.js +6 -5
- package/dist/chunk-3MEXPLWT.js +265 -0
- package/dist/{chunk-BDKM56TP.js → chunk-4KTLOK7K.js} +1 -1
- package/dist/{chunk-KMAXFJPH.js → chunk-CW3UNAF2.js} +5 -409
- package/dist/{chunk-HKBEURCV.js → chunk-G26INIF3.js} +1 -1
- package/dist/{chunk-7F3IQMLI.js → chunk-G66QFZXD.js} +11 -214
- package/dist/{chunk-QIW6OCEI.js → chunk-HLFFKKT3.js} +27 -373
- package/dist/chunk-JDNEWB5F.js +10 -0
- package/dist/{chunk-L7D6KNHV.js → chunk-JKBGDFX2.js} +890 -749
- package/dist/{chunk-YRKQNPK2.js → chunk-JPGX3533.js} +4 -3
- package/dist/chunk-KCGGA36K.js +73 -0
- package/dist/chunk-KEFWANZY.js +155 -0
- package/dist/chunk-LH4GPYDX.js +448 -0
- package/dist/{chunk-JXSBOG2R.js → chunk-LWKZ3BCC.js} +5 -4
- package/dist/chunk-OGXKOMUT.js +412 -0
- package/dist/chunk-OHXU5WWK.js +3731 -0
- package/dist/chunk-ONFKASZI.js +2004 -0
- package/dist/{chunk-U36X6NZM.js → chunk-RIFTUOPE.js} +2 -14
- package/dist/{chunk-T6INEVX6.js → chunk-SGS4CQ2B.js} +1 -1
- package/dist/{chunk-C7IBFI5B.js → chunk-UPMX5GJI.js} +5 -5
- package/dist/{chunk-ARJPZ66V.js → chunk-UY5I2KOZ.js} +208 -3124
- package/dist/chunk-W2ZTLH7Y.js +662 -0
- package/dist/{chunk-KNISO652.js → chunk-WUVR4QY6.js} +9 -9
- package/dist/{chunk-Q5BEODAT.js → chunk-X2SUMO3P.js} +2 -1
- package/dist/{chunk-SNHGSCKH.js → chunk-XBMCDGHA.js} +1 -1
- package/dist/{chunk-N55DVMAG.js → chunk-XQQEKWTL.js} +2 -6
- package/dist/{chunk-SBQ4MYQV.js → chunk-XZSEPJZQ.js} +5 -6
- package/dist/{chunk-CPAJXBTL.js → chunk-YHBPR67D.js} +490 -676
- package/dist/{chunk-QARSVM7Q.js → chunk-YO2YORW4.js} +4 -4
- package/dist/{chunk-TAIX4NO3.js → chunk-ZFLM2YVW.js} +2 -2
- package/dist/components/index.css +15 -5
- package/dist/components/index.d.ts +202 -383
- package/dist/components/index.js +43 -429
- package/dist/components/navigation/index.css +25 -15
- package/dist/execution/index.d.ts +0 -73
- package/dist/features/auth/index.css +25 -15
- package/dist/features/crm/index.css +25 -15
- package/dist/features/crm/index.d.ts +49 -49
- package/dist/features/crm/index.js +14 -15
- package/dist/features/dashboard/index.css +25 -15
- package/dist/features/dashboard/index.js +18 -16
- package/dist/features/delivery/index.css +15 -5
- package/dist/features/delivery/index.js +14 -15
- package/dist/features/knowledge/index.css +611 -0
- package/dist/features/knowledge/index.js +375 -72
- package/dist/features/lead-gen/index.css +25 -15
- package/dist/features/lead-gen/index.d.ts +60 -21
- package/dist/features/lead-gen/index.js +16 -16
- package/dist/features/monitoring/index.css +15 -5
- package/dist/features/monitoring/index.js +17 -17
- package/dist/features/monitoring/requests/index.css +25 -15
- package/dist/features/monitoring/requests/index.js +13 -14
- package/dist/features/operations/index.css +25 -15
- package/dist/features/operations/index.d.ts +16 -98
- package/dist/features/operations/index.js +26 -22
- package/dist/features/settings/index.css +25 -15
- package/dist/features/settings/index.d.ts +1 -0
- package/dist/features/settings/index.js +15 -16
- package/dist/hooks/delivery/index.css +25 -15
- package/dist/hooks/delivery/index.js +2 -2
- package/dist/hooks/index.css +15 -5
- package/dist/hooks/index.d.ts +172 -380
- package/dist/hooks/index.js +13 -14
- package/dist/hooks/published.css +15 -5
- package/dist/hooks/published.d.ts +172 -380
- package/dist/hooks/published.js +13 -14
- package/dist/index.css +15 -5
- package/dist/index.d.ts +988 -403
- package/dist/index.js +15 -15
- package/dist/initialization/index.d.ts +1 -0
- package/dist/knowledge/index.d.ts +981 -41
- package/dist/knowledge/index.js +5449 -294
- package/dist/layout/index.d.ts +2 -0
- package/dist/layout/index.js +3 -2
- package/dist/organization/index.css +25 -15
- package/dist/organization/index.d.ts +1 -0
- package/dist/provider/index.css +25 -15
- package/dist/provider/index.d.ts +818 -26
- package/dist/provider/index.js +11 -11
- package/dist/provider/published.css +25 -15
- package/dist/provider/published.d.ts +817 -25
- package/dist/provider/published.js +8 -9
- package/dist/test-utils/index.js +2 -2
- package/dist/test-utils/setup.js +1 -1
- package/dist/theme/index.js +3 -2
- package/dist/theme/presets/index.d.ts +97 -0
- package/dist/theme/presets/index.js +3 -0
- package/dist/types/index.d.ts +71 -126
- package/dist/utils/index.js +1 -1
- package/dist/vite/index.d.ts +7 -0
- package/dist/vite/index.js +10 -0
- package/dist/vite-plugin-knowledge/index.d.ts +1 -33
- package/dist/vite-plugin-knowledge/index.js +1 -66
- package/package.json +16 -3
- package/src/knowledge/README.md +8 -8
- package/src/theme/presets/README.md +19 -0
- package/dist/chunk-5RLYII6P.js +0 -314
- package/dist/chunk-6U7AIIHF.js +0 -880
- package/dist/chunk-HAEJ4M54.js +0 -94
- package/dist/chunk-LPM7O6XM.js +0 -293
- /package/dist/{chunk-SGXXJE52.js → chunk-QD4X4H5A.js} +0 -0
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from './chunk-
|
|
1
|
+
import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from './chunk-4KTLOK7K.js';
|
|
2
|
+
import { sanitizeInput } from './chunk-3MEXPLWT.js';
|
|
2
3
|
import { PageContainer } from './chunk-BZZCNLT6.js';
|
|
3
4
|
import { TableSelectionToolbar, SortableHeader } from './chunk-TUMSNGTX.js';
|
|
4
5
|
import { SubshellNavItem } from './chunk-X4WBGKJQ.js';
|
|
5
6
|
import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
|
|
6
7
|
import { FilterBar } from './chunk-PDHTXPSF.js';
|
|
7
8
|
import { CustomModal } from './chunk-KVJ3LFH2.js';
|
|
8
|
-
import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useWorkflowExecution, useList, useListProgress, useListExecutions, useDeleteList,
|
|
9
|
-
import { showApiErrorNotification, showSuccessNotification } from './chunk-
|
|
9
|
+
import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useWorkflowExecution, useList, useListProgress, useListExecutions, useDeleteList, useCompanyFacets, useCompanies, useDeleteCompanies, useContacts, useDeleteContacts, useListMembers, useListMember, useTransitionListMember, useDeriveActions, useArtifacts } from './chunk-YHBPR67D.js';
|
|
10
|
+
import { showApiErrorNotification, showSuccessNotification } from './chunk-G26INIF3.js';
|
|
11
|
+
import { PageTitleCaption, CenteredErrorState, StatCard, CardHeader, EmptyState, JsonViewer } from './chunk-RIFTUOPE.js';
|
|
12
|
+
import { useListActions, LEAD_GEN_STAGE_CATALOG, LEAD_GEN_PIPELINE_DEFINITIONS, findPipeline } from './chunk-W2ZTLH7Y.js';
|
|
10
13
|
import { SubshellContentContainer } from './chunk-TKAYX2SP.js';
|
|
11
|
-
import { PageTitleCaption, CenteredErrorState, StatCard, CardHeader, EmptyState, JsonViewer } from './chunk-U36X6NZM.js';
|
|
12
|
-
import { useListActions } from './chunk-LPM7O6XM.js';
|
|
13
|
-
import { LEAD_GEN_STAGE_CATALOG, LEAD_GEN_PIPELINE_DEFINITIONS, findPipeline } from './chunk-5RLYII6P.js';
|
|
14
14
|
import { useRouterContext } from './chunk-Q7DJKLEN.js';
|
|
15
15
|
import { useElevasisServices } from './chunk-5WWZXCS5.js';
|
|
16
|
-
import { Stack, Group, Title, Text, Paper, Anchor, ActionIcon, Divider, Box, SimpleGrid, Badge, Card, Center, Loader,
|
|
17
|
-
import { IconLayoutGrid, IconList, IconBuilding, IconAddressBook, IconTarget, IconExternalLink, IconX, IconAlertCircle, IconPlayerPlay, IconArrowRight, IconSparkles, IconListDetails, IconPlus, IconSearch, IconAlertTriangle, IconLayoutDashboard, IconBolt, IconCopy, IconUsers,
|
|
16
|
+
import { Stack, Group, Title, Text, Alert, Button, Collapse, Paper, Anchor, ActionIcon, Divider, Box, SimpleGrid, Badge, Card, Center, Loader, Table, TextInput, Select, Checkbox, Pagination, Textarea, Tooltip, Tabs, ThemeIcon, Pill, SegmentedControl, UnstyledButton, Drawer, JsonInput, Switch, NumberInput, MultiSelect, TagsInput, ScrollArea } from '@mantine/core';
|
|
17
|
+
import { IconLayoutGrid, IconList, IconBuilding, IconAddressBook, IconTarget, IconExternalLink, IconX, IconAlertCircle, IconPlayerPlay, IconArrowRight, IconSparkles, IconListDetails, IconPlus, IconSearch, IconAlertTriangle, IconLayoutDashboard, IconBolt, IconCopy, IconUsers, IconTrash, IconBuildingFactory2, IconArrowLeft, IconChevronDown, IconChevronRight, IconRefresh, IconMail, IconUser, IconDatabase } from '@tabler/icons-react';
|
|
18
18
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
19
19
|
import { Link, useNavigate, useSearch } from '@tanstack/react-router';
|
|
20
|
-
import {
|
|
21
|
-
import { useState, useMemo, useEffect, Fragment as Fragment$1 } from 'react';
|
|
20
|
+
import { useState, useRef, useMemo, useEffect, Fragment as Fragment$1 } from 'react';
|
|
22
21
|
import { useForm } from '@mantine/form';
|
|
22
|
+
import { zod4Resolver } from 'mantine-form-zod-resolver';
|
|
23
|
+
import { useQueryClient, useMutation } from '@tanstack/react-query';
|
|
23
24
|
|
|
24
25
|
var LeadGenSidebarTop = () => {
|
|
25
26
|
return /* @__PURE__ */ jsx(SubshellSidebarSection, { icon: IconTarget, label: "Lead Gen" });
|
|
@@ -110,6 +111,283 @@ function TabSection({ icon, title, description, rightSection, children }) {
|
|
|
110
111
|
children
|
|
111
112
|
] });
|
|
112
113
|
}
|
|
114
|
+
function renderField(field, form, disabled, jsonState, setJsonState) {
|
|
115
|
+
const inputProps = form.getInputProps(field.path);
|
|
116
|
+
const label = field.label;
|
|
117
|
+
const description = field.description;
|
|
118
|
+
const placeholder = field.placeholder;
|
|
119
|
+
switch (field.component) {
|
|
120
|
+
case "segmented": {
|
|
121
|
+
const options = field.options ?? [];
|
|
122
|
+
return /* @__PURE__ */ jsx(
|
|
123
|
+
SegmentedControl,
|
|
124
|
+
{
|
|
125
|
+
fullWidth: true,
|
|
126
|
+
disabled,
|
|
127
|
+
data: options,
|
|
128
|
+
value: inputProps.value ?? options[0]?.value ?? "",
|
|
129
|
+
onChange: (val) => {
|
|
130
|
+
form.setFieldValue(field.path, val);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
field.path
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
case "tags":
|
|
137
|
+
return /* @__PURE__ */ jsx(
|
|
138
|
+
TagsInput,
|
|
139
|
+
{
|
|
140
|
+
label,
|
|
141
|
+
description,
|
|
142
|
+
placeholder,
|
|
143
|
+
disabled,
|
|
144
|
+
value: inputProps.value ?? [],
|
|
145
|
+
onChange: (val) => form.setFieldValue(field.path, val),
|
|
146
|
+
error: inputProps.error,
|
|
147
|
+
clearable: true
|
|
148
|
+
},
|
|
149
|
+
field.path
|
|
150
|
+
);
|
|
151
|
+
case "multiselect":
|
|
152
|
+
return /* @__PURE__ */ jsx(
|
|
153
|
+
MultiSelect,
|
|
154
|
+
{
|
|
155
|
+
label,
|
|
156
|
+
description,
|
|
157
|
+
placeholder,
|
|
158
|
+
disabled,
|
|
159
|
+
data: field.options ?? [],
|
|
160
|
+
value: inputProps.value ?? [],
|
|
161
|
+
onChange: (val) => form.setFieldValue(field.path, val),
|
|
162
|
+
error: inputProps.error,
|
|
163
|
+
clearable: true
|
|
164
|
+
},
|
|
165
|
+
field.path
|
|
166
|
+
);
|
|
167
|
+
case "select":
|
|
168
|
+
return /* @__PURE__ */ jsx(
|
|
169
|
+
Select,
|
|
170
|
+
{
|
|
171
|
+
label,
|
|
172
|
+
description,
|
|
173
|
+
placeholder,
|
|
174
|
+
disabled,
|
|
175
|
+
data: field.options ?? [],
|
|
176
|
+
...inputProps
|
|
177
|
+
},
|
|
178
|
+
field.path
|
|
179
|
+
);
|
|
180
|
+
case "textinput":
|
|
181
|
+
return /* @__PURE__ */ jsx(
|
|
182
|
+
TextInput,
|
|
183
|
+
{
|
|
184
|
+
label,
|
|
185
|
+
description,
|
|
186
|
+
placeholder,
|
|
187
|
+
disabled,
|
|
188
|
+
...inputProps
|
|
189
|
+
},
|
|
190
|
+
field.path
|
|
191
|
+
);
|
|
192
|
+
case "textarea":
|
|
193
|
+
return /* @__PURE__ */ jsx(
|
|
194
|
+
Textarea,
|
|
195
|
+
{
|
|
196
|
+
label,
|
|
197
|
+
description,
|
|
198
|
+
placeholder,
|
|
199
|
+
disabled,
|
|
200
|
+
autosize: true,
|
|
201
|
+
minRows: 3,
|
|
202
|
+
...inputProps
|
|
203
|
+
},
|
|
204
|
+
field.path
|
|
205
|
+
);
|
|
206
|
+
case "numberinput":
|
|
207
|
+
return /* @__PURE__ */ jsx(
|
|
208
|
+
NumberInput,
|
|
209
|
+
{
|
|
210
|
+
label,
|
|
211
|
+
description,
|
|
212
|
+
placeholder,
|
|
213
|
+
disabled,
|
|
214
|
+
min: field.min,
|
|
215
|
+
max: field.max,
|
|
216
|
+
step: field.step,
|
|
217
|
+
allowDecimal: false,
|
|
218
|
+
value: inputProps.value ?? 0,
|
|
219
|
+
onChange: (val) => form.setFieldValue(field.path, typeof val === "number" ? val : 0),
|
|
220
|
+
error: inputProps.error
|
|
221
|
+
},
|
|
222
|
+
field.path
|
|
223
|
+
);
|
|
224
|
+
case "switch":
|
|
225
|
+
return /* @__PURE__ */ jsx(
|
|
226
|
+
Switch,
|
|
227
|
+
{
|
|
228
|
+
label,
|
|
229
|
+
description,
|
|
230
|
+
disabled,
|
|
231
|
+
checked: inputProps.value ?? false,
|
|
232
|
+
onChange: (e) => form.setFieldValue(field.path, e.currentTarget.checked),
|
|
233
|
+
error: inputProps.error
|
|
234
|
+
},
|
|
235
|
+
field.path
|
|
236
|
+
);
|
|
237
|
+
case "json": {
|
|
238
|
+
const path = field.path;
|
|
239
|
+
const state = jsonState[path];
|
|
240
|
+
const rawValue = state?.raw ?? (() => {
|
|
241
|
+
const current = inputProps.value;
|
|
242
|
+
if (current === void 0 || current === null) return "";
|
|
243
|
+
if (typeof current === "string") return current;
|
|
244
|
+
try {
|
|
245
|
+
return JSON.stringify(current, null, 2);
|
|
246
|
+
} catch {
|
|
247
|
+
return "";
|
|
248
|
+
}
|
|
249
|
+
})();
|
|
250
|
+
return /* @__PURE__ */ jsx(
|
|
251
|
+
JsonInput,
|
|
252
|
+
{
|
|
253
|
+
label,
|
|
254
|
+
description,
|
|
255
|
+
placeholder,
|
|
256
|
+
disabled,
|
|
257
|
+
value: rawValue,
|
|
258
|
+
onChange: (next) => {
|
|
259
|
+
if (!next.trim()) {
|
|
260
|
+
setJsonState(path, { raw: next, invalid: false });
|
|
261
|
+
form.setFieldValue(path, void 0);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
const parsed = JSON.parse(next);
|
|
266
|
+
setJsonState(path, { raw: next, invalid: false });
|
|
267
|
+
form.setFieldValue(path, parsed);
|
|
268
|
+
} catch {
|
|
269
|
+
setJsonState(path, { raw: next, invalid: true });
|
|
270
|
+
form.setFieldError(path, "Invalid JSON");
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
error: state?.invalid ? "Invalid JSON" : inputProps.error,
|
|
274
|
+
autosize: true,
|
|
275
|
+
minRows: 3,
|
|
276
|
+
formatOnBlur: true
|
|
277
|
+
},
|
|
278
|
+
path
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
default:
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function renderSection(section, values, form, disabled, jsonState, setJsonState) {
|
|
286
|
+
if (section.when && !section.when(values)) return null;
|
|
287
|
+
const visibleFields = section.fields.filter((f) => !f.when || f.when(values));
|
|
288
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
289
|
+
section.title && /* @__PURE__ */ jsxs(Box, { children: [
|
|
290
|
+
/* @__PURE__ */ jsx(Title, { order: 5, children: section.title }),
|
|
291
|
+
section.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: section.description })
|
|
292
|
+
] }),
|
|
293
|
+
visibleFields.map((field) => renderField(field, form, disabled, jsonState, setJsonState))
|
|
294
|
+
] }, section.id);
|
|
295
|
+
}
|
|
296
|
+
function StepConfigForm({
|
|
297
|
+
schema,
|
|
298
|
+
layout,
|
|
299
|
+
value,
|
|
300
|
+
onChange,
|
|
301
|
+
onAction,
|
|
302
|
+
actions,
|
|
303
|
+
disabled = false,
|
|
304
|
+
slot = "all"
|
|
305
|
+
}) {
|
|
306
|
+
const initialValues = sanitizeInput(schema, value);
|
|
307
|
+
const [validationError, setValidationError] = useState(null);
|
|
308
|
+
const [advancedOpen, setAdvancedOpen] = useState(false);
|
|
309
|
+
const [jsonState, setJsonStateMap] = useState({});
|
|
310
|
+
const validationErrorRef = useRef(null);
|
|
311
|
+
const setJsonState = (path, next) => {
|
|
312
|
+
setJsonStateMap((prev) => ({ ...prev, [path]: next }));
|
|
313
|
+
};
|
|
314
|
+
const form = useForm({
|
|
315
|
+
initialValues,
|
|
316
|
+
validate: zod4Resolver(schema),
|
|
317
|
+
// onValuesChange fires synchronously after each field update — no setTimeout needed.
|
|
318
|
+
onValuesChange: (values2) => {
|
|
319
|
+
if (validationErrorRef.current) {
|
|
320
|
+
validationErrorRef.current = null;
|
|
321
|
+
setValidationError(null);
|
|
322
|
+
}
|
|
323
|
+
onChange(values2);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
const handleActionClick = (action) => {
|
|
327
|
+
const parsed = schema.safeParse(form.values);
|
|
328
|
+
if (!parsed.success) {
|
|
329
|
+
const firstIssue = parsed.error.issues[0];
|
|
330
|
+
const fieldErrors = {};
|
|
331
|
+
for (const issue of parsed.error.issues) {
|
|
332
|
+
const path = issue.path.join(".");
|
|
333
|
+
if (path && !fieldErrors[path]) {
|
|
334
|
+
fieldErrors[path] = issue.message;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
form.setErrors(fieldErrors);
|
|
338
|
+
const msg = firstIssue?.message ?? "Validation failed";
|
|
339
|
+
validationErrorRef.current = msg;
|
|
340
|
+
setValidationError(msg);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
validationErrorRef.current = null;
|
|
344
|
+
setValidationError(null);
|
|
345
|
+
void onAction?.(action, parsed.data);
|
|
346
|
+
};
|
|
347
|
+
const values = form.values;
|
|
348
|
+
if (slot === "advanced") {
|
|
349
|
+
return /* @__PURE__ */ jsx(Stack, { gap: "md", children: layout.advanced ? renderSection(layout.advanced, values, form, disabled, jsonState, setJsonState) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No advanced settings for this step." }) });
|
|
350
|
+
}
|
|
351
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
352
|
+
slot === "all" && validationError && /* @__PURE__ */ jsx(
|
|
353
|
+
Alert,
|
|
354
|
+
{
|
|
355
|
+
color: "red",
|
|
356
|
+
onClose: () => {
|
|
357
|
+
validationErrorRef.current = null;
|
|
358
|
+
setValidationError(null);
|
|
359
|
+
},
|
|
360
|
+
withCloseButton: true,
|
|
361
|
+
children: validationError
|
|
362
|
+
}
|
|
363
|
+
),
|
|
364
|
+
layout.sections.map((section) => renderSection(section, values, form, disabled, jsonState, setJsonState)),
|
|
365
|
+
slot === "all" && layout.advanced && /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
366
|
+
/* @__PURE__ */ jsx(
|
|
367
|
+
Button,
|
|
368
|
+
{
|
|
369
|
+
variant: "subtle",
|
|
370
|
+
size: "xs",
|
|
371
|
+
onClick: () => setAdvancedOpen((o) => !o),
|
|
372
|
+
style: { alignSelf: "flex-start" },
|
|
373
|
+
children: advancedOpen ? "Hide advanced" : "Show advanced"
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ jsx(Collapse, { in: advancedOpen, children: renderSection(layout.advanced, values, form, disabled, jsonState, setJsonState) })
|
|
377
|
+
] }),
|
|
378
|
+
slot === "all" && actions && actions.length > 0 && /* @__PURE__ */ jsx(Group, { gap: "sm", children: actions.map((action) => /* @__PURE__ */ jsx(
|
|
379
|
+
Button,
|
|
380
|
+
{
|
|
381
|
+
variant: action.variant ?? "filled",
|
|
382
|
+
loading: action.loading,
|
|
383
|
+
disabled: disabled || action.disabled,
|
|
384
|
+
onClick: () => handleActionClick(action),
|
|
385
|
+
children: action.label
|
|
386
|
+
},
|
|
387
|
+
action.id
|
|
388
|
+
)) })
|
|
389
|
+
] });
|
|
390
|
+
}
|
|
113
391
|
var LEAD_GEN_ROUTE_LINKS = [
|
|
114
392
|
{ label: "Overview", to: "/lead-gen" },
|
|
115
393
|
{ label: "Lists", to: "/lead-gen/lists" },
|
|
@@ -1101,6 +1379,61 @@ function ListMemberDrawer({ memberId, memberKind, listId, onClose }) {
|
|
|
1101
1379
|
}
|
|
1102
1380
|
);
|
|
1103
1381
|
}
|
|
1382
|
+
var panelStyle = {
|
|
1383
|
+
flex: 1,
|
|
1384
|
+
minHeight: 0,
|
|
1385
|
+
overflowY: "auto",
|
|
1386
|
+
paddingTop: "var(--mantine-spacing-sm)"
|
|
1387
|
+
};
|
|
1388
|
+
function StepDetailRightColumn({
|
|
1389
|
+
configuration,
|
|
1390
|
+
advanced,
|
|
1391
|
+
runs,
|
|
1392
|
+
action,
|
|
1393
|
+
activeTab,
|
|
1394
|
+
onTabChange
|
|
1395
|
+
}) {
|
|
1396
|
+
return /* @__PURE__ */ jsxs(
|
|
1397
|
+
Stack,
|
|
1398
|
+
{
|
|
1399
|
+
gap: "sm",
|
|
1400
|
+
style: {
|
|
1401
|
+
flex: 1,
|
|
1402
|
+
minHeight: 0
|
|
1403
|
+
},
|
|
1404
|
+
children: [
|
|
1405
|
+
/* @__PURE__ */ jsxs(
|
|
1406
|
+
Tabs,
|
|
1407
|
+
{
|
|
1408
|
+
value: activeTab,
|
|
1409
|
+
onChange: (value) => {
|
|
1410
|
+
if (value === "configuration" || value === "advanced" || value === "runs") {
|
|
1411
|
+
onTabChange(value);
|
|
1412
|
+
}
|
|
1413
|
+
},
|
|
1414
|
+
style: {
|
|
1415
|
+
flex: 1,
|
|
1416
|
+
minHeight: 0,
|
|
1417
|
+
display: "flex",
|
|
1418
|
+
flexDirection: "column"
|
|
1419
|
+
},
|
|
1420
|
+
children: [
|
|
1421
|
+
/* @__PURE__ */ jsxs(Tabs.List, { children: [
|
|
1422
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "configuration", children: "Configuration" }),
|
|
1423
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "advanced", children: "Advanced" }),
|
|
1424
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "runs", children: "Runs" })
|
|
1425
|
+
] }),
|
|
1426
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "configuration", style: panelStyle, children: configuration }),
|
|
1427
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "advanced", style: panelStyle, children: advanced ?? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No advanced settings for this step." }) }),
|
|
1428
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "runs", style: panelStyle, children: runs })
|
|
1429
|
+
]
|
|
1430
|
+
}
|
|
1431
|
+
),
|
|
1432
|
+
/* @__PURE__ */ jsx(Stack, { gap: "xs", style: { flexShrink: 0 }, children: action })
|
|
1433
|
+
]
|
|
1434
|
+
}
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1104
1437
|
function ListBuilderIndexPage() {
|
|
1105
1438
|
const navigate = useNavigate();
|
|
1106
1439
|
const [query, setQuery] = useState("");
|
|
@@ -1508,6 +1841,9 @@ function PipelineFunnel({ progress, pipelineConfig, actions }) {
|
|
|
1508
1841
|
)
|
|
1509
1842
|
] }) });
|
|
1510
1843
|
}
|
|
1844
|
+
function asRecord(value) {
|
|
1845
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1846
|
+
}
|
|
1511
1847
|
function selectedCount(selection) {
|
|
1512
1848
|
return selection.selectedCompanyIds.length + selection.selectedContactIds.length;
|
|
1513
1849
|
}
|
|
@@ -1532,7 +1868,9 @@ function RunWorkflowModal({
|
|
|
1532
1868
|
onResourceChange,
|
|
1533
1869
|
onSubmitted
|
|
1534
1870
|
}) {
|
|
1535
|
-
const [selectedResourceId, setSelectedResourceId] = useState(
|
|
1871
|
+
const [selectedResourceId, setSelectedResourceId] = useState(
|
|
1872
|
+
initialResourceId ?? actions[0]?.resourceId ?? null
|
|
1873
|
+
);
|
|
1536
1874
|
const selectedAction = useMemo(
|
|
1537
1875
|
() => actions.find((action) => action.resourceId === selectedResourceId) ?? actions[0],
|
|
1538
1876
|
[actions, selectedResourceId]
|
|
@@ -1568,57 +1906,88 @@ function RunWorkflowModal({
|
|
|
1568
1906
|
showApiErrorNotification(error);
|
|
1569
1907
|
}
|
|
1570
1908
|
};
|
|
1571
|
-
const Form = selectedAction?.inputForm;
|
|
1572
1909
|
const count = selectedCount(selection);
|
|
1573
|
-
return /* @__PURE__ */ jsx(
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
value: selectedAction?.resourceId ?? null,
|
|
1588
|
-
onChange: handleResourceChange,
|
|
1589
|
-
disabled: execution.isPending || lockResourceSelection,
|
|
1590
|
-
searchable: true
|
|
1591
|
-
}
|
|
1592
|
-
),
|
|
1593
|
-
selectedAction ? /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
1594
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
1595
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: selectedAction.category }),
|
|
1596
|
-
selectedAction.stagesAffected.map((stage) => /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "outline", color: "gray", children: stage }, stage))
|
|
1910
|
+
return /* @__PURE__ */ jsx(
|
|
1911
|
+
CustomModal,
|
|
1912
|
+
{
|
|
1913
|
+
opened,
|
|
1914
|
+
onClose: () => !execution.isPending && onClose(),
|
|
1915
|
+
size: "lg",
|
|
1916
|
+
loading: execution.isPending,
|
|
1917
|
+
children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
1918
|
+
/* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
1919
|
+
/* @__PURE__ */ jsx(IconBolt, { size: 22 }),
|
|
1920
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1921
|
+
/* @__PURE__ */ jsx(Text, { fw: 600, children: title }),
|
|
1922
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: description })
|
|
1923
|
+
] })
|
|
1597
1924
|
] }),
|
|
1598
|
-
/* @__PURE__ */ jsx(
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
"
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1925
|
+
!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: [
|
|
1926
|
+
/* @__PURE__ */ jsx(
|
|
1927
|
+
Select,
|
|
1928
|
+
{
|
|
1929
|
+
label: "Workflow",
|
|
1930
|
+
data: actionOptions,
|
|
1931
|
+
value: selectedAction?.resourceId ?? null,
|
|
1932
|
+
onChange: handleResourceChange,
|
|
1933
|
+
disabled: execution.isPending || lockResourceSelection,
|
|
1934
|
+
searchable: true
|
|
1935
|
+
}
|
|
1936
|
+
),
|
|
1937
|
+
selectedAction ? /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
1938
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
1939
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: selectedAction.category }),
|
|
1940
|
+
selectedAction.stagesAffected.map((stage) => /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "outline", color: "gray", children: stage }, stage))
|
|
1941
|
+
] }),
|
|
1942
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: selectedAction.description })
|
|
1943
|
+
] }) : null,
|
|
1944
|
+
count > 0 ? /* @__PURE__ */ jsxs(Alert, { color: "blue", variant: "light", children: [
|
|
1945
|
+
"This run includes ",
|
|
1946
|
+
selection.selectedCompanyIds.length,
|
|
1947
|
+
" selected companies and",
|
|
1948
|
+
" ",
|
|
1949
|
+
selection.selectedContactIds.length,
|
|
1950
|
+
" selected contacts."
|
|
1951
|
+
] }) : null,
|
|
1952
|
+
selectedAction ? /* @__PURE__ */ jsx(
|
|
1953
|
+
RunWorkflowConfigForm,
|
|
1954
|
+
{
|
|
1955
|
+
action: selectedAction,
|
|
1956
|
+
list,
|
|
1957
|
+
onSubmit: submitInput,
|
|
1958
|
+
isSubmitting: execution.isPending
|
|
1959
|
+
},
|
|
1960
|
+
selectedAction.resourceId
|
|
1961
|
+
) : null
|
|
1962
|
+
] })
|
|
1963
|
+
] })
|
|
1964
|
+
}
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
function RunWorkflowConfigForm({ action, list, onSubmit, isSubmitting }) {
|
|
1968
|
+
const schema = action.schema;
|
|
1969
|
+
const layout = action.layout;
|
|
1970
|
+
const [config, setConfig] = useState(() => asRecord(action.defaultInput?.(list)));
|
|
1971
|
+
const handleChange = (next) => {
|
|
1972
|
+
setConfig(next);
|
|
1973
|
+
};
|
|
1974
|
+
const handleSubmit = async () => {
|
|
1975
|
+
await onSubmit(config);
|
|
1976
|
+
};
|
|
1977
|
+
return /* @__PURE__ */ jsx(Stack, { gap: "md", children: /* @__PURE__ */ jsx(
|
|
1978
|
+
StepConfigForm,
|
|
1979
|
+
{
|
|
1980
|
+
schema,
|
|
1981
|
+
layout,
|
|
1982
|
+
value: config,
|
|
1983
|
+
onChange: (v) => handleChange(asRecord(v)),
|
|
1984
|
+
actions: [{ id: "run", label: `Run ${action.label}`, loading: isSubmitting }],
|
|
1985
|
+
onAction: async () => {
|
|
1986
|
+
await handleSubmit();
|
|
1987
|
+
},
|
|
1988
|
+
disabled: isSubmitting
|
|
1989
|
+
}
|
|
1990
|
+
) });
|
|
1622
1991
|
}
|
|
1623
1992
|
function formatDateTime2(value) {
|
|
1624
1993
|
if (!value) return "Not yet";
|
|
@@ -1668,15 +2037,20 @@ function getSummaryKeys(value) {
|
|
|
1668
2037
|
if (!hasObjectContent(value)) return [];
|
|
1669
2038
|
return Object.keys(value).slice(0, 6);
|
|
1670
2039
|
}
|
|
1671
|
-
function WorkflowRunsPanel({
|
|
2040
|
+
function WorkflowRunsPanel({
|
|
2041
|
+
listId,
|
|
2042
|
+
title = "Workflow Runs",
|
|
2043
|
+
resourceFilter,
|
|
2044
|
+
onClearResourceFilter
|
|
2045
|
+
}) {
|
|
1672
2046
|
const navigate = useNavigate();
|
|
1673
|
-
const executionsQuery = useListExecutions(listId);
|
|
2047
|
+
const executionsQuery = useListExecutions(listId, resourceFilter ? { resourceId: resourceFilter } : {});
|
|
1674
2048
|
const [expandedExecutionId, setExpandedExecutionId] = useState(null);
|
|
1675
2049
|
const executions = useMemo(() => executionsQuery.data ?? [], [executionsQuery.data]);
|
|
1676
2050
|
const openWorkflow = (resourceId) => {
|
|
1677
2051
|
void navigate({ to: "/operations/resources/workflow/$workflowId", params: { workflowId: resourceId } });
|
|
1678
2052
|
};
|
|
1679
|
-
return /* @__PURE__ */
|
|
2053
|
+
return /* @__PURE__ */ jsxs(
|
|
1680
2054
|
TabSection,
|
|
1681
2055
|
{
|
|
1682
2056
|
icon: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }),
|
|
@@ -1693,89 +2067,95 @@ function WorkflowRunsPanel({ listId, title = "Workflow Runs" }) {
|
|
|
1693
2067
|
children: /* @__PURE__ */ jsx(IconRefresh, { size: 14 })
|
|
1694
2068
|
}
|
|
1695
2069
|
) }),
|
|
1696
|
-
children:
|
|
1697
|
-
/* @__PURE__ */
|
|
1698
|
-
/* @__PURE__ */ jsx(
|
|
1699
|
-
/* @__PURE__ */ jsx(
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
/* @__PURE__ */ jsx(Table.
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
tabIndex: hasDetails ? 0 : void 0,
|
|
1719
|
-
"aria-label": hasDetails ? expanded ? "Collapse run details" : "Expand run details" : void 0,
|
|
1720
|
-
onClick: hasDetails ? () => setExpandedExecutionId(expanded ? null : execution.executionId) : void 0,
|
|
1721
|
-
onKeyDown: hasDetails ? (event) => {
|
|
1722
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1723
|
-
event.preventDefault();
|
|
1724
|
-
setExpandedExecutionId(expanded ? null : execution.executionId);
|
|
1725
|
-
}
|
|
1726
|
-
} : void 0,
|
|
1727
|
-
style: {
|
|
1728
|
-
cursor: hasDetails ? "pointer" : "default",
|
|
1729
|
-
opacity: hasDetails ? 1 : 0.7
|
|
1730
|
-
},
|
|
1731
|
-
children: expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 })
|
|
1732
|
-
}
|
|
1733
|
-
) }),
|
|
1734
|
-
/* @__PURE__ */ jsxs(Table.Td, { children: [
|
|
1735
|
-
execution.resourceId ? /* @__PURE__ */ jsx(
|
|
1736
|
-
Text,
|
|
2070
|
+
children: [
|
|
2071
|
+
resourceFilter ? /* @__PURE__ */ jsxs(Group, { gap: "xs", mb: "xs", children: [
|
|
2072
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Filtered by workflow:" }),
|
|
2073
|
+
/* @__PURE__ */ jsx(Pill, { withRemoveButton: true, onRemove: onClearResourceFilter, children: resourceFilter })
|
|
2074
|
+
] }) : null,
|
|
2075
|
+
executionsQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "lg", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !executions.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: resourceFilter ? `No workflow runs recorded for ${resourceFilter}.` : "No workflow runs recorded for this list." }) : /* @__PURE__ */ jsx(Table.ScrollContainer, { minWidth: 720, children: /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
|
|
2076
|
+
/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
2077
|
+
/* @__PURE__ */ jsx(Table.Th, {}),
|
|
2078
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Workflow" }),
|
|
2079
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
|
|
2080
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
|
|
2081
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Completed" }),
|
|
2082
|
+
/* @__PURE__ */ jsx(Table.Th, { children: "Duration" })
|
|
2083
|
+
] }) }),
|
|
2084
|
+
/* @__PURE__ */ jsx(Table.Tbody, { children: executions.map((execution) => {
|
|
2085
|
+
const details = getRunDetails(execution);
|
|
2086
|
+
const hasDetails = details.input !== void 0 || details.config !== void 0;
|
|
2087
|
+
const expanded = expandedExecutionId === execution.executionId;
|
|
2088
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2089
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
2090
|
+
/* @__PURE__ */ jsx(Table.Td, { w: 32, children: /* @__PURE__ */ jsx(
|
|
2091
|
+
ThemeIcon,
|
|
1737
2092
|
{
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
2093
|
+
variant: "light",
|
|
2094
|
+
color: "blue",
|
|
2095
|
+
size: "md",
|
|
2096
|
+
role: hasDetails ? "button" : void 0,
|
|
2097
|
+
tabIndex: hasDetails ? 0 : void 0,
|
|
2098
|
+
"aria-label": hasDetails ? expanded ? "Collapse run details" : "Expand run details" : void 0,
|
|
2099
|
+
onClick: hasDetails ? () => setExpandedExecutionId(expanded ? null : execution.executionId) : void 0,
|
|
2100
|
+
onKeyDown: hasDetails ? (event) => {
|
|
1744
2101
|
if (event.key === "Enter" || event.key === " ") {
|
|
1745
2102
|
event.preventDefault();
|
|
1746
|
-
|
|
2103
|
+
setExpandedExecutionId(expanded ? null : execution.executionId);
|
|
1747
2104
|
}
|
|
2105
|
+
} : void 0,
|
|
2106
|
+
style: {
|
|
2107
|
+
cursor: hasDetails ? "pointer" : "default",
|
|
2108
|
+
opacity: hasDetails ? 1 : 0.7
|
|
1748
2109
|
},
|
|
1749
|
-
|
|
1750
|
-
children: execution.resourceId
|
|
2110
|
+
children: expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 })
|
|
1751
2111
|
}
|
|
1752
|
-
)
|
|
1753
|
-
/* @__PURE__ */
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
2112
|
+
) }),
|
|
2113
|
+
/* @__PURE__ */ jsxs(Table.Td, { children: [
|
|
2114
|
+
execution.resourceId ? /* @__PURE__ */ jsx(
|
|
2115
|
+
Text,
|
|
2116
|
+
{
|
|
2117
|
+
fw: 500,
|
|
2118
|
+
role: "button",
|
|
2119
|
+
tabIndex: 0,
|
|
2120
|
+
c: "blue",
|
|
2121
|
+
onClick: () => openWorkflow(execution.resourceId),
|
|
2122
|
+
onKeyDown: (event) => {
|
|
2123
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
2124
|
+
event.preventDefault();
|
|
2125
|
+
openWorkflow(execution.resourceId);
|
|
2126
|
+
}
|
|
2127
|
+
},
|
|
2128
|
+
style: { cursor: "pointer" },
|
|
2129
|
+
children: execution.resourceId
|
|
2130
|
+
}
|
|
2131
|
+
) : /* @__PURE__ */ jsx(Text, { fw: 500, children: "Unknown workflow" }),
|
|
2132
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", children: execution.executionId })
|
|
1772
2133
|
] }),
|
|
1773
|
-
/* @__PURE__ */ jsx(
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
2134
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(execution.status), children: execution.status }) }),
|
|
2135
|
+
/* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(execution.createdAt) }),
|
|
2136
|
+
/* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(execution.completedAt) }),
|
|
2137
|
+
/* @__PURE__ */ jsx(Table.Td, { children: formatDuration(execution.durationMs) })
|
|
2138
|
+
] }),
|
|
2139
|
+
/* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: 6, p: 0, children: /* @__PURE__ */ jsx(Collapse, { in: expanded, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", p: "sm", children: [
|
|
2140
|
+
details.input !== void 0 ? /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
2141
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
2142
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Input" }),
|
|
2143
|
+
getSummaryKeys(details.input).map((key) => /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: "gray", children: key }, key))
|
|
2144
|
+
] }),
|
|
2145
|
+
/* @__PURE__ */ jsx(JsonViewer, { data: details.input, maxHeight: 220, fontSize: "0.75rem" })
|
|
2146
|
+
] }) : null,
|
|
2147
|
+
details.config !== void 0 ? /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
2148
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
2149
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Config" }),
|
|
2150
|
+
getSummaryKeys(details.config).map((key) => /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: "gray", children: key }, key))
|
|
2151
|
+
] }),
|
|
2152
|
+
/* @__PURE__ */ jsx(JsonViewer, { data: details.config, maxHeight: 220, fontSize: "0.75rem" })
|
|
2153
|
+
] }) : null
|
|
2154
|
+
] }) }) }) })
|
|
2155
|
+
] }, execution.executionId);
|
|
2156
|
+
}) })
|
|
2157
|
+
] }) })
|
|
2158
|
+
]
|
|
1779
2159
|
}
|
|
1780
2160
|
);
|
|
1781
2161
|
}
|
|
@@ -1918,277 +2298,6 @@ function ListBuilderPage({ listId }) {
|
|
|
1918
2298
|
)
|
|
1919
2299
|
] });
|
|
1920
2300
|
}
|
|
1921
|
-
function CompanyCleanupForm({ list, onSubmit }) {
|
|
1922
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1923
|
-
const form = useForm({
|
|
1924
|
-
initialValues: {
|
|
1925
|
-
targetDescription: "",
|
|
1926
|
-
tag: "",
|
|
1927
|
-
dryRun: true,
|
|
1928
|
-
batchSize: 20
|
|
1929
|
-
},
|
|
1930
|
-
validate: {
|
|
1931
|
-
targetDescription: (value) => value.trim().length > 0 ? null : "Target description is required.",
|
|
1932
|
-
batchSize: (value) => Number.isInteger(value) && value >= 1 ? null : "Use a whole number of at least 1."
|
|
1933
|
-
}
|
|
1934
|
-
});
|
|
1935
|
-
const handleSubmit = form.onSubmit(async (values) => {
|
|
1936
|
-
setIsSubmitting(true);
|
|
1937
|
-
try {
|
|
1938
|
-
const tag = values.tag.trim();
|
|
1939
|
-
await onSubmit({
|
|
1940
|
-
listId: list.id,
|
|
1941
|
-
targetDescription: values.targetDescription.trim(),
|
|
1942
|
-
...tag ? { tag } : {},
|
|
1943
|
-
dryRun: values.dryRun,
|
|
1944
|
-
batchSize: values.batchSize
|
|
1945
|
-
});
|
|
1946
|
-
} finally {
|
|
1947
|
-
setIsSubmitting(false);
|
|
1948
|
-
}
|
|
1949
|
-
});
|
|
1950
|
-
return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
1951
|
-
/* @__PURE__ */ jsx(
|
|
1952
|
-
Textarea,
|
|
1953
|
-
{
|
|
1954
|
-
label: "Target description",
|
|
1955
|
-
placeholder: "independent veterinary clinics in Orange County",
|
|
1956
|
-
minRows: 3,
|
|
1957
|
-
autosize: true,
|
|
1958
|
-
disabled: isSubmitting,
|
|
1959
|
-
required: true,
|
|
1960
|
-
...form.getInputProps("targetDescription")
|
|
1961
|
-
}
|
|
1962
|
-
),
|
|
1963
|
-
/* @__PURE__ */ jsx(TextInput, { label: "Tag kept companies", placeholder: "vet-clinic", disabled: isSubmitting, ...form.getInputProps("tag") }),
|
|
1964
|
-
/* @__PURE__ */ jsx(
|
|
1965
|
-
NumberInput,
|
|
1966
|
-
{
|
|
1967
|
-
label: "Batch size",
|
|
1968
|
-
min: 1,
|
|
1969
|
-
allowDecimal: false,
|
|
1970
|
-
disabled: isSubmitting,
|
|
1971
|
-
required: true,
|
|
1972
|
-
...form.getInputProps("batchSize")
|
|
1973
|
-
}
|
|
1974
|
-
),
|
|
1975
|
-
/* @__PURE__ */ jsx(Switch, { label: "Dry run", disabled: isSubmitting, ...form.getInputProps("dryRun", { type: "checkbox" }) }),
|
|
1976
|
-
/* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(
|
|
1977
|
-
Button,
|
|
1978
|
-
{
|
|
1979
|
-
type: "submit",
|
|
1980
|
-
loading: isSubmitting,
|
|
1981
|
-
disabled: !form.values.targetDescription.trim(),
|
|
1982
|
-
leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }),
|
|
1983
|
-
children: "Run Company Cleanup"
|
|
1984
|
-
}
|
|
1985
|
-
) })
|
|
1986
|
-
] }) });
|
|
1987
|
-
}
|
|
1988
|
-
function optionalNumber(value) {
|
|
1989
|
-
return value === "" ? void 0 : value;
|
|
1990
|
-
}
|
|
1991
|
-
function EmailDiscoveryForm({ list, onSubmit }) {
|
|
1992
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1993
|
-
const form = useForm({
|
|
1994
|
-
initialValues: {
|
|
1995
|
-
maxCompanies: "",
|
|
1996
|
-
dryRun: false,
|
|
1997
|
-
chain: false,
|
|
1998
|
-
concurrency: 1,
|
|
1999
|
-
credentialName: "",
|
|
2000
|
-
tombaTimeoutMs: 15e3
|
|
2001
|
-
},
|
|
2002
|
-
validate: {
|
|
2003
|
-
maxCompanies: (value) => value === "" || Number.isInteger(value) && value >= 1 && value <= 500 ? null : "Use a whole number from 1 to 500.",
|
|
2004
|
-
concurrency: (value) => Number.isInteger(value) && value >= 1 && value <= 10 ? null : "Use a whole number from 1 to 10.",
|
|
2005
|
-
tombaTimeoutMs: (value) => Number.isInteger(value) && value >= 1e3 ? null : "Use a timeout of at least 1000 ms."
|
|
2006
|
-
}
|
|
2007
|
-
});
|
|
2008
|
-
const handleSubmit = form.onSubmit(async (values) => {
|
|
2009
|
-
setIsSubmitting(true);
|
|
2010
|
-
try {
|
|
2011
|
-
const credentialName = values.credentialName.trim();
|
|
2012
|
-
await onSubmit({
|
|
2013
|
-
listId: list.id,
|
|
2014
|
-
...optionalNumber(values.maxCompanies) !== void 0 ? { maxCompanies: optionalNumber(values.maxCompanies) } : {},
|
|
2015
|
-
dryRun: values.dryRun,
|
|
2016
|
-
chain: values.chain,
|
|
2017
|
-
concurrency: values.concurrency,
|
|
2018
|
-
...credentialName ? { credentialName } : {},
|
|
2019
|
-
tombaTimeoutMs: values.tombaTimeoutMs
|
|
2020
|
-
});
|
|
2021
|
-
} finally {
|
|
2022
|
-
setIsSubmitting(false);
|
|
2023
|
-
}
|
|
2024
|
-
});
|
|
2025
|
-
return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
2026
|
-
/* @__PURE__ */ jsx(
|
|
2027
|
-
NumberInput,
|
|
2028
|
-
{
|
|
2029
|
-
label: "Max companies",
|
|
2030
|
-
description: "Leave empty to process every eligible company.",
|
|
2031
|
-
min: 1,
|
|
2032
|
-
max: 500,
|
|
2033
|
-
allowDecimal: false,
|
|
2034
|
-
disabled: isSubmitting,
|
|
2035
|
-
...form.getInputProps("maxCompanies")
|
|
2036
|
-
}
|
|
2037
|
-
),
|
|
2038
|
-
/* @__PURE__ */ jsx(
|
|
2039
|
-
NumberInput,
|
|
2040
|
-
{
|
|
2041
|
-
label: "Concurrency",
|
|
2042
|
-
min: 1,
|
|
2043
|
-
max: 10,
|
|
2044
|
-
allowDecimal: false,
|
|
2045
|
-
disabled: isSubmitting,
|
|
2046
|
-
required: true,
|
|
2047
|
-
...form.getInputProps("concurrency")
|
|
2048
|
-
}
|
|
2049
|
-
),
|
|
2050
|
-
/* @__PURE__ */ jsx(
|
|
2051
|
-
TextInput,
|
|
2052
|
-
{
|
|
2053
|
-
label: "Tomba credential",
|
|
2054
|
-
placeholder: "Default credential",
|
|
2055
|
-
disabled: isSubmitting,
|
|
2056
|
-
...form.getInputProps("credentialName")
|
|
2057
|
-
}
|
|
2058
|
-
),
|
|
2059
|
-
/* @__PURE__ */ jsx(
|
|
2060
|
-
NumberInput,
|
|
2061
|
-
{
|
|
2062
|
-
label: "Tomba timeout",
|
|
2063
|
-
suffix: " ms",
|
|
2064
|
-
min: 1e3,
|
|
2065
|
-
step: 1e3,
|
|
2066
|
-
allowDecimal: false,
|
|
2067
|
-
disabled: isSubmitting,
|
|
2068
|
-
required: true,
|
|
2069
|
-
...form.getInputProps("tombaTimeoutMs")
|
|
2070
|
-
}
|
|
2071
|
-
),
|
|
2072
|
-
/* @__PURE__ */ jsx(Switch, { label: "Dry run", disabled: isSubmitting, ...form.getInputProps("dryRun", { type: "checkbox" }) }),
|
|
2073
|
-
/* @__PURE__ */ jsx(
|
|
2074
|
-
Switch,
|
|
2075
|
-
{
|
|
2076
|
-
label: "Run email verification after discovery",
|
|
2077
|
-
disabled: isSubmitting,
|
|
2078
|
-
...form.getInputProps("chain", { type: "checkbox" })
|
|
2079
|
-
}
|
|
2080
|
-
),
|
|
2081
|
-
/* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", loading: isSubmitting, leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), children: "Run Email Discovery" }) })
|
|
2082
|
-
] }) });
|
|
2083
|
-
}
|
|
2084
|
-
function EmailVerificationForm({ list, onSubmit }) {
|
|
2085
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
2086
|
-
const form = useForm({
|
|
2087
|
-
initialValues: {
|
|
2088
|
-
limit: 100,
|
|
2089
|
-
skipAlreadyVerified: true
|
|
2090
|
-
},
|
|
2091
|
-
validate: {
|
|
2092
|
-
limit: (value) => Number.isInteger(value) && value >= 1 && value <= 500 ? null : "Use a whole number from 1 to 500."
|
|
2093
|
-
}
|
|
2094
|
-
});
|
|
2095
|
-
const handleSubmit = form.onSubmit(async (values) => {
|
|
2096
|
-
setIsSubmitting(true);
|
|
2097
|
-
try {
|
|
2098
|
-
await onSubmit({
|
|
2099
|
-
listId: list.id,
|
|
2100
|
-
limit: values.limit,
|
|
2101
|
-
skipAlreadyVerified: values.skipAlreadyVerified
|
|
2102
|
-
});
|
|
2103
|
-
} finally {
|
|
2104
|
-
setIsSubmitting(false);
|
|
2105
|
-
}
|
|
2106
|
-
});
|
|
2107
|
-
return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
2108
|
-
/* @__PURE__ */ jsx(
|
|
2109
|
-
NumberInput,
|
|
2110
|
-
{
|
|
2111
|
-
label: "Contact limit",
|
|
2112
|
-
min: 1,
|
|
2113
|
-
max: 500,
|
|
2114
|
-
allowDecimal: false,
|
|
2115
|
-
disabled: isSubmitting,
|
|
2116
|
-
required: true,
|
|
2117
|
-
...form.getInputProps("limit")
|
|
2118
|
-
}
|
|
2119
|
-
),
|
|
2120
|
-
/* @__PURE__ */ jsx(
|
|
2121
|
-
Switch,
|
|
2122
|
-
{
|
|
2123
|
-
label: "Skip already verified contacts",
|
|
2124
|
-
disabled: isSubmitting,
|
|
2125
|
-
...form.getInputProps("skipAlreadyVerified", { type: "checkbox" })
|
|
2126
|
-
}
|
|
2127
|
-
),
|
|
2128
|
-
/* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", loading: isSubmitting, leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), children: "Run Email Verification" }) })
|
|
2129
|
-
] }) });
|
|
2130
|
-
}
|
|
2131
|
-
function WebsiteExtractForm({ list, onSubmit }) {
|
|
2132
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
2133
|
-
const form = useForm({
|
|
2134
|
-
initialValues: {
|
|
2135
|
-
limit: 200,
|
|
2136
|
-
concurrency: 10,
|
|
2137
|
-
chain: false
|
|
2138
|
-
},
|
|
2139
|
-
validate: {
|
|
2140
|
-
limit: (value) => Number.isInteger(value) && value >= 1 && value <= 200 ? null : "Use a whole number from 1 to 200.",
|
|
2141
|
-
concurrency: (value) => Number.isInteger(value) && value >= 1 ? null : "Use a whole number of at least 1."
|
|
2142
|
-
}
|
|
2143
|
-
});
|
|
2144
|
-
const handleSubmit = form.onSubmit(async (values) => {
|
|
2145
|
-
setIsSubmitting(true);
|
|
2146
|
-
try {
|
|
2147
|
-
await onSubmit({
|
|
2148
|
-
listId: list.id,
|
|
2149
|
-
limit: values.limit,
|
|
2150
|
-
concurrency: values.concurrency,
|
|
2151
|
-
chain: values.chain
|
|
2152
|
-
});
|
|
2153
|
-
} finally {
|
|
2154
|
-
setIsSubmitting(false);
|
|
2155
|
-
}
|
|
2156
|
-
});
|
|
2157
|
-
return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
2158
|
-
/* @__PURE__ */ jsx(
|
|
2159
|
-
NumberInput,
|
|
2160
|
-
{
|
|
2161
|
-
label: "Company limit",
|
|
2162
|
-
min: 1,
|
|
2163
|
-
max: 200,
|
|
2164
|
-
allowDecimal: false,
|
|
2165
|
-
disabled: isSubmitting,
|
|
2166
|
-
required: true,
|
|
2167
|
-
...form.getInputProps("limit")
|
|
2168
|
-
}
|
|
2169
|
-
),
|
|
2170
|
-
/* @__PURE__ */ jsx(
|
|
2171
|
-
NumberInput,
|
|
2172
|
-
{
|
|
2173
|
-
label: "Concurrency",
|
|
2174
|
-
min: 1,
|
|
2175
|
-
allowDecimal: false,
|
|
2176
|
-
disabled: isSubmitting,
|
|
2177
|
-
required: true,
|
|
2178
|
-
...form.getInputProps("concurrency")
|
|
2179
|
-
}
|
|
2180
|
-
),
|
|
2181
|
-
/* @__PURE__ */ jsx(
|
|
2182
|
-
Switch,
|
|
2183
|
-
{
|
|
2184
|
-
label: "Run company qualification after extraction",
|
|
2185
|
-
disabled: isSubmitting,
|
|
2186
|
-
...form.getInputProps("chain", { type: "checkbox" })
|
|
2187
|
-
}
|
|
2188
|
-
),
|
|
2189
|
-
/* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", loading: isSubmitting, leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), children: "Run Website Extract" }) })
|
|
2190
|
-
] }) });
|
|
2191
|
-
}
|
|
2192
2301
|
function formatDateTime4(value) {
|
|
2193
2302
|
if (!value) return "Not yet";
|
|
2194
2303
|
return new Date(value).toLocaleString("en-US", {
|
|
@@ -2237,7 +2346,7 @@ function getMemberStateColor2(stateKey) {
|
|
|
2237
2346
|
return "gray";
|
|
2238
2347
|
}
|
|
2239
2348
|
}
|
|
2240
|
-
function
|
|
2349
|
+
function asRecord2(value) {
|
|
2241
2350
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2242
2351
|
}
|
|
2243
2352
|
function getRunStatusColor(status) {
|
|
@@ -2259,25 +2368,22 @@ function getRunStatusColor(status) {
|
|
|
2259
2368
|
}
|
|
2260
2369
|
}
|
|
2261
2370
|
function getRunInput(run) {
|
|
2262
|
-
const payload =
|
|
2371
|
+
const payload = asRecord2(run.payload);
|
|
2263
2372
|
return run.input ?? run.inputs ?? payload.input ?? payload.inputs;
|
|
2264
2373
|
}
|
|
2265
|
-
function
|
|
2266
|
-
return
|
|
2374
|
+
function sanitizeStepInput(value, _capabilityKey) {
|
|
2375
|
+
return value;
|
|
2267
2376
|
}
|
|
2268
2377
|
function getDefaultStepInput(list, action) {
|
|
2269
|
-
return
|
|
2378
|
+
return asRecord2(action?.defaultInput?.(list));
|
|
2270
2379
|
}
|
|
2271
|
-
function
|
|
2272
|
-
const persistedConfig = capabilityKey ? list.metadata.stepConfig?.[capabilityKey] : void 0;
|
|
2273
|
-
if (persistedConfig !== void 0) return asRecord(persistedConfig);
|
|
2380
|
+
function getInitialStepInput(list, action) {
|
|
2274
2381
|
return getDefaultStepInput(list, action);
|
|
2275
2382
|
}
|
|
2276
|
-
function mergeStepRunInput(list, action,
|
|
2383
|
+
function mergeStepRunInput(list, action, inputAtSubmit) {
|
|
2277
2384
|
return {
|
|
2278
2385
|
...getDefaultStepInput(list, action),
|
|
2279
|
-
...
|
|
2280
|
-
...formStateAtSubmit
|
|
2386
|
+
...inputAtSubmit
|
|
2281
2387
|
};
|
|
2282
2388
|
}
|
|
2283
2389
|
var ORPHAN_STAGE_ORDER = 9999;
|
|
@@ -2285,10 +2391,6 @@ var EMPTY_SELECTION2 = {
|
|
|
2285
2391
|
selectedCompanyIds: [],
|
|
2286
2392
|
selectedContactIds: []
|
|
2287
2393
|
};
|
|
2288
|
-
var BUILD_TEMPLATE_SELECT_OPTIONS2 = PROSPECTING_BUILD_TEMPLATE_OPTIONS.map((template) => ({
|
|
2289
|
-
value: template.id,
|
|
2290
|
-
label: template.label
|
|
2291
|
-
}));
|
|
2292
2394
|
var MVP_BUILD_STEPS = [
|
|
2293
2395
|
{
|
|
2294
2396
|
id: "source-companies",
|
|
@@ -2444,10 +2546,12 @@ function getPrerequisiteSteps(step, byStepId) {
|
|
|
2444
2546
|
return dependency ? [dependency] : [];
|
|
2445
2547
|
});
|
|
2446
2548
|
}
|
|
2447
|
-
function getStepActionKind(ready, failed, action) {
|
|
2549
|
+
function getStepActionKind(step, ready, failed, action) {
|
|
2448
2550
|
if (!action) return "none";
|
|
2449
2551
|
if (failed > 0) return "retry_failed";
|
|
2450
2552
|
if (ready > 0) return "run_next_batch";
|
|
2553
|
+
const isSeedStep = (step.dependsOn?.length ?? 0) === 0 && step.outputs.includes(step.primaryEntity);
|
|
2554
|
+
if (isSeedStep) return "run_next_batch";
|
|
2451
2555
|
return "none";
|
|
2452
2556
|
}
|
|
2453
2557
|
function getStepActionLabel(kind) {
|
|
@@ -2480,7 +2584,7 @@ function deriveBuildStepStates(list, progress, actions) {
|
|
|
2480
2584
|
const entityTotal = getEntityTotal(progress, step.primaryEntity);
|
|
2481
2585
|
const prerequisites = getPrerequisiteSteps(step, byStepId);
|
|
2482
2586
|
const hasDependencies = (step.dependsOn?.length ?? 0) > 0;
|
|
2483
|
-
const eligibleTotal = hasDependencies ? prerequisites.reduce((sum, prerequisite) => sum + prerequisite.complete, 0) : entityTotal > 0 ? entityTotal :
|
|
2587
|
+
const eligibleTotal = hasDependencies ? prerequisites.reduce((sum, prerequisite) => sum + prerequisite.complete, 0) : entityTotal > 0 ? entityTotal : 0;
|
|
2484
2588
|
const total = Math.max(stageProgress?.total ?? 0, entityTotal, eligibleTotal);
|
|
2485
2589
|
const complete = stageProgress ? stageProgress.success + stageProgress.noResult + stageProgress.skipped + stageProgress.other : 0;
|
|
2486
2590
|
const failed = stageProgress?.error ?? 0;
|
|
@@ -2488,7 +2592,7 @@ function deriveBuildStepStates(list, progress, actions) {
|
|
|
2488
2592
|
const blocked = hasDependencies ? Math.max(entityTotal - eligibleTotal, 0) : 0;
|
|
2489
2593
|
const status = failed > 0 ? "failed" : ready > 0 ? "ready" : blocked > 0 || total === 0 ? "blocked" : "complete";
|
|
2490
2594
|
const action = findActionForStep(actions, step);
|
|
2491
|
-
const nextActionKind = getStepActionKind(ready, failed, action);
|
|
2595
|
+
const nextActionKind = getStepActionKind(step, ready, failed, action);
|
|
2492
2596
|
const state = {
|
|
2493
2597
|
...step,
|
|
2494
2598
|
status,
|
|
@@ -2516,74 +2620,173 @@ function resolveBuildState(list, progress, actions) {
|
|
|
2516
2620
|
recommendedAction: recommendedStep?.recommendedAction ?? null
|
|
2517
2621
|
};
|
|
2518
2622
|
}
|
|
2519
|
-
function
|
|
2520
|
-
|
|
2623
|
+
function getStageStatus(entry) {
|
|
2624
|
+
if (!entry || (entry.total ?? 0) === 0) return "not-started";
|
|
2625
|
+
if ((entry.error ?? 0) > 0) return "errors";
|
|
2626
|
+
if ((entry.attempted ?? 0) >= (entry.total ?? 0) && (entry.success ?? 0) > 0) return "complete";
|
|
2627
|
+
return "in-progress";
|
|
2628
|
+
}
|
|
2629
|
+
function getStageColors(status) {
|
|
2630
|
+
switch (status) {
|
|
2631
|
+
case "complete":
|
|
2632
|
+
return {
|
|
2633
|
+
bg: "var(--color-success)",
|
|
2634
|
+
fg: "white",
|
|
2635
|
+
border: "var(--color-success)",
|
|
2636
|
+
ring: "color-mix(in srgb, var(--color-success) 22%, transparent)"
|
|
2637
|
+
};
|
|
2638
|
+
case "errors":
|
|
2639
|
+
return {
|
|
2640
|
+
bg: "var(--color-error)",
|
|
2641
|
+
fg: "white",
|
|
2642
|
+
border: "var(--color-error)",
|
|
2643
|
+
ring: "color-mix(in srgb, var(--color-error) 22%, transparent)"
|
|
2644
|
+
};
|
|
2645
|
+
case "in-progress":
|
|
2646
|
+
return {
|
|
2647
|
+
bg: "var(--color-primary)",
|
|
2648
|
+
fg: "white",
|
|
2649
|
+
border: "var(--color-primary)",
|
|
2650
|
+
ring: "color-mix(in srgb, var(--color-primary) 22%, transparent)"
|
|
2651
|
+
};
|
|
2652
|
+
case "not-started":
|
|
2653
|
+
default:
|
|
2654
|
+
return {
|
|
2655
|
+
bg: "color-mix(in srgb, var(--color-primary) 28%, var(--mantine-color-body))",
|
|
2656
|
+
fg: "color-mix(in srgb, var(--color-primary) 55%, var(--color-text-dimmed))",
|
|
2657
|
+
border: "color-mix(in srgb, var(--color-primary) 45%, var(--color-border))",
|
|
2658
|
+
ring: "color-mix(in srgb, var(--color-primary) 10%, transparent)"
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
var STAGE_NODE_WIDTH = 110;
|
|
2663
|
+
var STAGE_CIRCLE_SIZE = 36;
|
|
2664
|
+
function StageNode({
|
|
2665
|
+
index,
|
|
2666
|
+
stageKey,
|
|
2667
|
+
fallbackLabel,
|
|
2668
|
+
entry
|
|
2669
|
+
}) {
|
|
2670
|
+
const label = LEAD_GEN_STAGE_CATALOG[stageKey]?.label ?? fallbackLabel ?? stageKey;
|
|
2671
|
+
const status = getStageStatus(entry);
|
|
2672
|
+
const colors = getStageColors(status);
|
|
2673
|
+
const total = entry?.total ?? 0;
|
|
2674
|
+
const attempted = entry?.attempted ?? 0;
|
|
2675
|
+
const success = entry?.success ?? 0;
|
|
2676
|
+
const tooltipLines = entry ? [
|
|
2677
|
+
`${attempted} / ${total} attempted`,
|
|
2678
|
+
`${success} success`,
|
|
2679
|
+
(entry.noResult ?? 0) > 0 ? `${entry.noResult} no result` : null,
|
|
2680
|
+
(entry.skipped ?? 0) > 0 ? `${entry.skipped} skipped` : null,
|
|
2681
|
+
(entry.error ?? 0) > 0 ? `${entry.error} errors` : null,
|
|
2682
|
+
(entry.notAttempted ?? 0) > 0 ? `${entry.notAttempted} not attempted` : null
|
|
2683
|
+
].filter(Boolean) : ["Not started"];
|
|
2684
|
+
return /* @__PURE__ */ jsxs(
|
|
2685
|
+
Stack,
|
|
2686
|
+
{
|
|
2687
|
+
gap: 6,
|
|
2688
|
+
align: "center",
|
|
2689
|
+
style: {
|
|
2690
|
+
width: STAGE_NODE_WIDTH,
|
|
2691
|
+
flex: "0 0 auto",
|
|
2692
|
+
padding: "0 4px",
|
|
2693
|
+
position: "relative",
|
|
2694
|
+
zIndex: 1
|
|
2695
|
+
},
|
|
2696
|
+
children: [
|
|
2697
|
+
/* @__PURE__ */ jsx(Tooltip, { label: tooltipLines.join(" \xB7 "), position: "top", withArrow: true, multiline: true, maw: 260, children: /* @__PURE__ */ jsx(
|
|
2698
|
+
Box,
|
|
2699
|
+
{
|
|
2700
|
+
style: {
|
|
2701
|
+
width: STAGE_CIRCLE_SIZE,
|
|
2702
|
+
height: STAGE_CIRCLE_SIZE,
|
|
2703
|
+
borderRadius: "50%",
|
|
2704
|
+
backgroundColor: colors.bg,
|
|
2705
|
+
border: `1.5px solid ${colors.border}`,
|
|
2706
|
+
display: "flex",
|
|
2707
|
+
alignItems: "center",
|
|
2708
|
+
justifyContent: "center",
|
|
2709
|
+
boxShadow: `0 0 0 4px ${colors.ring}`,
|
|
2710
|
+
transition: "all var(--duration-normal) var(--easing)"
|
|
2711
|
+
},
|
|
2712
|
+
children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: status === "not-started" ? 500 : 700, style: { color: colors.fg, lineHeight: 1 }, children: status === "complete" ? "\u2713" : index + 1 })
|
|
2713
|
+
}
|
|
2714
|
+
) }),
|
|
2715
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, align: "center", style: { minWidth: 0, maxWidth: "100%" }, children: [
|
|
2716
|
+
/* @__PURE__ */ jsx(
|
|
2717
|
+
Text,
|
|
2718
|
+
{
|
|
2719
|
+
size: "xs",
|
|
2720
|
+
fw: status === "not-started" ? 500 : 600,
|
|
2721
|
+
ta: "center",
|
|
2722
|
+
lineClamp: 1,
|
|
2723
|
+
style: {
|
|
2724
|
+
maxWidth: "100%",
|
|
2725
|
+
color: status === "not-started" ? "var(--color-text-dimmed)" : "var(--color-text)",
|
|
2726
|
+
letterSpacing: 0.2
|
|
2727
|
+
},
|
|
2728
|
+
children: label
|
|
2729
|
+
}
|
|
2730
|
+
),
|
|
2731
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", style: { color: "var(--color-text-subtle)", fontVariantNumeric: "tabular-nums" }, children: entry ? `${attempted}/${total}` : "Pending" })
|
|
2732
|
+
] })
|
|
2733
|
+
]
|
|
2734
|
+
}
|
|
2735
|
+
);
|
|
2736
|
+
}
|
|
2737
|
+
function PipelineStepper({
|
|
2738
|
+
plannedSteps,
|
|
2521
2739
|
byStage,
|
|
2522
2740
|
emptyText
|
|
2523
2741
|
}) {
|
|
2524
|
-
const
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
const statusSummary = [
|
|
2541
|
-
`${entry?.success ?? 0} success`,
|
|
2542
|
-
`${entry?.noResult ?? 0} no result`,
|
|
2543
|
-
`${entry?.skipped ?? 0} skipped`,
|
|
2544
|
-
`${entry?.error ?? 0} errors`,
|
|
2545
|
-
(entry?.other ?? 0) > 0 ? `${entry?.other ?? 0} other` : null,
|
|
2546
|
-
(entry?.notAttempted ?? 0) > 0 ? `${entry?.notAttempted ?? 0} not attempted` : null
|
|
2547
|
-
].filter(Boolean);
|
|
2548
|
-
return /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
2549
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
2550
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", children: label }),
|
|
2551
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
2552
|
-
attempted,
|
|
2553
|
-
" / ",
|
|
2554
|
-
total,
|
|
2555
|
-
" attempted (",
|
|
2556
|
-
percent2,
|
|
2557
|
-
"%)"
|
|
2558
|
-
] })
|
|
2559
|
-
] }),
|
|
2742
|
+
const stageKeys = plannedSteps.length > 0 ? plannedSteps.map((s) => s.stageKey) : sortStageKeys(Object.keys(byStage));
|
|
2743
|
+
const labelByKey = new Map(plannedSteps.map((s) => [s.stageKey, s.label]));
|
|
2744
|
+
if (stageKeys.length === 0) {
|
|
2745
|
+
return /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: emptyText });
|
|
2746
|
+
}
|
|
2747
|
+
return /* @__PURE__ */ jsx(Box, { style: { overflowX: "auto", padding: "4px 0" }, children: /* @__PURE__ */ jsxs(
|
|
2748
|
+
Box,
|
|
2749
|
+
{
|
|
2750
|
+
style: {
|
|
2751
|
+
position: "relative",
|
|
2752
|
+
display: "flex",
|
|
2753
|
+
justifyContent: "space-between",
|
|
2754
|
+
alignItems: "flex-start",
|
|
2755
|
+
minWidth: stageKeys.length * STAGE_NODE_WIDTH
|
|
2756
|
+
},
|
|
2757
|
+
children: [
|
|
2560
2758
|
/* @__PURE__ */ jsx(
|
|
2561
2759
|
Box,
|
|
2562
2760
|
{
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
bg: segment.color
|
|
2572
|
-
},
|
|
2573
|
-
segment.key
|
|
2574
|
-
))
|
|
2761
|
+
style: {
|
|
2762
|
+
position: "absolute",
|
|
2763
|
+
top: STAGE_CIRCLE_SIZE / 2 - 1,
|
|
2764
|
+
left: STAGE_NODE_WIDTH / 2,
|
|
2765
|
+
right: STAGE_NODE_WIDTH / 2,
|
|
2766
|
+
height: 2,
|
|
2767
|
+
backgroundColor: "var(--color-border)"
|
|
2768
|
+
}
|
|
2575
2769
|
}
|
|
2576
2770
|
),
|
|
2577
|
-
/* @__PURE__ */ jsx(
|
|
2578
|
-
]
|
|
2579
|
-
}
|
|
2580
|
-
|
|
2771
|
+
stageKeys.map((key, index) => /* @__PURE__ */ jsx(StageNode, { index, stageKey: key, fallbackLabel: labelByKey.get(key), entry: byStage[key] }, key))
|
|
2772
|
+
]
|
|
2773
|
+
}
|
|
2774
|
+
) });
|
|
2581
2775
|
}
|
|
2582
2776
|
function PipelineStagesCard({ list, progress }) {
|
|
2583
|
-
const
|
|
2777
|
+
const plannedSteps = list.metadata.buildPlanSnapshot?.steps ?? [];
|
|
2778
|
+
const templateLabel = list.metadata.buildPlanSnapshot?.templateLabel;
|
|
2779
|
+
const combinedByStage = { ...progress.byCompanyStage, ...progress.byContactStage };
|
|
2780
|
+
const hasAnyContent = plannedSteps.length > 0 || Object.keys(combinedByStage).length > 0;
|
|
2584
2781
|
return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
2585
2782
|
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", children: [
|
|
2586
|
-
/* @__PURE__ */
|
|
2783
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
2784
|
+
/* @__PURE__ */ jsx(Title, { order: 5, children: "Pipeline Stages" }),
|
|
2785
|
+
templateLabel && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
2786
|
+
"Template: ",
|
|
2787
|
+
templateLabel
|
|
2788
|
+
] })
|
|
2789
|
+
] }),
|
|
2587
2790
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
2588
2791
|
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor4(list.status), children: list.status }),
|
|
2589
2792
|
list.launchedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
@@ -2596,21 +2799,20 @@ function PipelineStagesCard({ list, progress }) {
|
|
|
2596
2799
|
] })
|
|
2597
2800
|
] })
|
|
2598
2801
|
] }),
|
|
2599
|
-
!
|
|
2600
|
-
/* @__PURE__ */
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
),
|
|
2802
|
+
!hasAnyContent ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No pipeline stages configured yet \u2014 plan a build template to populate this list." }) : /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
2803
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 600, children: [
|
|
2804
|
+
"Pipeline (",
|
|
2805
|
+
progress.totalCompanies,
|
|
2806
|
+
" companies \xB7 ",
|
|
2807
|
+
progress.totalMembers,
|
|
2808
|
+
" contacts)"
|
|
2809
|
+
] }),
|
|
2608
2810
|
/* @__PURE__ */ jsx(
|
|
2609
|
-
|
|
2811
|
+
PipelineStepper,
|
|
2610
2812
|
{
|
|
2611
|
-
|
|
2612
|
-
byStage:
|
|
2613
|
-
emptyText: "No
|
|
2813
|
+
plannedSteps,
|
|
2814
|
+
byStage: combinedByStage,
|
|
2815
|
+
emptyText: "No pipeline activity recorded yet."
|
|
2614
2816
|
}
|
|
2615
2817
|
)
|
|
2616
2818
|
] })
|
|
@@ -2624,12 +2826,12 @@ function ListConfigCard({ list }) {
|
|
|
2624
2826
|
if (!hasIcp && !hasScraping) {
|
|
2625
2827
|
return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
2626
2828
|
/* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
|
|
2627
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No ICP rubric or scraping criteria
|
|
2829
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No ICP rubric or scraping criteria recorded for this list." })
|
|
2628
2830
|
] }) });
|
|
2629
2831
|
}
|
|
2630
2832
|
return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
2631
2833
|
/* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
|
|
2632
|
-
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
|
|
2834
|
+
(hasIcp || hasScraping) && /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
|
|
2633
2835
|
hasIcp && /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
2634
2836
|
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "ICP Rubric" }),
|
|
2635
2837
|
icp.qualificationRubricKey && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
@@ -2700,26 +2902,13 @@ function OverviewTab({ list, progress }) {
|
|
|
2700
2902
|
/* @__PURE__ */ jsx(PipelineStagesCard, { list, progress }),
|
|
2701
2903
|
/* @__PURE__ */ jsx(ListConfigCard, { list }),
|
|
2702
2904
|
hasMetadata && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
2703
|
-
/* @__PURE__ */ jsx(Title, { order: 5, children: "Metadata
|
|
2905
|
+
/* @__PURE__ */ jsx(Title, { order: 5, children: "Metadata" }),
|
|
2704
2906
|
/* @__PURE__ */ jsx(JsonViewer, { data: list.metadata, maxHeight: 320 })
|
|
2705
2907
|
] }) })
|
|
2706
2908
|
]
|
|
2707
2909
|
}
|
|
2708
2910
|
);
|
|
2709
2911
|
}
|
|
2710
|
-
function getBuildStatusLabel(status) {
|
|
2711
|
-
switch (status) {
|
|
2712
|
-
case "failed":
|
|
2713
|
-
return "Needs retry";
|
|
2714
|
-
case "blocked":
|
|
2715
|
-
return "Waiting";
|
|
2716
|
-
case "complete":
|
|
2717
|
-
return "Complete";
|
|
2718
|
-
case "ready":
|
|
2719
|
-
default:
|
|
2720
|
-
return "Ready";
|
|
2721
|
-
}
|
|
2722
|
-
}
|
|
2723
2912
|
function getBuildToneStyle(tone) {
|
|
2724
2913
|
switch (tone) {
|
|
2725
2914
|
case "complete":
|
|
@@ -2737,7 +2926,7 @@ function getBuildToneStyle(tone) {
|
|
|
2737
2926
|
case "ready":
|
|
2738
2927
|
return {
|
|
2739
2928
|
backgroundColor: "color-mix(in srgb, var(--color-primary) 14%, transparent)",
|
|
2740
|
-
borderColor: "
|
|
2929
|
+
borderColor: "var(--border-primary-muted)",
|
|
2741
2930
|
color: "var(--color-primary)"
|
|
2742
2931
|
};
|
|
2743
2932
|
case "blocked":
|
|
@@ -2772,23 +2961,21 @@ function StatusPill({ label, tone }) {
|
|
|
2772
2961
|
}
|
|
2773
2962
|
);
|
|
2774
2963
|
}
|
|
2775
|
-
function
|
|
2776
|
-
const
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
{
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
}
|
|
2791
|
-
);
|
|
2964
|
+
function StepCounterLine({ step }) {
|
|
2965
|
+
const items = [
|
|
2966
|
+
step.ready > 0 ? { label: "ready", value: step.ready, color: "var(--color-primary)" } : null,
|
|
2967
|
+
step.complete > 0 ? { label: "done", value: step.complete, color: "var(--color-success)" } : null,
|
|
2968
|
+
step.failed > 0 ? { label: "failed", value: step.failed, color: "var(--color-error)" } : null,
|
|
2969
|
+
step.blocked > 0 ? { label: "waiting", value: step.blocked, color: "var(--color-text-dimmed)" } : null
|
|
2970
|
+
].filter((item) => item !== null);
|
|
2971
|
+
if (!items.length) {
|
|
2972
|
+
return /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No records yet" });
|
|
2973
|
+
}
|
|
2974
|
+
return /* @__PURE__ */ jsx(Group, { gap: "md", wrap: "nowrap", children: items.map((item) => /* @__PURE__ */ jsxs(Text, { size: "xs", fw: 700, style: { color: item.color }, children: [
|
|
2975
|
+
item.value,
|
|
2976
|
+
" ",
|
|
2977
|
+
item.label
|
|
2978
|
+
] }, item.label)) });
|
|
2792
2979
|
}
|
|
2793
2980
|
function BuildStepProgressBar({ step }) {
|
|
2794
2981
|
const segments = [
|
|
@@ -2813,15 +3000,6 @@ function BuildStepProgressBar({ step }) {
|
|
|
2813
3000
|
}
|
|
2814
3001
|
);
|
|
2815
3002
|
}
|
|
2816
|
-
function getStepCompactSummary(step) {
|
|
2817
|
-
const parts = [
|
|
2818
|
-
step.complete > 0 ? `${step.complete} complete` : null,
|
|
2819
|
-
step.ready > 0 ? `${step.ready} ready` : null,
|
|
2820
|
-
step.failed > 0 ? `${step.failed} failed` : null,
|
|
2821
|
-
step.blocked > 0 ? `${step.blocked} waiting` : null
|
|
2822
|
-
].filter(Boolean);
|
|
2823
|
-
return parts.length ? parts.join(" | ") : "No records yet";
|
|
2824
|
-
}
|
|
2825
3003
|
function getDisplayStep(steps, recommendedStep) {
|
|
2826
3004
|
return recommendedStep ?? steps.find((step) => step.status !== "complete") ?? steps[steps.length - 1] ?? null;
|
|
2827
3005
|
}
|
|
@@ -2834,41 +3012,67 @@ function BuildTab({
|
|
|
2834
3012
|
onViewRuns
|
|
2835
3013
|
}) {
|
|
2836
3014
|
const [selectedStepId, setSelectedStepId] = useState(null);
|
|
2837
|
-
const [
|
|
2838
|
-
const
|
|
3015
|
+
const [stepInputFormState, setStepInputFormState] = useState({});
|
|
3016
|
+
const [stepInputError, setStepInputError] = useState(null);
|
|
3017
|
+
const [stepInputInitialized, setStepInputInitialized] = useState(false);
|
|
3018
|
+
const [activeRightColumnTab, setActiveRightColumnTab] = useState("configuration");
|
|
3019
|
+
const [stepInputResetKey, setStepInputResetKey] = useState(0);
|
|
2839
3020
|
const currentStep = getDisplayStep(steps, recommendedStep);
|
|
2840
3021
|
const selectedStep = steps.find((step) => step.id === selectedStepId) ?? currentStep;
|
|
2841
3022
|
const selectedStepIndex = selectedStep ? steps.findIndex((step) => step.id === selectedStep.id) : -1;
|
|
2842
3023
|
const selectedActionKind = selectedStep?.nextActionKind ?? "none";
|
|
2843
3024
|
const selectedCapabilityKey = selectedStep?.action?.capabilityKey ?? selectedStep?.capabilityKey;
|
|
2844
3025
|
const selectedResourceId = selectedStep?.action?.resourceId ?? null;
|
|
2845
|
-
const
|
|
3026
|
+
const stepSchema = selectedStep?.action?.schema;
|
|
3027
|
+
const stepLayout = selectedStep?.action?.layout;
|
|
2846
3028
|
const recentRunsQuery = useListExecutions(list.id, { resourceId: selectedResourceId, limit: 5 });
|
|
2847
3029
|
const recentRuns = useMemo(() => recentRunsQuery.data ?? [], [recentRunsQuery.data]);
|
|
2848
3030
|
const canRunSelectedAction = !!selectedStep?.action && (selectedActionKind === "retry_failed" || selectedActionKind === "run_next_batch");
|
|
2849
3031
|
const selectedActionIcon = selectedActionKind === "retry_failed" ? /* @__PURE__ */ jsx(IconRefresh, { size: 14 }) : /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 });
|
|
2850
3032
|
useEffect(() => {
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
3033
|
+
setStepInputFormState(getInitialStepInput(list, selectedStep?.action));
|
|
3034
|
+
setStepInputError(null);
|
|
3035
|
+
setStepInputInitialized(false);
|
|
3036
|
+
setStepInputResetKey((k) => k + 1);
|
|
3037
|
+
}, [list, selectedStep?.action]);
|
|
3038
|
+
useEffect(() => {
|
|
3039
|
+
if (stepInputInitialized) return;
|
|
3040
|
+
if (recentRunsQuery.isLoading) return;
|
|
3041
|
+
if (recentRuns.length > 0) {
|
|
3042
|
+
const lastInput = getRunInput(recentRuns[0]);
|
|
3043
|
+
if (lastInput) {
|
|
3044
|
+
setStepInputFormState(sanitizeStepInput(asRecord2(lastInput)));
|
|
3045
|
+
setStepInputResetKey((k) => k + 1);
|
|
2858
3046
|
}
|
|
2859
|
-
}
|
|
3047
|
+
}
|
|
3048
|
+
setStepInputInitialized(true);
|
|
3049
|
+
}, [stepInputInitialized, recentRunsQuery.isLoading, recentRuns, selectedCapabilityKey]);
|
|
3050
|
+
const handleStepInputChange = (next) => {
|
|
3051
|
+
setStepInputFormState(next);
|
|
3052
|
+
if (stepInputError) setStepInputError(null);
|
|
2860
3053
|
};
|
|
2861
3054
|
const handleSelectedAction = () => {
|
|
2862
3055
|
if (!selectedStep || !canRunSelectedAction) return;
|
|
2863
|
-
|
|
3056
|
+
if (stepSchema) {
|
|
3057
|
+
const parsed = stepSchema.safeParse(stepInputFormState);
|
|
3058
|
+
if (!parsed.success) {
|
|
3059
|
+
const firstIssue = parsed.error.issues[0];
|
|
3060
|
+
setStepInputError(firstIssue?.message ?? "Validation failed");
|
|
3061
|
+
return;
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
setStepInputError(null);
|
|
3065
|
+
const submittedInput = stepSchema ? stepInputFormState : {};
|
|
2864
3066
|
if (selectedActionKind === "retry_failed") {
|
|
2865
|
-
onRetryStep(selectedStep,
|
|
3067
|
+
onRetryStep(selectedStep, submittedInput);
|
|
2866
3068
|
return;
|
|
2867
3069
|
}
|
|
2868
|
-
onRunStep(selectedStep,
|
|
3070
|
+
onRunStep(selectedStep, submittedInput);
|
|
2869
3071
|
};
|
|
2870
3072
|
const loadRecentRunInput = (run) => {
|
|
2871
|
-
|
|
3073
|
+
setStepInputFormState(sanitizeStepInput(asRecord2(getRunInput(run))));
|
|
3074
|
+
setStepInputResetKey((k) => k + 1);
|
|
3075
|
+
setActiveRightColumnTab("configuration");
|
|
2872
3076
|
};
|
|
2873
3077
|
return /* @__PURE__ */ jsx(
|
|
2874
3078
|
TabSection,
|
|
@@ -2877,7 +3081,7 @@ function BuildTab({
|
|
|
2877
3081
|
title: "Build",
|
|
2878
3082
|
description: currentStep ? `${currentStep.label} is the current step in this list build.` : "No build steps are available for this list.",
|
|
2879
3083
|
children: /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
|
|
2880
|
-
/* @__PURE__ */ jsx(Stack, { gap: "xs", children: steps.map((step, index) => {
|
|
3084
|
+
/* @__PURE__ */ jsx(Card, { withBorder: true, style: { height: "100%", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx(Stack, { gap: "xs", style: { flex: 1, minHeight: 0 }, children: steps.map((step, index) => {
|
|
2881
3085
|
const isCurrent = currentStep?.id === step.id;
|
|
2882
3086
|
const isSelected = selectedStep?.id === step.id;
|
|
2883
3087
|
const isWaiting = step.status === "blocked";
|
|
@@ -2888,7 +3092,7 @@ function BuildTab({
|
|
|
2888
3092
|
{
|
|
2889
3093
|
onClick: () => setSelectedStepId(step.id),
|
|
2890
3094
|
style: {
|
|
2891
|
-
backgroundColor: isSelected ? "var(--
|
|
3095
|
+
backgroundColor: isSelected ? "var(--surface-primary-strong)" : isPassiveWaiting ? "color-mix(in srgb, var(--color-surface-hover) 38%, transparent)" : "transparent",
|
|
2892
3096
|
border: isSelected ? "var(--active-border)" : "1px solid var(--color-border)",
|
|
2893
3097
|
borderStyle: isPassiveWaiting ? "dashed" : "solid",
|
|
2894
3098
|
borderRadius: 8,
|
|
@@ -2918,101 +3122,123 @@ function BuildTab({
|
|
|
2918
3122
|
children: index + 1
|
|
2919
3123
|
}
|
|
2920
3124
|
),
|
|
2921
|
-
/* @__PURE__ */ jsxs(Stack, { gap:
|
|
3125
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 4, style: { minWidth: 0, flex: 1 }, children: [
|
|
2922
3126
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "space-between", wrap: "nowrap", children: [
|
|
2923
3127
|
/* @__PURE__ */ jsx(Text, { fw: 700, c: isPassiveWaiting ? "dimmed" : void 0, truncate: true, children: step.label }),
|
|
2924
3128
|
isCurrent ? /* @__PURE__ */ jsx(StatusPill, { label: "Current", tone: step.status }) : null,
|
|
2925
3129
|
!isCurrent && isWaiting ? /* @__PURE__ */ jsx(StatusPill, { label: "Waiting", tone: "blocked" }) : null
|
|
2926
3130
|
] }),
|
|
2927
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children:
|
|
3131
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: step.description }),
|
|
3132
|
+
/* @__PURE__ */ jsx(StepCounterLine, { step })
|
|
2928
3133
|
] })
|
|
2929
3134
|
] })
|
|
2930
3135
|
},
|
|
2931
3136
|
step.id
|
|
2932
3137
|
);
|
|
2933
|
-
}) }),
|
|
2934
|
-
selectedStep ? /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
2935
|
-
/* @__PURE__ */ jsxs(
|
|
2936
|
-
/* @__PURE__ */ jsxs(
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
" details"
|
|
2941
|
-
] }),
|
|
2942
|
-
/* @__PURE__ */ jsx(Title, { order: 5, children: selectedStep.label })
|
|
3138
|
+
}) }) }),
|
|
3139
|
+
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: [
|
|
3140
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, style: { minWidth: 0, flexShrink: 0 }, children: [
|
|
3141
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: [
|
|
3142
|
+
"Step ",
|
|
3143
|
+
selectedStepIndex + 1,
|
|
3144
|
+
" details"
|
|
2943
3145
|
] }),
|
|
2944
|
-
/* @__PURE__ */ jsx(
|
|
2945
|
-
] }),
|
|
2946
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: selectedStep.description }),
|
|
2947
|
-
selectedStep.status === "blocked" ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: selectedStep.emptyBlockedText }) : null,
|
|
2948
|
-
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 2, sm: 4 }, spacing: "xs", children: [
|
|
2949
|
-
/* @__PURE__ */ jsx(CountBadge, { label: "Ready", value: selectedStep.ready, tone: "ready" }),
|
|
2950
|
-
/* @__PURE__ */ jsx(CountBadge, { label: "Complete", value: selectedStep.complete, tone: "complete" }),
|
|
2951
|
-
/* @__PURE__ */ jsx(CountBadge, { label: "Failed", value: selectedStep.failed, tone: "failed" }),
|
|
2952
|
-
/* @__PURE__ */ jsx(CountBadge, { label: "Waiting", value: selectedStep.blocked, tone: "blocked" })
|
|
3146
|
+
/* @__PURE__ */ jsx(Title, { order: 5, children: selectedStep.label })
|
|
2953
3147
|
] }),
|
|
2954
3148
|
/* @__PURE__ */ jsx(BuildStepProgressBar, { step: selectedStep }),
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
] }),
|
|
2994
|
-
!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((run) => /* @__PURE__ */ jsx(
|
|
2995
|
-
UnstyledButton,
|
|
2996
|
-
{
|
|
2997
|
-
onClick: () => loadRecentRunInput(run),
|
|
2998
|
-
style: {
|
|
2999
|
-
border: "1px solid var(--color-border)",
|
|
3000
|
-
borderRadius: 8,
|
|
3001
|
-
padding: "8px 10px",
|
|
3002
|
-
textAlign: "left",
|
|
3003
|
-
width: "100%"
|
|
3149
|
+
/* @__PURE__ */ jsx(
|
|
3150
|
+
StepDetailRightColumn,
|
|
3151
|
+
{
|
|
3152
|
+
activeTab: activeRightColumnTab,
|
|
3153
|
+
onTabChange: setActiveRightColumnTab,
|
|
3154
|
+
configuration: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
3155
|
+
selectedStep.status === "blocked" ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: selectedStep.emptyBlockedText }) : null,
|
|
3156
|
+
selectedStep.outputs.includes(selectedStep.primaryEntity) && selectedStep.ready === 0 && selectedStep.complete === 0 && selectedStep.failed === 0 && selectedStep.blocked === 0 ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Run this step to populate members." }) : null,
|
|
3157
|
+
!selectedStep.outputs.includes(selectedStep.primaryEntity) && selectedStep.recommendedAction?.defaultSize !== void 0 && selectedStep.recommendedAction.maxSize !== void 0 ? /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
3158
|
+
"Batch size: ",
|
|
3159
|
+
selectedStep.recommendedAction.defaultSize,
|
|
3160
|
+
" default,",
|
|
3161
|
+
" ",
|
|
3162
|
+
selectedStep.recommendedAction.maxSize,
|
|
3163
|
+
" max."
|
|
3164
|
+
] }) : null,
|
|
3165
|
+
stepSchema && stepLayout ? /* @__PURE__ */ jsx(
|
|
3166
|
+
StepConfigForm,
|
|
3167
|
+
{
|
|
3168
|
+
slot: "main",
|
|
3169
|
+
schema: stepSchema,
|
|
3170
|
+
layout: stepLayout,
|
|
3171
|
+
value: stepInputFormState,
|
|
3172
|
+
onChange: (v) => handleStepInputChange(asRecord2(v) ?? {}),
|
|
3173
|
+
disabled: !canRunSelectedAction
|
|
3174
|
+
},
|
|
3175
|
+
`${selectedResourceId ?? "none"}-main-${stepInputResetKey}`
|
|
3176
|
+
) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No configuration for this step." })
|
|
3177
|
+
] }),
|
|
3178
|
+
advanced: stepSchema && stepLayout?.advanced ? /* @__PURE__ */ jsx(
|
|
3179
|
+
StepConfigForm,
|
|
3180
|
+
{
|
|
3181
|
+
slot: "advanced",
|
|
3182
|
+
schema: stepSchema,
|
|
3183
|
+
layout: stepLayout,
|
|
3184
|
+
value: stepInputFormState,
|
|
3185
|
+
onChange: (v) => handleStepInputChange(asRecord2(v) ?? {}),
|
|
3186
|
+
disabled: !canRunSelectedAction
|
|
3004
3187
|
},
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
/* @__PURE__ */ jsx(
|
|
3188
|
+
`${selectedResourceId ?? "none"}-advanced-${stepInputResetKey}`
|
|
3189
|
+
) : void 0,
|
|
3190
|
+
runs: selectedResourceId ? /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
3191
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
3192
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: "Recent runs" }),
|
|
3193
|
+
recentRunsQuery.isFetching ? /* @__PURE__ */ jsx(Loader, { size: "xs" }) : null
|
|
3194
|
+
] }),
|
|
3195
|
+
!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((run) => /* @__PURE__ */ jsx(
|
|
3196
|
+
UnstyledButton,
|
|
3197
|
+
{
|
|
3198
|
+
onClick: () => loadRecentRunInput(run),
|
|
3199
|
+
style: {
|
|
3200
|
+
border: "1px solid var(--color-border)",
|
|
3201
|
+
borderRadius: 8,
|
|
3202
|
+
padding: "8px 10px",
|
|
3203
|
+
textAlign: "left",
|
|
3204
|
+
width: "100%"
|
|
3205
|
+
},
|
|
3206
|
+
children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
|
|
3207
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, style: { minWidth: 0 }, children: [
|
|
3208
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, truncate: true, children: formatDateTime4(run.createdAt) }),
|
|
3209
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", truncate: true, children: run.executionId })
|
|
3210
|
+
] }),
|
|
3211
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getRunStatusColor(run.status), children: run.status })
|
|
3212
|
+
] })
|
|
3213
|
+
},
|
|
3214
|
+
run.executionId
|
|
3215
|
+
)) })
|
|
3216
|
+
] }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "No runs available for this step." }),
|
|
3217
|
+
action: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3218
|
+
stepInputError ? /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), variant: "light", children: stepInputError }) : null,
|
|
3219
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "flex-end", wrap: "nowrap", children: [
|
|
3220
|
+
/* @__PURE__ */ jsx(
|
|
3221
|
+
Button,
|
|
3222
|
+
{
|
|
3223
|
+
leftSection: selectedActionIcon,
|
|
3224
|
+
disabled: !canRunSelectedAction,
|
|
3225
|
+
onClick: handleSelectedAction,
|
|
3226
|
+
children: selectedActionKind === "none" ? "No action" : getStepActionLabel(selectedActionKind)
|
|
3227
|
+
}
|
|
3228
|
+
),
|
|
3229
|
+
recentRuns.length > 0 ? /* @__PURE__ */ jsx(
|
|
3230
|
+
Button,
|
|
3231
|
+
{
|
|
3232
|
+
variant: "light",
|
|
3233
|
+
leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 }),
|
|
3234
|
+
onClick: () => onViewRuns(selectedResourceId),
|
|
3235
|
+
children: "View runs"
|
|
3236
|
+
}
|
|
3237
|
+
) : null
|
|
3011
3238
|
] })
|
|
3012
|
-
}
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
] }) : null
|
|
3239
|
+
] })
|
|
3240
|
+
}
|
|
3241
|
+
)
|
|
3016
3242
|
] }) }) : null
|
|
3017
3243
|
] })
|
|
3018
3244
|
}
|
|
@@ -3128,25 +3354,22 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3128
3354
|
const listQuery = useList(listId);
|
|
3129
3355
|
const progressQuery = useListProgress(listId);
|
|
3130
3356
|
const deleteListMutation = useDeleteList();
|
|
3131
|
-
const updateListMutation = useUpdateList(listId);
|
|
3132
|
-
const updateListConfigMutation = useUpdateListConfig(listId);
|
|
3133
3357
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
|
3134
|
-
const [pipelineModalOpen, setPipelineModalOpen] = useState(false);
|
|
3135
|
-
const [selectedBuildTemplateId, setSelectedBuildTemplateId] = useState(DEFAULT_PROSPECTING_BUILD_TEMPLATE_ID);
|
|
3136
3358
|
const [runModalOpen, setRunModalOpen] = useState(false);
|
|
3137
3359
|
const [activeTab, setActiveTab] = useState("overview");
|
|
3360
|
+
const [runsResourceFilter, setRunsResourceFilter] = useState(null);
|
|
3138
3361
|
const [initialRunResourceId, setInitialRunResourceId] = useState(null);
|
|
3139
|
-
const [
|
|
3362
|
+
const [pendingStepRunInput, setPendingStepRunInput] = useState(null);
|
|
3140
3363
|
const runModalActions = useMemo(() => {
|
|
3141
|
-
if (!
|
|
3364
|
+
if (!pendingStepRunInput) return actions;
|
|
3142
3365
|
return actions.map((action) => {
|
|
3143
|
-
if (action.resourceId !==
|
|
3366
|
+
if (action.resourceId !== pendingStepRunInput.resourceId) return action;
|
|
3144
3367
|
return {
|
|
3145
3368
|
...action,
|
|
3146
|
-
defaultInput: (nextList) => mergeStepRunInput(nextList, action,
|
|
3369
|
+
defaultInput: (nextList) => mergeStepRunInput(nextList, action, pendingStepRunInput.inputAtSubmit)
|
|
3147
3370
|
};
|
|
3148
3371
|
});
|
|
3149
|
-
}, [actions,
|
|
3372
|
+
}, [actions, pendingStepRunInput]);
|
|
3150
3373
|
const isLoading = listQuery.isLoading || progressQuery.isLoading;
|
|
3151
3374
|
const error = listQuery.error ?? progressQuery.error;
|
|
3152
3375
|
const backButton = /* @__PURE__ */ jsx(
|
|
@@ -3200,12 +3423,7 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3200
3423
|
}
|
|
3201
3424
|
const list = listQuery.data;
|
|
3202
3425
|
const progress = progressQuery.data;
|
|
3203
|
-
const currentBuildTemplateId = list.metadata.buildPlanSnapshot?.templateId ?? DEFAULT_PROSPECTING_BUILD_TEMPLATE_ID;
|
|
3204
3426
|
const currentBuildTemplateLabel = list.metadata.buildPlanSnapshot?.templateLabel ?? "Default lead generation";
|
|
3205
|
-
const selectedBuildTemplate = PROSPECTING_BUILD_TEMPLATE_OPTIONS.find(
|
|
3206
|
-
(template) => template.id === selectedBuildTemplateId
|
|
3207
|
-
);
|
|
3208
|
-
const isSameBuildTemplate = selectedBuildTemplateId === currentBuildTemplateId;
|
|
3209
3427
|
const buildResolution = resolveBuildState(list, progress, actions);
|
|
3210
3428
|
const buildSteps = buildResolution.steps;
|
|
3211
3429
|
const recommendedBuildStep = buildResolution.recommendedStep;
|
|
@@ -3217,17 +3435,16 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3217
3435
|
const closeRunModal = () => {
|
|
3218
3436
|
setRunModalOpen(false);
|
|
3219
3437
|
setInitialRunResourceId(null);
|
|
3220
|
-
|
|
3438
|
+
setPendingStepRunInput(null);
|
|
3221
3439
|
};
|
|
3222
|
-
const openStepRun = (step,
|
|
3223
|
-
if (step.action?.
|
|
3224
|
-
|
|
3440
|
+
const openStepRun = (step, inputAtSubmit) => {
|
|
3441
|
+
if (step.action?.schema) {
|
|
3442
|
+
setPendingStepRunInput({
|
|
3225
3443
|
resourceId: step.action.resourceId,
|
|
3226
|
-
|
|
3227
|
-
formStateAtSubmit
|
|
3444
|
+
inputAtSubmit
|
|
3228
3445
|
});
|
|
3229
3446
|
} else {
|
|
3230
|
-
|
|
3447
|
+
setPendingStepRunInput(null);
|
|
3231
3448
|
}
|
|
3232
3449
|
openRunModal(step.action?.resourceId ?? null);
|
|
3233
3450
|
};
|
|
@@ -3243,39 +3460,6 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3243
3460
|
}
|
|
3244
3461
|
});
|
|
3245
3462
|
};
|
|
3246
|
-
const openPipelineModal = () => {
|
|
3247
|
-
setSelectedBuildTemplateId(currentBuildTemplateId);
|
|
3248
|
-
setPipelineModalOpen(true);
|
|
3249
|
-
};
|
|
3250
|
-
const closePipelineModal = () => {
|
|
3251
|
-
if (updateListMutation.isPending) return;
|
|
3252
|
-
setPipelineModalOpen(false);
|
|
3253
|
-
setSelectedBuildTemplateId(currentBuildTemplateId);
|
|
3254
|
-
};
|
|
3255
|
-
const handleChangePipeline = () => {
|
|
3256
|
-
if (isSameBuildTemplate) return;
|
|
3257
|
-
updateListMutation.mutate(
|
|
3258
|
-
{
|
|
3259
|
-
buildTemplateId: selectedBuildTemplateId,
|
|
3260
|
-
confirmBuildTemplateChange: true
|
|
3261
|
-
},
|
|
3262
|
-
{
|
|
3263
|
-
onSuccess: () => {
|
|
3264
|
-
setPipelineModalOpen(false);
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
);
|
|
3268
|
-
};
|
|
3269
|
-
const persistSubmittedStepConfig = (resourceId) => {
|
|
3270
|
-
if (!pendingStepRunConfig || pendingStepRunConfig.resourceId !== resourceId || !pendingStepRunConfig.capabilityKey) {
|
|
3271
|
-
return;
|
|
3272
|
-
}
|
|
3273
|
-
updateListConfigMutation.mutate({
|
|
3274
|
-
stepConfig: {
|
|
3275
|
-
[pendingStepRunConfig.capabilityKey]: pendingStepRunConfig.formStateAtSubmit
|
|
3276
|
-
}
|
|
3277
|
-
});
|
|
3278
|
-
};
|
|
3279
3463
|
return /* @__PURE__ */ jsxs(SubshellContentContainer, { children: [
|
|
3280
3464
|
/* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
3281
3465
|
/* @__PURE__ */ jsx(
|
|
@@ -3295,16 +3479,6 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3295
3479
|
] })
|
|
3296
3480
|
] }),
|
|
3297
3481
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
3298
|
-
/* @__PURE__ */ jsx(
|
|
3299
|
-
Button,
|
|
3300
|
-
{
|
|
3301
|
-
size: "xs",
|
|
3302
|
-
variant: "light",
|
|
3303
|
-
leftSection: /* @__PURE__ */ jsx(IconSwitchHorizontal, { size: 14 }),
|
|
3304
|
-
onClick: openPipelineModal,
|
|
3305
|
-
children: "Change pipeline"
|
|
3306
|
-
}
|
|
3307
|
-
),
|
|
3308
3482
|
/* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", onClick: handleCopyListCommand, style: { cursor: "pointer" }, children: [
|
|
3309
3483
|
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", children: list.id }),
|
|
3310
3484
|
/* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", "aria-label": "Copy list command", children: /* @__PURE__ */ jsx(IconCopy, { size: 14 }) })
|
|
@@ -3341,56 +3515,24 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3341
3515
|
recommendedStep: recommendedBuildStep,
|
|
3342
3516
|
onRunStep: openStepRun,
|
|
3343
3517
|
onRetryStep: openStepRun,
|
|
3344
|
-
onViewRuns: () =>
|
|
3518
|
+
onViewRuns: (resourceId) => {
|
|
3519
|
+
setRunsResourceFilter(resourceId);
|
|
3520
|
+
setActiveTab("runs");
|
|
3521
|
+
}
|
|
3345
3522
|
}
|
|
3346
3523
|
) }),
|
|
3347
|
-
/* @__PURE__ */ jsx(Tabs.Panel, { value: "runs", pt: "sm", children: /* @__PURE__ */ jsx(
|
|
3524
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "runs", pt: "sm", children: /* @__PURE__ */ jsx(
|
|
3525
|
+
WorkflowRunsPanel,
|
|
3526
|
+
{
|
|
3527
|
+
listId,
|
|
3528
|
+
title: "Runs",
|
|
3529
|
+
resourceFilter: runsResourceFilter,
|
|
3530
|
+
onClearResourceFilter: () => setRunsResourceFilter(null)
|
|
3531
|
+
}
|
|
3532
|
+
) })
|
|
3348
3533
|
] }) })
|
|
3349
3534
|
] }) }),
|
|
3350
3535
|
/* @__PURE__ */ jsx(ListMemberDrawer, { memberId, memberKind, listId, onClose: handleDrawerClose }),
|
|
3351
|
-
/* @__PURE__ */ jsx(
|
|
3352
|
-
CustomModal,
|
|
3353
|
-
{
|
|
3354
|
-
opened: pipelineModalOpen,
|
|
3355
|
-
onClose: closePipelineModal,
|
|
3356
|
-
size: "md",
|
|
3357
|
-
loading: updateListMutation.isPending,
|
|
3358
|
-
children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
3359
|
-
/* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
3360
|
-
/* @__PURE__ */ jsx(IconSwitchHorizontal, { size: 22 }),
|
|
3361
|
-
/* @__PURE__ */ jsx(Title, { order: 4, children: "Change build pipeline" })
|
|
3362
|
-
] }),
|
|
3363
|
-
/* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "yellow", variant: "light", children: /* @__PURE__ */ jsx(Text, { size: "sm", children: "Changing the pipeline replaces this list's build plan snapshot. Existing records stay in place, but future build steps on the Build tab will follow the newly selected pipeline." }) }),
|
|
3364
|
-
/* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
3365
|
-
/* @__PURE__ */ jsx(
|
|
3366
|
-
Select,
|
|
3367
|
-
{
|
|
3368
|
-
label: "Build Pipeline",
|
|
3369
|
-
data: BUILD_TEMPLATE_SELECT_OPTIONS2,
|
|
3370
|
-
value: selectedBuildTemplateId,
|
|
3371
|
-
onChange: (value) => setSelectedBuildTemplateId(value ?? currentBuildTemplateId),
|
|
3372
|
-
disabled: updateListMutation.isPending,
|
|
3373
|
-
required: true
|
|
3374
|
-
}
|
|
3375
|
-
),
|
|
3376
|
-
selectedBuildTemplate?.description ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: selectedBuildTemplate.description }) : null
|
|
3377
|
-
] }),
|
|
3378
|
-
/* @__PURE__ */ jsxs(Group, { justify: "flex-end", mt: "md", children: [
|
|
3379
|
-
/* @__PURE__ */ jsx(Button, { variant: "light", onClick: closePipelineModal, disabled: updateListMutation.isPending, children: "Cancel" }),
|
|
3380
|
-
/* @__PURE__ */ jsx(
|
|
3381
|
-
Button,
|
|
3382
|
-
{
|
|
3383
|
-
color: "yellow",
|
|
3384
|
-
loading: updateListMutation.isPending,
|
|
3385
|
-
disabled: isSameBuildTemplate,
|
|
3386
|
-
onClick: handleChangePipeline,
|
|
3387
|
-
children: "Confirm pipeline change"
|
|
3388
|
-
}
|
|
3389
|
-
)
|
|
3390
|
-
] })
|
|
3391
|
-
] })
|
|
3392
|
-
}
|
|
3393
|
-
),
|
|
3394
3536
|
/* @__PURE__ */ jsx(
|
|
3395
3537
|
CustomModal,
|
|
3396
3538
|
{
|
|
@@ -3429,8 +3571,7 @@ function LeadGenListDetailPage({ listId }) {
|
|
|
3429
3571
|
title: "Run build step",
|
|
3430
3572
|
description: "Run the selected bounded build workflow for this list.",
|
|
3431
3573
|
lockResourceSelection: true,
|
|
3432
|
-
onSubmitted: (
|
|
3433
|
-
persistSubmittedStepConfig(resourceId);
|
|
3574
|
+
onSubmitted: (_, executionId) => {
|
|
3434
3575
|
showSuccessNotification(`Workflow run started: ${executionId}`);
|
|
3435
3576
|
}
|
|
3436
3577
|
}
|
|
@@ -3795,4 +3936,4 @@ function LeadGenContactsPage() {
|
|
|
3795
3936
|
] }) });
|
|
3796
3937
|
}
|
|
3797
3938
|
|
|
3798
|
-
export {
|
|
3939
|
+
export { CompanyDetailModal, ContactDetailModal, LEAD_GEN_ITEMS, LEAD_GEN_ROUTE_LINKS, LeadGenCompaniesPage, LeadGenContactsPage, LeadGenListDetailPage, LeadGenListsPage, LeadGenOverviewPage, LeadGenRouteShell, LeadGenSidebar, LeadGenSidebarMiddle, LeadGenSidebarTop, ListBuilderIndexPage, ListBuilderPage, RunWorkflowModal, StepConfigForm, TabSection, formatDate, getEnrichmentColor, getEnrichmentStatus, getStateKeyColor, getStatusColor, leadGenManifest, useDeleteLists };
|