@xyne/workflow-ui 1.1.0 → 1.3.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/components/automations/CreateWorkflowDialog.d.ts +1 -1
- package/dist/components/automations/CreateWorkflowDialog.d.ts.map +1 -1
- package/dist/components/automations/CreateWorkflowDialog.js +14 -27
- package/dist/components/automations/CreateWorkflowDialog.js.map +1 -1
- package/dist/components/browser/EntryGrid.d.ts +3 -1
- package/dist/components/browser/EntryGrid.d.ts.map +1 -1
- package/dist/components/browser/EntryGrid.js +43 -38
- package/dist/components/browser/EntryGrid.js.map +1 -1
- package/dist/components/browser/EntryList.d.ts +3 -1
- package/dist/components/browser/EntryList.d.ts.map +1 -1
- package/dist/components/browser/EntryList.js +39 -35
- package/dist/components/browser/EntryList.js.map +1 -1
- package/dist/components/browser/MoveDialog.d.ts.map +1 -1
- package/dist/components/browser/MoveDialog.js +3 -1
- package/dist/components/browser/MoveDialog.js.map +1 -1
- package/dist/components/browser/NameDialog.d.ts.map +1 -1
- package/dist/components/browser/NameDialog.js +5 -2
- package/dist/components/browser/NameDialog.js.map +1 -1
- package/dist/components/browser/SearchField.js +1 -1
- package/dist/components/browser/SearchField.js.map +1 -1
- package/dist/components/browser/ViewToggle.js +5 -5
- package/dist/components/browser/ViewToggle.js.map +1 -1
- package/dist/components/builder/v3/ConditionEditorPanel.js +2 -2
- package/dist/components/builder/v3/ConditionEditorPanel.js.map +1 -1
- package/dist/components/builder/v3/DeleteStepDialog.js +1 -1
- package/dist/components/builder/v3/DeleteStepDialog.js.map +1 -1
- package/dist/components/builder/v3/DiscriminatedUnionEditor.js +1 -1
- package/dist/components/builder/v3/DiscriminatedUnionEditor.js.map +1 -1
- package/dist/components/builder/v3/EnhancedSchemaFormRenderer.js +1 -1
- package/dist/components/builder/v3/EnhancedSchemaFormRenderer.js.map +1 -1
- package/dist/components/builder/v3/InputSchemaBuilder.js +1 -1
- package/dist/components/builder/v3/InputSchemaBuilder.js.map +1 -1
- package/dist/components/builder/v3/SaveValidationDialog.js +1 -1
- package/dist/components/builder/v3/SaveValidationDialog.js.map +1 -1
- package/dist/components/builder/v3/StringArrayInput.js +1 -1
- package/dist/components/builder/v3/StringArrayInput.js.map +1 -1
- package/dist/components/builder/v3/SummaryDialog.js +1 -1
- package/dist/components/builder/v3/SummaryDialog.js.map +1 -1
- package/dist/components/builder/v3/SwitchCaseEditor.js +1 -1
- package/dist/components/builder/v3/SwitchCaseEditor.js.map +1 -1
- package/dist/components/builder/v3/VariableRefInput.js +1 -1
- package/dist/components/builder/v3/VariableRefInput.js.map +1 -1
- package/dist/components/dashboard/TriggerFormModal.js +1 -1
- package/dist/components/dashboard/TriggerFormModal.js.map +1 -1
- package/dist/components/execution/ApprovalReviewDisplay.d.ts.map +1 -1
- package/dist/components/execution/ApprovalReviewDisplay.js +5 -3
- package/dist/components/execution/ApprovalReviewDisplay.js.map +1 -1
- package/dist/components/execution/ApprovalsView.d.ts.map +1 -1
- package/dist/components/execution/ApprovalsView.js +144 -23
- package/dist/components/execution/ApprovalsView.js.map +1 -1
- package/dist/components/execution/PauseFormRenderer.d.ts.map +1 -1
- package/dist/components/execution/PauseFormRenderer.js +3 -2
- package/dist/components/execution/PauseFormRenderer.js.map +1 -1
- package/dist/components/execution/PauseInteractionPanel.js +1 -1
- package/dist/components/execution/PauseInteractionPanel.js.map +1 -1
- package/dist/components/execution/RerunDialog.js +1 -1
- package/dist/components/execution/RerunDialog.js.map +1 -1
- package/dist/components/execution/SidePanelShell.d.ts +3 -1
- package/dist/components/execution/SidePanelShell.d.ts.map +1 -1
- package/dist/components/execution/SidePanelShell.js +2 -2
- package/dist/components/execution/SidePanelShell.js.map +1 -1
- package/dist/components/execution/ValueEditor.js +21 -21
- package/dist/components/execution/ValueEditor.js.map +1 -1
- package/dist/components/execution/origin/OriginTrace.d.ts +6 -3
- package/dist/components/execution/origin/OriginTrace.d.ts.map +1 -1
- package/dist/components/execution/origin/OriginTrace.js +53 -12
- package/dist/components/execution/origin/OriginTrace.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/runs/RunsFilters.js +1 -1
- package/dist/components/runs/RunsFilters.js.map +1 -1
- package/dist/components/runs/RunsTable.d.ts +3 -1
- package/dist/components/runs/RunsTable.d.ts.map +1 -1
- package/dist/components/runs/RunsTable.js +18 -28
- package/dist/components/runs/RunsTable.js.map +1 -1
- package/dist/components/runs/RunsView.d.ts.map +1 -1
- package/dist/components/runs/RunsView.js +51 -3
- package/dist/components/runs/RunsView.js.map +1 -1
- package/dist/components/schema-form/AttachmentFieldInput.js +8 -8
- package/dist/components/schema-form/AttachmentFieldInput.js.map +1 -1
- package/dist/components/schema-form/SchemaFormRenderer.js +4 -4
- package/dist/components/schema-form/SchemaFormRenderer.js.map +1 -1
- package/dist/components/shared/AttachmentCard.d.ts.map +1 -1
- package/dist/components/shared/AttachmentCard.js +8 -1
- package/dist/components/shared/AttachmentCard.js.map +1 -1
- package/dist/components/shared/ChatPanel.d.ts +3 -1
- package/dist/components/shared/ChatPanel.d.ts.map +1 -1
- package/dist/components/shared/ChatPanel.js +12 -12
- package/dist/components/shared/ChatPanel.js.map +1 -1
- package/dist/components/shared/DocPreviewContext.d.ts +10 -0
- package/dist/components/shared/DocPreviewContext.d.ts.map +1 -0
- package/dist/components/shared/DocPreviewContext.js +12 -0
- package/dist/components/shared/DocPreviewContext.js.map +1 -0
- package/dist/components/shared/JsonView.d.ts +13 -0
- package/dist/components/shared/JsonView.d.ts.map +1 -0
- package/dist/components/shared/JsonView.js +59 -0
- package/dist/components/shared/JsonView.js.map +1 -0
- package/dist/components/shared/MarkdownEditor.d.ts.map +1 -1
- package/dist/components/shared/MarkdownEditor.js +10 -5
- package/dist/components/shared/MarkdownEditor.js.map +1 -1
- package/dist/components/shared/MarkdownView.d.ts +1 -1
- package/dist/components/shared/MarkdownView.d.ts.map +1 -1
- package/dist/components/shared/MarkdownView.js +33 -20
- package/dist/components/shared/MarkdownView.js.map +1 -1
- package/dist/components/shared/Select.d.ts +20 -0
- package/dist/components/shared/Select.d.ts.map +1 -0
- package/dist/components/shared/Select.js +50 -0
- package/dist/components/shared/Select.js.map +1 -0
- package/dist/components/shared/Toolbar.d.ts +17 -0
- package/dist/components/shared/Toolbar.d.ts.map +1 -0
- package/dist/components/shared/Toolbar.js +26 -0
- package/dist/components/shared/Toolbar.js.map +1 -0
- package/dist/components/workflows/WorkflowBrowser.d.ts +4 -1
- package/dist/components/workflows/WorkflowBrowser.d.ts.map +1 -1
- package/dist/components/workflows/WorkflowBrowser.js +123 -30
- package/dist/components/workflows/WorkflowBrowser.js.map +1 -1
- package/dist/components/workflows/WorkflowHome.d.ts +22 -0
- package/dist/components/workflows/WorkflowHome.d.ts.map +1 -0
- package/dist/components/workflows/WorkflowHome.js +33 -0
- package/dist/components/workflows/WorkflowHome.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
|
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import ReactMarkdown from 'react-markdown';
|
|
3
3
|
import remarkGfm from 'remark-gfm';
|
|
4
4
|
import { cn } from './cn.js';
|
|
5
|
+
import { JsonView, tryParseJson } from './JsonView.js';
|
|
5
6
|
/**
|
|
6
7
|
* Renders markdown (GitHub-flavored) to safe React nodes — no
|
|
7
8
|
* `dangerouslySetInnerHTML`. Used for the workflow summary in both the builder
|
|
@@ -9,27 +10,39 @@ import { cn } from './cn.js';
|
|
|
9
10
|
* it works without a Tailwind typography plugin.
|
|
10
11
|
*/
|
|
11
12
|
export function MarkdownView({ children, className, bare }) {
|
|
12
|
-
return (_jsx("div", { className: cn('wui-markdown min-w-0 max-w-full', !bare && 'text-[13px] leading-relaxed text-
|
|
13
|
-
h1: ({ node: _n, ...p }) => _jsx("h1", { className: "mb-2 mt-
|
|
14
|
-
h2: ({ node: _n, ...p }) => _jsx("h2", { className: "mb-
|
|
15
|
-
h3: ({ node: _n, ...p }) => _jsx("h3", { className: "mb-1 mt-
|
|
16
|
-
p: ({ node: _n, ...p }) => _jsx("p", { className: "my-2 first:mt-0 last:mb-0", ...p }),
|
|
17
|
-
ul: ({ node: _n, ...p }) => _jsx("ul", { className: "my-2 list-disc space-y-
|
|
18
|
-
ol: ({ node: _n, ...p }) => _jsx("ol", { className: "my-2 list-decimal space-y-
|
|
19
|
-
li: ({ node: _n, ...p }) => _jsx("li", { className: "pl-0.5", ...p }),
|
|
20
|
-
a: ({ node: _n, ...p }) => _jsx("a", { className: "text-
|
|
21
|
-
code: ({ node: _n, className: c, ...p }) => c?.includes('language-') ? (_jsx("code", { className: cn('font-mono text-[12px]', c), ...p })) : (_jsx("code", { className: "rounded bg-
|
|
22
|
-
// Block code:
|
|
13
|
+
return (_jsx("div", { className: cn('wui-markdown min-w-0 max-w-full', !bare && 'text-[13px] leading-relaxed text-[var(--wui-fg)]', className), children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: {
|
|
14
|
+
h1: ({ node: _n, ...p }) => _jsx("h1", { className: "mb-2.5 mt-4 border-b border-[var(--wui-border)] pb-1.5 text-[15px] font-semibold text-[var(--wui-fg)] first:mt-0", ...p }),
|
|
15
|
+
h2: ({ node: _n, ...p }) => _jsx("h2", { className: "mb-2 mt-4 border-b border-[var(--wui-border)] pb-1 text-[13.5px] font-semibold text-[var(--wui-fg)] first:mt-0", ...p }),
|
|
16
|
+
h3: ({ node: _n, ...p }) => _jsx("h3", { className: "mb-1.5 mt-3 text-[12.5px] font-semibold text-[var(--wui-fg)] first:mt-0", ...p }),
|
|
17
|
+
p: ({ node: _n, ...p }) => _jsx("p", { className: "my-2 leading-relaxed first:mt-0 last:mb-0", ...p }),
|
|
18
|
+
ul: ({ node: _n, ...p }) => _jsx("ul", { className: "my-2 list-disc space-y-1 pl-5 marker:text-[var(--wui-fg-muted)]", ...p }),
|
|
19
|
+
ol: ({ node: _n, ...p }) => _jsx("ol", { className: "my-2 list-decimal space-y-1 pl-5 marker:text-[var(--wui-fg-muted)]", ...p }),
|
|
20
|
+
li: ({ node: _n, ...p }) => _jsx("li", { className: "pl-0.5 leading-relaxed", ...p }),
|
|
21
|
+
a: ({ node: _n, ...p }) => _jsx("a", { className: "font-medium text-[var(--wui-primary)] underline underline-offset-2 hover:text-[var(--wui-primary-hover)]", target: "_blank", rel: "noreferrer noopener", ...p }),
|
|
22
|
+
code: ({ node: _n, className: c, ...p }) => c?.includes('language-') ? (_jsx("code", { className: cn('font-mono text-[12px]', c), ...p })) : (_jsx("code", { className: "rounded-[4px] border border-[var(--wui-border)] bg-[var(--wui-bg-muted)] px-1.5 py-0.5 font-mono text-[0.85em] text-[var(--wui-fg)]", ...p })),
|
|
23
|
+
// Block code: the <pre> owns the styling and neutralizes the inline-code
|
|
23
24
|
// chrome on its <code> child (an indented/no-language block otherwise gets
|
|
24
|
-
// the
|
|
25
|
-
pre: ({ node: _n, ...p }) =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
// the inline-code background, leaving boxes inside the block).
|
|
26
|
+
pre: ({ node: _n, children, ...p }) => {
|
|
27
|
+
// A fenced block whose body is JSON renders as a collapsible tree.
|
|
28
|
+
const child = Array.isArray(children) ? children[0] : children;
|
|
29
|
+
const raw = child && typeof child === 'object' && 'props' in child
|
|
30
|
+
? child.props?.children
|
|
31
|
+
: undefined;
|
|
32
|
+
const text = typeof raw === 'string' ? raw : Array.isArray(raw) ? raw.map(String).join('') : '';
|
|
33
|
+
const json = tryParseJson(text);
|
|
34
|
+
if (json !== undefined) {
|
|
35
|
+
return (_jsx("div", { className: "my-2.5 overflow-x-auto rounded-lg border border-[var(--wui-border)] bg-[var(--wui-bg-muted)] p-3", children: _jsx(JsonView, { data: json }) }));
|
|
36
|
+
}
|
|
37
|
+
return _jsx("pre", { className: "my-2.5 overflow-x-auto rounded-lg border border-[var(--wui-border)] bg-[var(--wui-bg-muted)] p-3.5 text-[12px] leading-relaxed text-[var(--wui-fg)] [&_code]:border-0 [&_code]:bg-transparent [&_code]:p-0 [&_code]:text-inherit [&_code]:ring-0", ...p, children: children });
|
|
38
|
+
},
|
|
39
|
+
blockquote: ({ node: _n, ...p }) => _jsx("blockquote", { className: "my-2.5 border-l-[3px] border-[var(--wui-border-strong)] pl-3.5 text-[var(--wui-fg-muted)]", ...p }),
|
|
40
|
+
// GitHub-style tables: rounded bordered frame, header fill, zebra rows,
|
|
41
|
+
// and cell separators — scrolls horizontally inside the frame when wide.
|
|
42
|
+
table: ({ node: _n, ...p }) => (_jsx("div", { className: "my-3 max-w-full overflow-hidden rounded-lg border border-[var(--wui-border)]", children: _jsx("div", { className: "max-w-full overflow-x-auto", children: _jsx("table", { className: "w-full border-collapse text-[12px] [&_tbody_tr:nth-child(2n)]:bg-[color-mix(in_srgb,var(--wui-fg)_4%,transparent)] [&_tbody_tr:last-child_td]:border-b-0", ...p }) }) })),
|
|
43
|
+
th: ({ node: _n, ...p }) => _jsx("th", { className: "border-b border-[var(--wui-border)] bg-[var(--wui-bg-muted)] px-3 py-2 text-left font-semibold text-[var(--wui-fg)] [&:not(:last-child)]:border-r [&:not(:last-child)]:border-[var(--wui-border)]", ...p }),
|
|
44
|
+
td: ({ node: _n, ...p }) => _jsx("td", { className: "border-b border-[var(--wui-border)] px-3 py-2 align-top text-[var(--wui-fg)] [&:not(:last-child)]:border-r [&:not(:last-child)]:border-[var(--wui-border)]", ...p }),
|
|
45
|
+
hr: ({ node: _n, ...p }) => _jsx("hr", { className: "my-4 border-t border-[var(--wui-border)]", ...p }),
|
|
33
46
|
}, children: children }) }));
|
|
34
47
|
}
|
|
35
48
|
//# sourceMappingURL=MarkdownView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownView.js","sourceRoot":"","sources":["../../../src/components/shared/MarkdownView.tsx"],"names":[],"mappings":";AAAA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"MarkdownView.js","sourceRoot":"","sources":["../../../src/components/shared/MarkdownView.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface SelectOption {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Fully custom dropdown — a styled trigger + a themed option menu. Replaces the
|
|
7
|
+
* native <select> so the open popup is styled too (the native popup can't be).
|
|
8
|
+
* Closes on outside-click / Escape; the chosen option is highlighted in brand.
|
|
9
|
+
*/
|
|
10
|
+
export declare function Select({ value, options, onChange, placeholder, disabled, compact, className, ariaLabel, }: {
|
|
11
|
+
value: string;
|
|
12
|
+
options: SelectOption[];
|
|
13
|
+
onChange: (value: string) => void;
|
|
14
|
+
placeholder?: string | undefined;
|
|
15
|
+
disabled?: boolean | undefined;
|
|
16
|
+
compact?: boolean | undefined;
|
|
17
|
+
className?: string | undefined;
|
|
18
|
+
ariaLabel?: string | undefined;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=Select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/shared/Select.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,OAAO,EACP,SAAS,EACT,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,+BA0GA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { cn } from './cn.js';
|
|
4
|
+
/**
|
|
5
|
+
* Fully custom dropdown — a styled trigger + a themed option menu. Replaces the
|
|
6
|
+
* native <select> so the open popup is styled too (the native popup can't be).
|
|
7
|
+
* Closes on outside-click / Escape; the chosen option is highlighted in brand.
|
|
8
|
+
*/
|
|
9
|
+
export function Select({ value, options, onChange, placeholder, disabled, compact, className, ariaLabel, }) {
|
|
10
|
+
const [open, setOpen] = useState(false);
|
|
11
|
+
const [openUp, setOpenUp] = useState(false);
|
|
12
|
+
const ref = useRef(null);
|
|
13
|
+
const current = options.find((o) => o.value === value);
|
|
14
|
+
const toggle = () => {
|
|
15
|
+
if (!open) {
|
|
16
|
+
// Flip the menu above the trigger when there isn't room below (e.g. the
|
|
17
|
+
// last field, where the menu would otherwise clip under the action bar).
|
|
18
|
+
const rect = ref.current?.getBoundingClientRect();
|
|
19
|
+
setOpenUp(!!rect && rect.bottom > window.innerHeight - 290);
|
|
20
|
+
}
|
|
21
|
+
setOpen((o) => !o);
|
|
22
|
+
};
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!open)
|
|
25
|
+
return undefined;
|
|
26
|
+
const onDoc = (e) => {
|
|
27
|
+
if (ref.current && !ref.current.contains(e.target))
|
|
28
|
+
setOpen(false);
|
|
29
|
+
};
|
|
30
|
+
const onKey = (e) => {
|
|
31
|
+
if (e.key === 'Escape')
|
|
32
|
+
setOpen(false);
|
|
33
|
+
};
|
|
34
|
+
document.addEventListener('mousedown', onDoc);
|
|
35
|
+
document.addEventListener('keydown', onKey);
|
|
36
|
+
return () => {
|
|
37
|
+
document.removeEventListener('mousedown', onDoc);
|
|
38
|
+
document.removeEventListener('keydown', onKey);
|
|
39
|
+
};
|
|
40
|
+
}, [open]);
|
|
41
|
+
return (_jsxs("div", { ref: ref, className: cn('relative', className), children: [_jsxs("button", { type: "button", disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": open, "aria-label": ariaLabel, onClick: toggle, className: cn('flex w-full items-center justify-between gap-1.5 rounded-[var(--wui-radius-sm)] border bg-[var(--wui-bg)] text-left text-[var(--wui-fg)] transition-colors', compact ? 'h-7 px-1.5 text-[11px]' : 'px-2.5 py-1.5 text-sm', 'disabled:cursor-not-allowed disabled:opacity-50', open
|
|
42
|
+
? 'border-[var(--wui-primary)] ring-1 ring-[var(--wui-primary)]'
|
|
43
|
+
: 'border-[var(--wui-border)] hover:border-[var(--wui-border-strong)]'), children: [_jsx("span", { className: cn('min-w-0 truncate', !current && 'text-[var(--wui-fg-muted)]'), children: current?.label ?? placeholder ?? 'Select…' }), _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: cn('shrink-0 text-[var(--wui-fg-muted)] transition-transform', compact ? 'h-3 w-3' : 'h-3.5 w-3.5', open && 'rotate-180'), children: _jsx("polyline", { points: "6 9 12 15 18 9" }) })] }), open && (_jsx("div", { role: "listbox", className: cn('absolute left-0 z-50 max-h-56 w-max min-w-full max-w-[280px] overflow-y-auto rounded-[var(--wui-radius-sm)] border border-[var(--wui-border)] bg-[color-mix(in_srgb,var(--wui-bg-muted)_96%,var(--wui-fg)_4%)] py-1 shadow-lg', openUp ? 'bottom-full mb-1' : 'top-full mt-1'), children: options.length === 0 ? (_jsx("div", { className: "px-2.5 py-1.5 text-[13px] text-[var(--wui-fg-muted)]", children: "No options" })) : (options.map((opt) => {
|
|
44
|
+
const selected = opt.value === value;
|
|
45
|
+
return (_jsxs("button", { type: "button", role: "option", "aria-selected": selected, onClick: () => { onChange(opt.value); setOpen(false); }, className: cn('flex w-full items-center justify-between gap-2 whitespace-nowrap px-2.5 py-1.5 text-left text-[13px] transition-colors', selected
|
|
46
|
+
? 'bg-[color-mix(in_srgb,var(--wui-primary)_12%,transparent)] font-medium text-[var(--wui-primary)]'
|
|
47
|
+
: 'text-[var(--wui-fg)] hover:bg-[color-mix(in_srgb,var(--wui-fg)_6%,transparent)]'), children: [_jsx("span", { className: "min-w-0 truncate", children: opt.label }), selected && (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", className: "h-3.5 w-3.5 shrink-0", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) }))] }, opt.value));
|
|
48
|
+
})) }))] }));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=Select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select.js","sourceRoot":"","sources":["../../../src/components/shared/Select.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, ReactNode, SelectHTMLAttributes } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Shared section toolbar — one consistent bar across the workflow tabs
|
|
4
|
+
* (Workflows / Executions / Approvals) so every tab reads as the same surface.
|
|
5
|
+
* `left` holds context (breadcrumb / label); `right` holds controls.
|
|
6
|
+
*/
|
|
7
|
+
export declare function SectionToolbar({ left, right, className, }: {
|
|
8
|
+
left?: ReactNode;
|
|
9
|
+
right?: ReactNode;
|
|
10
|
+
className?: string | undefined;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
12
|
+
/** Base styling shared by every compact toolbar control (h-8, one radius). */
|
|
13
|
+
export declare const toolbarControl: string;
|
|
14
|
+
export declare function ToolbarButton({ className, ...props }: ButtonHTMLAttributes<HTMLButtonElement>): import("react").JSX.Element;
|
|
15
|
+
export declare function ToolbarIconButton({ className, ...props }: ButtonHTMLAttributes<HTMLButtonElement>): import("react").JSX.Element;
|
|
16
|
+
export declare function ToolbarSelect({ className, children, ...props }: SelectHTMLAttributes<HTMLSelectElement>): import("react").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=Toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../../src/components/shared/Toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAGnF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,KAAK,EACL,SAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,+BAaA;AAED,8EAA8E;AAC9E,eAAO,MAAM,cAAc,QAKwB,CAAC;AAEpD,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,+BAEzC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,+BAEzC;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,+BAMzC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from './cn.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shared section toolbar — one consistent bar across the workflow tabs
|
|
5
|
+
* (Workflows / Executions / Approvals) so every tab reads as the same surface.
|
|
6
|
+
* `left` holds context (breadcrumb / label); `right` holds controls.
|
|
7
|
+
*/
|
|
8
|
+
export function SectionToolbar({ left, right, className, }) {
|
|
9
|
+
return (_jsxs("div", { className: cn('flex h-12 shrink-0 flex-wrap items-center justify-between gap-x-3 gap-y-2 px-5', 'border-b border-[var(--wui-border)]', className), children: [_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: left }), right ? _jsx("div", { className: "flex items-center gap-1.5", children: right }) : null] }));
|
|
10
|
+
}
|
|
11
|
+
/** Base styling shared by every compact toolbar control (h-8, one radius). */
|
|
12
|
+
export const toolbarControl = 'inline-flex h-7 items-center justify-center gap-1 rounded-[var(--wui-control-radius)] border border-[var(--wui-control-border)] ' +
|
|
13
|
+
'bg-[var(--wui-control-bg)] text-[12px] font-medium text-[var(--wui-control-fg)] transition-colors ' +
|
|
14
|
+
'hover:bg-[var(--wui-control-bg-hover)] ' +
|
|
15
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--wui-primary)_30%,transparent)] ' +
|
|
16
|
+
'disabled:cursor-not-allowed disabled:opacity-50';
|
|
17
|
+
export function ToolbarButton({ className, ...props }) {
|
|
18
|
+
return _jsx("button", { type: "button", className: cn(toolbarControl, 'px-2', className), ...props });
|
|
19
|
+
}
|
|
20
|
+
export function ToolbarIconButton({ className, ...props }) {
|
|
21
|
+
return _jsx("button", { type: "button", className: cn(toolbarControl, 'w-7', className), ...props });
|
|
22
|
+
}
|
|
23
|
+
export function ToolbarSelect({ className, children, ...props }) {
|
|
24
|
+
return (_jsx("select", { className: cn(toolbarControl, 'cursor-pointer px-2 pr-7', className), ...props, children: children }));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=Toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.js","sourceRoot":"","sources":["../../../src/components/shared/Toolbar.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE7B;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,IAAI,EACJ,KAAK,EACL,SAAS,GAKV;IACC,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,gFAAgF,EAChF,qCAAqC,EACrC,SAAS,CACV,aAED,cAAK,SAAS,EAAC,wCAAwC,YAAE,IAAI,GAAO,EACnE,KAAK,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,2BAA2B,YAAE,KAAK,GAAO,CAAC,CAAC,CAAC,IAAI,IACpE,CACP,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GACzB,kIAAkI;IAClI,oGAAoG;IACpG,yCAAyC;IACzC,6HAA6H;IAC7H,iDAAiD,CAAC;AAEpD,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACgC;IACxC,OAAO,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAChC,SAAS,EACT,GAAG,KAAK,EACgC;IACxC,OAAO,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACgC;IACxC,OAAO,CACL,iBAAQ,SAAS,EAAE,EAAE,CAAC,cAAc,EAAE,0BAA0B,EAAE,SAAS,CAAC,KAAM,KAAK,YACpF,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -8,7 +8,10 @@ export interface WorkflowBrowserProps {
|
|
|
8
8
|
path: FolderCrumb[];
|
|
9
9
|
onPathChange: (path: FolderCrumb[]) => void;
|
|
10
10
|
onToast?: (kind: 'success' | 'error', message: string) => void;
|
|
11
|
+
/** Suppress the embedded "waiting for approval" banner + inline approvals view
|
|
12
|
+
* (used when approvals live in a sibling tab, e.g. WorkflowHome). */
|
|
13
|
+
hideApprovals?: boolean;
|
|
11
14
|
className?: string;
|
|
12
15
|
}
|
|
13
|
-
export declare function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb, onPathChange, onToast, className, }: WorkflowBrowserProps): import("react").JSX.Element;
|
|
16
|
+
export declare function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb, onPathChange, onToast, hideApprovals, className, }: WorkflowBrowserProps): import("react").JSX.Element;
|
|
14
17
|
//# sourceMappingURL=WorkflowBrowser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowBrowser.d.ts","sourceRoot":"","sources":["../../../src/components/workflows/WorkflowBrowser.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WorkflowBrowser.d.ts","sourceRoot":"","sources":["../../../src/components/workflows/WorkflowBrowser.tsx"],"names":[],"mappings":"AAuKA,MAAM,WAAW,WAAW;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAEzD,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IACpE,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D;0EACsE;IACtE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,eAAe,CAAC,EAC9B,gBAAgB,EAChB,SAAS,EACT,IAAI,EAAE,UAAU,EAChB,YAAY,EACZ,OAAO,EACP,aAAqB,EACrB,SAAS,GACV,EAAE,oBAAoB,+BAumBtB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { AlertCircle, ArrowLeft, FolderPlus, Plus, RefreshCw, Workflow } from 'lucide-react';
|
|
3
|
+
import { AlertCircle, ArrowLeft, Clock, FolderPlus, MousePointerClick, Plus, RefreshCw, Webhook, Workflow, Zap } from 'lucide-react';
|
|
4
4
|
import { useWorkflowClient } from '../../hooks/use-workflow-client.js';
|
|
5
5
|
import { useApprovalCount } from '../../hooks/use-approval-count.js';
|
|
6
6
|
import { CreateWorkflowDialog } from '../automations/CreateWorkflowDialog.js';
|
|
@@ -11,6 +11,7 @@ import { FolderCard } from '../browser/FolderCard.js';
|
|
|
11
11
|
import { SearchField } from '../browser/SearchField.js';
|
|
12
12
|
import { ViewToggle } from '../browser/ViewToggle.js';
|
|
13
13
|
import { NameDialog } from '../browser/NameDialog.js';
|
|
14
|
+
import { ToolbarButton, ToolbarIconButton } from '../shared/Toolbar.js';
|
|
14
15
|
import { MoveDialog } from '../browser/MoveDialog.js';
|
|
15
16
|
import { TriggerFormModal } from '../dashboard/TriggerFormModal.js';
|
|
16
17
|
import { TagInput } from '../shared/TagInput.js';
|
|
@@ -18,16 +19,67 @@ import { TagFilter } from '../shared/TagFilter.js';
|
|
|
18
19
|
import { cn } from '../shared/cn.js';
|
|
19
20
|
// ─── Column definitions ───────────────────────────────────────────────────────
|
|
20
21
|
const WF_COLUMNS = [
|
|
21
|
-
{ key: 'status', header: 'Status', width: '
|
|
22
|
-
{ key: 'steps', header: 'Steps', width: '
|
|
23
|
-
{ key: 'trigger', header: 'Trigger', width: '
|
|
22
|
+
{ key: 'status', header: 'Status', width: '104px', render: (e) => _jsx(WorkflowStatusPill, { status: e.columns?.['status'] }) },
|
|
23
|
+
{ key: 'steps', header: 'Steps', width: '60px' },
|
|
24
|
+
{ key: 'trigger', header: 'Trigger', width: '116px', render: (e) => _jsx(TriggerCell, { type: e.columns?.['trigger'] }) },
|
|
25
|
+
{ key: 'lastRun', header: 'Last run', width: '116px', render: (e) => _jsx(LastRunCell, { status: e.columns?.['lastRunStatus'], at: e.columns?.['lastRunAt'] }) },
|
|
24
26
|
];
|
|
27
|
+
function timeAgo(ms) {
|
|
28
|
+
const sec = Math.floor(Math.max(0, Date.now() - ms) / 1000);
|
|
29
|
+
if (sec < 60)
|
|
30
|
+
return `${String(sec)}s ago`;
|
|
31
|
+
const min = Math.floor(sec / 60);
|
|
32
|
+
if (min < 60)
|
|
33
|
+
return `${String(min)}m ago`;
|
|
34
|
+
const hr = Math.floor(min / 60);
|
|
35
|
+
if (hr < 24)
|
|
36
|
+
return `${String(hr)}h ago`;
|
|
37
|
+
return `${String(Math.floor(hr / 24))}d ago`;
|
|
38
|
+
}
|
|
39
|
+
function LastRunCell({ status, at }) {
|
|
40
|
+
if (!status || !at) {
|
|
41
|
+
return _jsx("span", { className: "text-[12px] text-[var(--wui-fg-muted)]", children: "Never run" });
|
|
42
|
+
}
|
|
43
|
+
const s = status.toUpperCase();
|
|
44
|
+
const dot = s === 'COMPLETED' ? 'bg-[var(--wui-status-completed)]'
|
|
45
|
+
: s === 'FAILED' ? 'bg-[var(--wui-status-failed)]'
|
|
46
|
+
: s === 'RUNNING' ? 'bg-[var(--wui-status-running)]'
|
|
47
|
+
: s === 'EXTERNAL_WAIT' ? 'bg-[var(--wui-status-paused)]'
|
|
48
|
+
: 'bg-[var(--wui-fg-muted)]';
|
|
49
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-[12px] text-[var(--wui-fg-muted)]", title: new Date(Number(at)).toLocaleString(), children: [_jsx("span", { className: cn('h-1.5 w-1.5 shrink-0 rounded-full', dot) }), timeAgo(Number(at))] }));
|
|
50
|
+
}
|
|
51
|
+
function WorkflowStatusPill({ status }) {
|
|
52
|
+
const s = (status ?? '').toUpperCase();
|
|
53
|
+
const styles = {
|
|
54
|
+
ACTIVE: 'text-[var(--wui-status-completed)] bg-[color-mix(in_srgb,var(--wui-status-completed)_14%,transparent)]',
|
|
55
|
+
PENDING_APPROVAL: 'text-[var(--wui-status-paused)] bg-[color-mix(in_srgb,var(--wui-status-paused)_14%,transparent)]',
|
|
56
|
+
DRAFT: 'text-[var(--wui-fg-muted)] bg-[var(--wui-bg-muted)]',
|
|
57
|
+
};
|
|
58
|
+
const cls = styles[s] ?? 'text-[var(--wui-fg-muted)] bg-[var(--wui-bg-muted)]';
|
|
59
|
+
const label = s ? s.charAt(0) + s.slice(1).toLowerCase().replace(/_/g, ' ') : '—';
|
|
60
|
+
return (_jsx("span", { className: cn('inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium', cls), children: label }));
|
|
61
|
+
}
|
|
62
|
+
function TriggerCell({ type }) {
|
|
63
|
+
const t = (type ?? '').toUpperCase();
|
|
64
|
+
const map = {
|
|
65
|
+
MANUAL: { Icon: MousePointerClick, label: 'Manual' },
|
|
66
|
+
WEBHOOK: { Icon: Webhook, label: 'Webhook' },
|
|
67
|
+
CRON: { Icon: Clock, label: 'Schedule' },
|
|
68
|
+
SCHEDULE: { Icon: Clock, label: 'Schedule' },
|
|
69
|
+
EVENT: { Icon: Zap, label: 'Event' },
|
|
70
|
+
};
|
|
71
|
+
const m = map[t];
|
|
72
|
+
if (!m)
|
|
73
|
+
return _jsx("span", { className: "text-[12px] text-[var(--wui-fg-muted)]", children: type || '—' });
|
|
74
|
+
const { Icon, label } = m;
|
|
75
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-[12px] text-[var(--wui-fg-muted)]", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0", strokeWidth: 1.75 }), label] }));
|
|
76
|
+
}
|
|
25
77
|
// ─── Leading visual ───────────────────────────────────────────────────────────
|
|
26
78
|
const wfLeading = (entry, size) => {
|
|
27
79
|
if (entry.kind === 'folder')
|
|
28
80
|
return _jsx(FolderCard, { size: size });
|
|
29
81
|
const isSm = size === 'sm';
|
|
30
|
-
return (_jsx("div", { className: cn('flex items-center justify-center rounded-lg bg-
|
|
82
|
+
return (_jsx("div", { className: cn('flex items-center justify-center rounded-lg bg-[color-mix(in_srgb,var(--wui-primary)_12%,transparent)]', isSm ? 'h-9 w-9' : 'h-14 w-14'), children: _jsx(Workflow, { strokeWidth: 1.5, className: cn('text-[var(--wui-primary)]', isSm ? 'h-5 w-5' : 'h-8 w-8') }) }));
|
|
31
83
|
};
|
|
32
84
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
33
85
|
function parseMeta(raw) {
|
|
@@ -74,11 +126,11 @@ function folderToEntry(f, childCount) {
|
|
|
74
126
|
kind: 'folder',
|
|
75
127
|
id: f.id,
|
|
76
128
|
name: f.name,
|
|
77
|
-
caption: `${String(childCount)} item${childCount === 1 ? '' : 's'}
|
|
129
|
+
...(childCount > 0 ? { caption: `${String(childCount)} item${childCount === 1 ? '' : 's'}` } : {}),
|
|
78
130
|
};
|
|
79
131
|
}
|
|
80
132
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
81
|
-
export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb, onPathChange, onToast, className, }) {
|
|
133
|
+
export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb, onPathChange, onToast, hideApprovals = false, className, }) {
|
|
82
134
|
const client = useWorkflowClient();
|
|
83
135
|
const [view, setViewInternal] = useState(() => {
|
|
84
136
|
try {
|
|
@@ -116,6 +168,8 @@ export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb,
|
|
|
116
168
|
const [selectedTags, setSelectedTags] = useState([]);
|
|
117
169
|
/** Workflow whose tags are being edited. */
|
|
118
170
|
const [tagEditTarget, setTagEditTarget] = useState(null);
|
|
171
|
+
const [deleteTarget, setDeleteTarget] = useState(null);
|
|
172
|
+
const [lastRunByWorkflow, setLastRunByWorkflow] = useState({});
|
|
119
173
|
const [showCreateDialog, setShowCreateDialog] = useState(false);
|
|
120
174
|
const [showApprovals, setShowApprovals] = useState(false);
|
|
121
175
|
const polledCount = useApprovalCount();
|
|
@@ -149,6 +203,30 @@ export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb,
|
|
|
149
203
|
setLoading(false); });
|
|
150
204
|
return () => { cancelled = true; };
|
|
151
205
|
}, [currentFolderId, reloadKey]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
206
|
+
// Most-recent execution per workflow in this folder — drives the "Last run" column.
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
if (!currentFolderId) {
|
|
209
|
+
setLastRunByWorkflow({});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
let cancelled = false;
|
|
213
|
+
void client.executions
|
|
214
|
+
.list({ folderId: currentFolderId, limit: 300 })
|
|
215
|
+
.then((res) => {
|
|
216
|
+
if (cancelled)
|
|
217
|
+
return;
|
|
218
|
+
const map = {};
|
|
219
|
+
for (const ex of res.items) {
|
|
220
|
+
// list is newest-first, so the first hit per workflow is its latest run.
|
|
221
|
+
if (!map[ex.workflowId]) {
|
|
222
|
+
map[ex.workflowId] = { status: ex.status, createdAt: new Date(ex.createdAt).getTime() };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
setLastRunByWorkflow(map);
|
|
226
|
+
})
|
|
227
|
+
.catch(() => { });
|
|
228
|
+
return () => { cancelled = true; };
|
|
229
|
+
}, [currentFolderId, reloadKey]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
152
230
|
const childFolders = allFolders.filter((f) => currentFolderId ? f.parentId === currentFolderId : !f.parentId);
|
|
153
231
|
const itemCount = (id) => {
|
|
154
232
|
const subfolders = allFolders.filter((f) => f.parentId === id).length;
|
|
@@ -157,7 +235,13 @@ export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb,
|
|
|
157
235
|
};
|
|
158
236
|
const allEntries = [
|
|
159
237
|
...childFolders.map((f) => folderToEntry(f, itemCount(f.id))),
|
|
160
|
-
...(isAtRoot ? [] : workflows.map(
|
|
238
|
+
...(isAtRoot ? [] : workflows.map((wf) => {
|
|
239
|
+
const e = workflowToEntry(wf);
|
|
240
|
+
const lr = lastRunByWorkflow[wf.id];
|
|
241
|
+
return lr
|
|
242
|
+
? { ...e, columns: { ...e.columns, lastRunStatus: lr.status, lastRunAt: String(lr.createdAt) } }
|
|
243
|
+
: e;
|
|
244
|
+
})),
|
|
161
245
|
];
|
|
162
246
|
// Tags present in this folder's workflows — drives the filter selector.
|
|
163
247
|
const availableTags = [
|
|
@@ -262,19 +346,22 @@ export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb,
|
|
|
262
346
|
onToast?.('error', err instanceof Error ? err.message : 'Could not update tags');
|
|
263
347
|
}
|
|
264
348
|
};
|
|
265
|
-
const handleDelete =
|
|
266
|
-
if (entry.kind === 'folder')
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
349
|
+
const handleDelete = (entry) => {
|
|
350
|
+
if (entry.kind === 'folder')
|
|
351
|
+
setDeleteTarget(entry);
|
|
352
|
+
};
|
|
353
|
+
const confirmDelete = async () => {
|
|
354
|
+
const entry = deleteTarget;
|
|
355
|
+
if (!entry)
|
|
356
|
+
return;
|
|
357
|
+
setDeleteTarget(null);
|
|
358
|
+
try {
|
|
359
|
+
await client.folders.delete(entry.id);
|
|
360
|
+
onToast?.('success', `Deleted "${entry.name}"`);
|
|
361
|
+
refresh();
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
onToast?.('error', err instanceof Error ? err.message : 'Could not delete folder');
|
|
278
365
|
}
|
|
279
366
|
};
|
|
280
367
|
const triggerWorkflow = async (id, name, payload) => {
|
|
@@ -363,28 +450,34 @@ export function WorkflowBrowser({ onSelectWorkflow, onViewRun, path: breadcrumb,
|
|
|
363
450
|
onSelectWorkflow(wf.id, breadcrumb);
|
|
364
451
|
};
|
|
365
452
|
// ── Render ──────────────────────────────────────────────────────────────────
|
|
366
|
-
return (_jsxs("div", { className: cn('relative flex h-full flex-col', className), children: [
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
453
|
+
return (_jsxs("div", { className: cn('relative flex h-full flex-col', className), children: [_jsx("div", { className: "flex h-12 shrink-0 items-center border-b border-[var(--wui-border)] px-5", children: _jsxs("div", { className: "mx-auto flex w-full max-w-7xl items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 overflow-hidden", children: [(showApprovals || !isAtRoot) && (_jsx("button", { type: "button", "aria-label": "Up one level", onClick: showApprovals ? () => { setShowApprovals(false); } : goUp, className: "grid h-7 w-7 place-items-center rounded-md text-[var(--wui-fg-muted)] transition hover:bg-[var(--wui-bg-muted)] hover:text-[var(--wui-fg)]", children: _jsx(ArrowLeft, { className: "h-3.5 w-3.5", "aria-hidden": true, strokeWidth: 1.75 }) })), showApprovals ? (_jsxs("nav", { className: "flex min-w-0 items-center gap-1 text-[13px] text-muted-foreground", children: [_jsx("button", { type: "button", onClick: () => { setShowApprovals(false); }, className: "rounded-md px-1.5 py-0.5 transition hover:bg-secondary hover:text-foreground", children: "Workflows" }), _jsx("span", { className: "select-none text-muted-foreground/60", children: "\u203A" }), _jsx("span", { className: "cursor-default px-1.5 py-0.5 font-medium text-foreground", children: "Pending Approvals" })] })) : isAtRoot ? (_jsx("span", { className: "text-[13px] font-medium text-[var(--wui-fg)]", children: "Workflows" })) : (_jsxs("nav", { className: "flex min-w-0 items-center gap-1 text-[13px] text-muted-foreground", children: [_jsx("button", { type: "button", onClick: goRoot, className: "rounded-md px-1.5 py-0.5 transition hover:bg-secondary hover:text-foreground", children: "Workflows" }), breadcrumb.map((seg, i) => {
|
|
454
|
+
const isLast = i === breadcrumb.length - 1;
|
|
455
|
+
return (_jsxs("span", { className: "flex min-w-0 items-center gap-1", children: [_jsx("span", { className: "select-none text-muted-foreground/60", children: "\u203A" }), _jsx("button", { type: "button", onClick: () => (isLast ? undefined : goToIndex(i)), className: cn('max-w-[24ch] truncate rounded-md px-1.5 py-0.5 transition', isLast
|
|
456
|
+
? 'cursor-default font-medium text-foreground'
|
|
457
|
+
: 'hover:bg-secondary hover:text-foreground'), title: seg.name, children: seg.name })] }, seg.id));
|
|
458
|
+
})] }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [!showApprovals && !isAtRoot && (_jsxs(ToolbarButton, { onClick: () => { setShowCreateDialog(true); }, children: [_jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.75 }), "Create workflow"] })), !showApprovals && (_jsxs(ToolbarButton, { onClick: () => { setDialog('folder'); }, children: [_jsx(FolderPlus, { className: "h-3.5 w-3.5", strokeWidth: 1.75 }), "New folder"] })), !showApprovals && (_jsx(ToolbarIconButton, { onClick: refresh, disabled: loading, "aria-label": "Refresh", title: "Refresh", children: _jsx(RefreshCw, { className: cn('h-3.5 w-3.5', loading && 'animate-spin'), strokeWidth: 1.75 }) })), !showApprovals && _jsx(ViewToggle, { value: view, onChange: setView }), !showApprovals && (_jsx(SearchField, { value: query, onChange: setQuery, className: "w-56", ariaLabel: "Search workflows", placeholder: "Search by name" }))] })] }) }), selectedIds.size > 0 && (_jsx("div", { className: "pointer-events-none absolute bottom-6 left-0 right-0 z-20 flex justify-center", children: _jsxs("div", { className: "pointer-events-auto flex items-center gap-2 rounded-full border border-border bg-surface-elevated px-4 py-2 shadow-lg backdrop-blur-md", children: [_jsxs("span", { className: "text-[13px] font-medium text-foreground", children: [selectedIds.size, " item", selectedIds.size === 1 ? '' : 's', " selected"] }), _jsx("div", { className: "mx-1 h-4 w-px bg-border" }), _jsx("button", { type: "button", onClick: () => { setMoveEntries(allEntries.filter((e) => selectedIds.has(e.id))); }, className: "inline-flex h-7 items-center rounded-full bg-[var(--wui-primary)] px-3 text-[12px] font-medium text-[var(--wui-primary-fg)] transition-colors hover:bg-[var(--wui-primary-hover)]", children: "Move selected" }), _jsx("button", { type: "button", onClick: clearSelection, className: "text-[12px] text-muted-foreground transition hover:text-foreground", children: "Clear" })] }) })), showApprovals && (_jsx("div", { className: "flex-1 overflow-hidden", children: _jsx(ApprovalsView, { className: "h-full", onCountChange: setLocalCount, ...(onViewRun
|
|
372
459
|
? {
|
|
373
460
|
onViewRun: (executionId, workflowName) => {
|
|
374
461
|
setShowApprovals(false);
|
|
375
462
|
onViewRun(executionId, workflowName);
|
|
376
463
|
},
|
|
377
464
|
}
|
|
378
|
-
: {}) }) })), _jsx("main", { ref: mainRef, className: cn('relative flex-1 overflow-
|
|
465
|
+
: {}) }) })), _jsx("main", { ref: mainRef, className: cn('relative flex flex-1 flex-col overflow-hidden px-5 py-5', showApprovals && 'hidden'), children: _jsx("div", { className: "mx-auto flex h-full w-full min-h-0 max-w-7xl flex-col", children: false ? null : (_jsxs(_Fragment, { children: [!hideApprovals && approvalCount > 0 && (_jsxs("button", { type: "button", onClick: () => { setShowApprovals(true); }, className: "mb-4 flex w-full items-center gap-3 rounded-xl border border-orange-200 bg-orange-50 px-4 py-3 text-left transition hover:bg-orange-100 dark:border-orange-800 dark:bg-orange-950/30 dark:hover:bg-orange-950/50", children: [_jsx(AlertCircle, { className: "h-4 w-4 shrink-0 text-orange-500", strokeWidth: 1.75 }), _jsxs("span", { className: "flex-1 text-[13px] font-medium text-orange-800 dark:text-orange-300", children: [approvalCount, " workflow", approvalCount === 1 ? '' : 's', " waiting for approval"] }), _jsx("span", { className: "text-[12px] text-orange-600 dark:text-orange-400", children: "Review \u2192" })] })), _jsxs("div", { className: "mb-3 flex shrink-0 items-center justify-between gap-2", children: [_jsx("p", { className: "text-[12px] text-muted-foreground", children: countText }), _jsx(TagFilter, { tags: availableTags, selected: selectedTags, onChange: setSelectedTags })] }), _jsx("div", { className: "min-h-0 flex-1", children: entries.length === 0 && !loading ? (_jsx(EmptyPane, { isRoot: isAtRoot })) : view === 'grid' ? (_jsx(EntryGrid, { entries: entries, renderLeading: wfLeading, onOpen: openEntry, onOpenEditor: (e) => { onSelectWorkflow(e.id, breadcrumb); }, onEditTags: openTagEditor, onRename: (e, name) => { void handleRename(e, name); }, onDelete: (e) => { void handleDelete(e); }, onMove: (e) => { setMoveEntries([e]); }, selectedIds: selectedIds, onToggleSelect: toggleSelect, scrollParentRef: mainRef })) : (_jsx(EntryList, { entries: entries, columns: isAtRoot ? [] : WF_COLUMNS, renderLeading: wfLeading, onOpen: openEntry, onOpenEditor: (e) => { onSelectWorkflow(e.id, breadcrumb); }, onEditTags: openTagEditor, onRename: (e, name) => { void handleRename(e, name); }, onDelete: (e) => { void handleDelete(e); }, onMove: (e) => { setMoveEntries([e]); }, selectedIds: selectedIds, onToggleSelect: toggleSelect, scrollParentRef: mainRef })) })] })) }) }), _jsx(NameDialog, { open: dialog === 'folder', title: "New folder", description: currentFolderId
|
|
379
466
|
? 'Adds a subfolder inside the current folder.'
|
|
380
|
-
: 'Adds a top-level folder for organising workflows.', label: "Folder name", placeholder: "e.g. Notifications", helper: "Up to 255 characters.", submitLabel: "Create folder", onSubmit: submitNewFolder, onClose: () => { setDialog(null); } }), showCreateDialog && (_jsx(CreateWorkflowDialog, { folders: allFolders, defaultFolderId: currentFolderId ?? undefined, onCreateFolder: handleCreateFolder, onCreated: handleWorkflowCreated, onClose: () => { setShowCreateDialog(false); } })), tagEditTarget && (_jsx(TagEditDialog, { target: tagEditTarget, suggestions: availableTags, onSave: (tags) => { void saveTags(tagEditTarget.id, tags); }, onClose: () => { setTagEditTarget(null); } })), runTarget && (_jsx(TriggerFormModal, { inputSchema: runTarget.inputSchema, workflowName: runTarget.name, onSubmit: (payload) => triggerWorkflow(runTarget.id, runTarget.name, payload), onClose: () => { setRunTarget(null); } })), moveEntries && moveEntries.length > 0 && (_jsx(MoveDialog, { entries: moveEntries, folders: allFolders, currentParentId: moveEntries.length === 1 && moveEntries[0].kind === 'folder'
|
|
467
|
+
: 'Adds a top-level folder for organising workflows.', label: "Folder name", placeholder: "e.g. Notifications", helper: "Up to 255 characters.", submitLabel: "Create folder", onSubmit: submitNewFolder, onClose: () => { setDialog(null); } }), showCreateDialog && (_jsx(CreateWorkflowDialog, { folders: allFolders, defaultFolderId: currentFolderId ?? undefined, onCreateFolder: handleCreateFolder, onCreated: handleWorkflowCreated, onClose: () => { setShowCreateDialog(false); } })), tagEditTarget && (_jsx(TagEditDialog, { target: tagEditTarget, suggestions: availableTags, onSave: (tags) => { void saveTags(tagEditTarget.id, tags); }, onClose: () => { setTagEditTarget(null); } })), deleteTarget && (_jsx(ConfirmDialog, { title: `Delete folder "${deleteTarget.name}"?`, message: "This permanently deletes the folder. This can't be undone.", confirmLabel: "Delete folder", danger: true, onConfirm: () => { void confirmDelete(); }, onClose: () => { setDeleteTarget(null); } })), runTarget && (_jsx(TriggerFormModal, { inputSchema: runTarget.inputSchema, workflowName: runTarget.name, onSubmit: (payload) => triggerWorkflow(runTarget.id, runTarget.name, payload), onClose: () => { setRunTarget(null); } })), moveEntries && moveEntries.length > 0 && (_jsx(MoveDialog, { entries: moveEntries, folders: allFolders, currentParentId: moveEntries.length === 1 && moveEntries[0].kind === 'folder'
|
|
381
468
|
? (allFolders.find((f) => f.id === moveEntries[0].id)?.parentId ?? null)
|
|
382
469
|
: currentFolderId, onMove: (targetId) => { void handleMoveConfirm(moveEntries, targetId); }, onClose: () => { setMoveEntries(null); } }))] }));
|
|
383
470
|
}
|
|
384
471
|
// ─── Tag editor dialog ─────────────────────────────────────────────────────────
|
|
385
472
|
function TagEditDialog({ target, suggestions, onSave, onClose, }) {
|
|
386
473
|
const [tags, setTags] = useState(target.tags);
|
|
387
|
-
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/
|
|
474
|
+
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: onClose }), _jsxs("div", { className: "relative z-10 w-full max-w-md rounded-xl border border-[var(--wui-border)] bg-[var(--wui-surface)] shadow-xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-[var(--wui-border)] px-5 py-3.5", children: [_jsxs("h3", { className: "truncate text-sm font-semibold text-[var(--wui-fg)]", title: target.name, children: ["Teams \u00B7 ", target.name] }), _jsx("button", { onClick: onClose, "aria-label": "Close", className: "grid h-6 w-6 place-items-center rounded-md text-[var(--wui-fg-muted)] hover:bg-[var(--wui-bg-muted)] hover:text-[var(--wui-fg)]", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [_jsx("path", { d: "M18 6 6 18" }), _jsx("path", { d: "m6 6 12 12" })] }) })] }), _jsx("div", { className: "px-5 py-4", children: _jsx(TagInput, { value: tags, onChange: setTags, suggestions: suggestions, placeholder: "Add a team \u2014 Enter to confirm" }) }), _jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-[var(--wui-border)] px-5 py-3", children: [_jsx("button", { onClick: onClose, className: "rounded-md border border-[var(--wui-border)] px-3.5 py-1.5 text-[13px] font-medium text-[var(--wui-fg-muted)] hover:bg-[var(--wui-bg-muted)]", children: "Cancel" }), _jsx("button", { onClick: () => onSave(tags), className: "rounded-md bg-[var(--wui-primary)] px-3.5 py-1.5 text-[13px] font-semibold text-[var(--wui-primary-fg)] hover:bg-[var(--wui-primary-hover)]", children: "Save tags" })] })] })] }));
|
|
475
|
+
}
|
|
476
|
+
// ─── Confirm dialog ───────────────────────────────────────────────────────────
|
|
477
|
+
function ConfirmDialog({ title, message, confirmLabel, danger, onConfirm, onClose, }) {
|
|
478
|
+
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: onClose }), _jsxs("div", { className: "relative z-10 w-full max-w-sm rounded-xl border border-[var(--wui-border)] bg-[var(--wui-surface)] shadow-xl", children: [_jsxs("div", { className: "px-5 py-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[var(--wui-fg)]", children: title }), message ? (_jsx("p", { className: "mt-1.5 text-[13px] leading-relaxed text-[var(--wui-fg-muted)]", children: message })) : null] }), _jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-[var(--wui-border)] px-5 py-3", children: [_jsx("button", { onClick: onClose, className: "rounded-md border border-[var(--wui-border)] px-3.5 py-1.5 text-[13px] font-medium text-[var(--wui-fg-muted)] transition-colors hover:bg-[var(--wui-bg-muted)]", children: "Cancel" }), _jsx("button", { onClick: onConfirm, className: cn('rounded-md px-3.5 py-1.5 text-[13px] font-semibold text-white transition-colors', danger
|
|
479
|
+
? 'bg-[var(--wui-status-failed)] hover:opacity-90'
|
|
480
|
+
: 'bg-[var(--wui-primary)] hover:bg-[var(--wui-primary-hover)]'), children: confirmLabel })] })] })] }));
|
|
388
481
|
}
|
|
389
482
|
// ─── Empty state ──────────────────────────────────────────────────────────────
|
|
390
483
|
function EmptyPane({ isRoot }) {
|