@motiadev/workbench 0.3.1-beta.88-041205 → 0.3.1-beta.88-490801
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/src/App.js +16 -1
- package/dist/src/components/endpoints/endpoint-call.js +1 -1
- package/dist/src/components/endpoints/json-editor.js +5 -7
- package/dist/src/components/flow/flow-tab-menu-item.js +1 -1
- package/dist/src/components/header/header.js +1 -1
- package/dist/src/components/observability/traces-groups.js +1 -1
- package/dist/src/publicComponents/base-node/base-handle.d.ts +0 -1
- package/dist/src/publicComponents/base-node/base-handle.js +1 -1
- package/dist/src/publicComponents/base-node/base-node.js +1 -1
- package/dist/src/publicComponents/event-node.d.ts +1 -1
- package/dist/tsconfig.app.tsbuildinfo +1 -1
- package/package.json +3 -3
package/dist/src/App.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CollapsiblePanel, CollapsiblePanelGroup, TabsContent, TabsList, TabsTrigger } from '@motiadev/ui';
|
|
3
3
|
import { ReactFlowProvider } from '@xyflow/react';
|
|
4
|
+
import { analytics } from '@/lib/analytics';
|
|
4
5
|
import { File, GanttChart, Link2, LogsIcon } from 'lucide-react';
|
|
6
|
+
import React from 'react';
|
|
5
7
|
import { EndpointsPage } from './components/endpoints/endpoints-page';
|
|
6
8
|
import { FlowPage } from './components/flow/flow-page';
|
|
7
9
|
import { FlowTabMenuItem } from './components/flow/flow-tab-menu-item';
|
|
@@ -11,9 +13,22 @@ import { TracesPage } from './components/observability/traces-page';
|
|
|
11
13
|
import { APP_SIDEBAR_CONTAINER_ID } from './components/sidebar/sidebar';
|
|
12
14
|
import { StatesPage } from './components/states/states-page';
|
|
13
15
|
import { useTabsStore } from './stores/use-tabs-store';
|
|
16
|
+
var TabLocation;
|
|
17
|
+
(function (TabLocation) {
|
|
18
|
+
TabLocation["TOP"] = "top";
|
|
19
|
+
TabLocation["BOTTOM"] = "bottom";
|
|
20
|
+
})(TabLocation || (TabLocation = {}));
|
|
14
21
|
export const App = () => {
|
|
15
22
|
const tab = useTabsStore((state) => state.tab);
|
|
16
23
|
const setTopTab = useTabsStore((state) => state.setTopTab);
|
|
17
24
|
const setBottomTab = useTabsStore((state) => state.setBottomTab);
|
|
18
|
-
|
|
25
|
+
const tabChangeCallbacks = React.useMemo(() => ({
|
|
26
|
+
[TabLocation.TOP]: setTopTab,
|
|
27
|
+
[TabLocation.BOTTOM]: setBottomTab,
|
|
28
|
+
}), [setTopTab, setBottomTab]);
|
|
29
|
+
const onTabChange = React.useCallback((location) => (newTab) => {
|
|
30
|
+
analytics.track(`${location} tab changed`, { [`new.${location}`]: newTab, tab });
|
|
31
|
+
tabChangeCallbacks[location](newTab);
|
|
32
|
+
}, [tabChangeCallbacks]);
|
|
33
|
+
return (_jsxs("div", { className: "grid grid-rows-[auto_1fr] grid-cols-[1fr_auto] bg-background text-foreground h-screen", children: [_jsx("div", { className: "col-span-2", children: _jsx(Header, {}) }), _jsx("main", { className: "m-2 overflow-hidden", role: "main", children: _jsxs(CollapsiblePanelGroup, { autoSaveId: "app-panel", direction: "vertical", className: "gap-1 h-full", "aria-label": "Workbench panels", children: [_jsxs(CollapsiblePanel, { id: "top-panel", variant: 'tabs', defaultTab: tab.top, onTabChange: onTabChange(TabLocation.TOP), header: _jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "flow", "data-testid": "flows-link", children: _jsx(FlowTabMenuItem, {}) }), _jsxs(TabsTrigger, { value: "endpoint", "data-testid": "endpoints-link", children: [_jsx(Link2, {}), "Endpoint"] })] }), children: [_jsx(TabsContent, { value: "flow", className: "h-full", asChild: true, children: _jsx(ReactFlowProvider, { children: _jsx(FlowPage, {}) }) }), _jsx(TabsContent, { value: "endpoint", asChild: true, children: _jsx(EndpointsPage, {}) })] }), _jsxs(CollapsiblePanel, { id: "bottom-panel", variant: 'tabs', defaultTab: tab.bottom, onTabChange: onTabChange(TabLocation.BOTTOM), header: _jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "tracing", "data-testid": "traces-link", children: [_jsx(GanttChart, {}), " Tracing"] }), _jsxs(TabsTrigger, { value: "logs", "data-testid": "logs-link", children: [_jsx(LogsIcon, {}), "Logs"] }), _jsxs(TabsTrigger, { value: "states", "data-testid": "states-link", children: [_jsx(File, {}), "States"] })] }), children: [_jsx(TabsContent, { value: "tracing", className: "max-h-fit", asChild: true, children: _jsx(TracesPage, {}) }), _jsx(TabsContent, { value: "logs", asChild: true, children: _jsx(LogsPage, {}) }), _jsx(TabsContent, { value: "states", asChild: true, children: _jsx(StatesPage, {}) })] })] }) }), _jsx("div", { id: APP_SIDEBAR_CONTAINER_ID })] }));
|
|
19
34
|
};
|
|
@@ -69,7 +69,7 @@ export const EndpointCall = ({ endpoint, onClose }) => {
|
|
|
69
69
|
icon: _jsx(X, { className: "cursor-pointer w-4 h-4", onClick: onClose }),
|
|
70
70
|
onClick: onClose,
|
|
71
71
|
},
|
|
72
|
-
], children: [endpoint.description && (_jsx("div", { className: "rounded-lg border p-4 font-medium text-muted-foreground", children: endpoint.description })), !!pathParams.length && (_jsx(Panel, { title: "Path params", size: "sm", children: _jsx("table", { children: pathParams.map((param) => (_jsxs("tr", { children: [_jsx("td", { className: "flex flex-col font-bold leading-[36px]", children: param }), _jsx("td", { className: "w-2/3 pl-4", children: _jsx(Input, { className: "w-full", value: pathParamsValues[param], onChange: (e) => onPathParamChange(param, e.target.value) }) })] }, param))) }) })), !!endpoint.queryParams?.length && (_jsx(Panel, { title: "Query params", size: "sm", children: _jsx("table", { children: endpoint.queryParams.map((param) => (_jsxs("tr", { children: [_jsxs("td", { className: "flex flex-col", children: [_jsx("span", { className: "font-bold", children: param.name }), _jsx("span", { className: "text-md text-muted-foreground", children: param.description })] }), _jsx("td", { className: "w-2/3 pl-4", children: _jsx(Input, { className: "w-full", value: queryParamsValues[param.name], onChange: (e) => onQueryParamChange(param.name, e.target.value) }) })] }, param.name))) }) })), shouldHaveBody && (_jsx(Panel, { title: "Body", size: "sm", contentClassName: "p-0", children: _jsx(JsonEditor, { value: body, schema: endpoint.bodySchema, onChange: setBody, onValidate: setIsBodyValid }) })), _jsxs(Button, { className: "w-fit", onClick: handleRequest, variant: "accent", "data-testid": "endpoint-play-button", disabled: isRequestLoading || !isPlayEnabled, children: [isRequestLoading ? _jsx(Loader2, { className: "animate-spin" }) : _jsx(Play, {}), " Play"] }), _jsx(EndpointResponse, { responseCode: responseCode, responseBody: responseBody, executionTime: executionTime }), _jsx(EndpointResponseSchema, { items: Object.entries(endpoint?.responseSchema ?? {}).map(([status, schema]) => ({
|
|
72
|
+
], children: [endpoint.description && (_jsx("div", { className: "rounded-lg border p-4 font-medium text-muted-foreground", children: endpoint.description })), !!pathParams.length && (_jsx(Panel, { title: "Path params", size: "sm", children: _jsx("table", { children: pathParams.map((param) => (_jsxs("tr", { children: [_jsx("td", { className: "flex flex-col font-bold leading-[36px]", children: param }), _jsx("td", { className: "w-2/3 pl-4", children: _jsx(Input, { className: "w-full", value: pathParamsValues[param], onChange: (e) => onPathParamChange(param, e.target.value) }) })] }, param))) }) })), !!endpoint.queryParams?.length && (_jsx(Panel, { title: "Query params", size: "sm", children: _jsx("table", { children: endpoint.queryParams.map((param) => (_jsxs("tr", { children: [_jsxs("td", { className: "flex flex-col justify-start", children: [_jsx("span", { className: "font-bold", children: param.name }), _jsx("span", { className: "text-md text-muted-foreground", children: param.description })] }), _jsx("td", { className: "w-2/3 pl-4 align-top", children: _jsx(Input, { className: "w-full", value: queryParamsValues[param.name], onChange: (e) => onQueryParamChange(param.name, e.target.value) }) })] }, param.name))) }) })), shouldHaveBody && (_jsx(Panel, { title: "Body", size: "sm", contentClassName: "p-0", "data-testid": "endpoint-body-panel", children: _jsx(JsonEditor, { value: body, schema: endpoint.bodySchema, onChange: setBody, onValidate: setIsBodyValid }) })), _jsxs(Button, { className: "w-fit", onClick: handleRequest, variant: "accent", "data-testid": "endpoint-play-button", disabled: isRequestLoading || !isPlayEnabled, children: [isRequestLoading ? _jsx(Loader2, { className: "animate-spin" }) : _jsx(Play, {}), " Play"] }), _jsx(EndpointResponse, { responseCode: responseCode, responseBody: responseBody, executionTime: executionTime }), _jsx(EndpointResponseSchema, { items: Object.entries(endpoint?.responseSchema ?? {}).map(([status, schema]) => ({
|
|
73
73
|
responseCode: status,
|
|
74
74
|
bodySchema: schema,
|
|
75
75
|
})) })] }));
|
|
@@ -20,12 +20,10 @@ export const JsonEditor = ({ value, schema, onChange, onValidate }) => {
|
|
|
20
20
|
],
|
|
21
21
|
});
|
|
22
22
|
}, [monaco, schema]);
|
|
23
|
-
return (_jsx(Editor, { height: "200px", language: "json", value: value, theme: editorTheme, onChange: (value) => {
|
|
23
|
+
return (_jsx(Editor, { "data-testid": "json-editor", height: "200px", language: "json", value: value, theme: editorTheme, onChange: (value) => {
|
|
24
|
+
if (!value) {
|
|
25
|
+
onValidate(false);
|
|
26
|
+
}
|
|
24
27
|
onChange(value ?? '');
|
|
25
|
-
}, onValidate: (markers) => {
|
|
26
|
-
onValidate(markers.length === 0);
|
|
27
|
-
}, options: {
|
|
28
|
-
lineNumbers: 'off',
|
|
29
|
-
minimap: { enabled: false },
|
|
30
|
-
} }));
|
|
28
|
+
}, onValidate: (markers) => onValidate(markers.length === 0), options: { lineNumbers: 'off', minimap: { enabled: false } } }));
|
|
31
29
|
};
|
|
@@ -11,5 +11,5 @@ export const FlowTabMenuItem = () => {
|
|
|
11
11
|
if (flows.length === 0) {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
|
-
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("div", { className: "flex flex-row justify-center items-center gap-2 cursor-pointer", children: [_jsx(Workflow, {}), selectedFlowId ?? 'No flow selected', _jsx(ChevronsUpDown, { className: "size-4" })] }) }), _jsx(DropdownMenuContent, { className: "bg-background text-foreground", children: flows.map((item) => (_jsx(DropdownMenuItem, { className: "cursor-pointer gap-2", onClick: () => selectFlowId(item), children: item }, `dropdown-${item}`))) })] }));
|
|
14
|
+
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("div", { "data-testid": "flows-dropdown-trigger", className: "flex flex-row justify-center items-center gap-2 cursor-pointer", children: [_jsx(Workflow, {}), selectedFlowId ?? 'No flow selected', _jsx(ChevronsUpDown, { className: "size-4" })] }) }), _jsx(DropdownMenuContent, { className: "bg-background text-foreground flows-dropdown", children: flows.map((item) => (_jsx(DropdownMenuItem, { "data-testid": `dropdown-${item}`, className: "cursor-pointer gap-2 flow-link", onClick: () => selectFlowId(item), children: item }, `dropdown-${item}`))) })] }));
|
|
15
15
|
};
|
|
@@ -3,5 +3,5 @@ import { useThemeStore } from '@/stores/use-theme-store';
|
|
|
3
3
|
import { ThemeToggle } from '../ui/theme-toggle';
|
|
4
4
|
export const Header = () => {
|
|
5
5
|
const theme = useThemeStore((state) => state.theme);
|
|
6
|
-
return (_jsxs("header", { className: "min-h-16 px-4 gap-1 flex items-center bg-default text-default-foreground border-b", children: [_jsx("img", { src: `/motia-${theme}.png`, className: "h-5" }), _jsx("div", { className: "flex-1" }), _jsx(ThemeToggle, {})] }));
|
|
6
|
+
return (_jsxs("header", { className: "min-h-16 px-4 gap-1 flex items-center bg-default text-default-foreground border-b", children: [_jsx("img", { src: `/motia-${theme}.png`, className: "h-5", id: "logo-icon", "data-testid": "logo-icon" }), _jsx("div", { className: "flex-1" }), _jsx(ThemeToggle, {})] }));
|
|
7
7
|
};
|
|
@@ -11,5 +11,5 @@ export const TracesGroups = memo(({ groups, selectedGroupId, onGroupSelect }) =>
|
|
|
11
11
|
return `${duration}ms`;
|
|
12
12
|
return `${(duration / 1000).toFixed(1)}s`;
|
|
13
13
|
};
|
|
14
|
-
return (_jsx("div", { className: "overflow-auto", children: groups.length > 0 && (_jsx("div", { children: [...groups].reverse().map((group) => (_jsx("div", { "data-testid": `trace-${group.id}`, className: cn('cursor-pointer transition-colors', selectedGroupId === group.id ? 'bg-muted-foreground/10' : 'hover:bg-muted/70'), onClick: () => onGroupSelect(group), children: _jsxs("div", { className: "p-3 flex flex-col gap-1", children: [_jsxs("div", { className: "flex flex-row justify-between items-center gap-2", children: [_jsx("span", { className: "font-semibold text-lg", children: group.name }), _jsx(TraceStatusBadge, { status: group.status, duration: group.endTime ? formatDuration(group.endTime - group.startTime) : undefined })] }), _jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("div", { "data-testid": "trace-id", className: "text-xs text-muted-foreground font-mono tracking-[1px]", children: group.id }), _jsxs("span", { children: [group.metadata.totalSteps, " steps"] })] }), _jsxs("div", { className: "flex justify-between", children: [
|
|
14
|
+
return (_jsx("div", { className: "overflow-auto", children: groups.length > 0 && (_jsx("div", { children: [...groups].reverse().map((group) => (_jsx("div", { "data-testid": `trace-${group.id}`, className: cn('cursor-pointer transition-colors', selectedGroupId === group.id ? 'bg-muted-foreground/10' : 'hover:bg-muted/70'), onClick: () => onGroupSelect(group), children: _jsxs("div", { className: "p-3 flex flex-col gap-1", children: [_jsxs("div", { className: "flex flex-row justify-between items-center gap-2", children: [_jsx("span", { className: "font-semibold text-lg", children: group.name }), _jsx(TraceStatusBadge, { status: group.status, duration: group.endTime ? formatDuration(group.endTime - group.startTime) : undefined })] }), _jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("div", { "data-testid": "trace-id", className: "text-xs text-muted-foreground font-mono tracking-[1px]", children: group.id }), _jsxs("span", { children: [group.metadata.totalSteps, " steps"] })] }), _jsxs("div", { className: "flex justify-between", children: [formatDistanceToNow(group.startTime), " ago"] }), group.metadata.activeSteps > 0 && (_jsxs("div", { className: "text-blue-600", children: [group.metadata.activeSteps, " active"] }))] })] }) }, group.id))) })) }));
|
|
15
15
|
});
|
|
@@ -2,7 +2,6 @@ import React, { HTMLAttributes } from 'react';
|
|
|
2
2
|
import { HandleProps } from '@xyflow/react';
|
|
3
3
|
type Props = HandleProps & Omit<HTMLAttributes<HTMLDivElement>, 'id'> & {
|
|
4
4
|
isHidden?: boolean;
|
|
5
|
-
variant?: string | null;
|
|
6
5
|
onTogglePosition?: () => void;
|
|
7
6
|
};
|
|
8
7
|
export declare const BaseHandle: React.FC<Props>;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Position, Handle as RFHandle } from '@xyflow/react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
export const BaseHandle = (props) => {
|
|
5
|
-
const { isHidden, position,
|
|
5
|
+
const { isHidden, position, onTogglePosition, ...rest } = props;
|
|
6
6
|
const isHorizontal = position === Position.Left || position === Position.Right;
|
|
7
7
|
return (_jsx("div", { className: clsx('absolute w-[6px] h-[6px]', position === Position.Top && '-top-[4px]', position === Position.Bottom && '-bottom-[4px]', position === Position.Left && '-left-[4px]', position === Position.Right && '-right-[4px]', isHorizontal ? 'top-1/2 -mt-[2px]' : 'left-1/2 -ml-[2px]', isHidden && 'hidden'), onClick: onTogglePosition, children: _jsx(RFHandle, { ...rest, position: position, style: { background: 'rgb(30,118,231)' }, className: "\n bg-white/50\n !static\n !w-[6px]\n !h-[6px]\n !min-w-[6px]\n !min-h-[6px]\n !p-0\n !border-none\n !transform-none\n !rounded-full\n !outline-none\n !shadow-none\n " }) }));
|
|
8
8
|
};
|
|
@@ -9,5 +9,5 @@ import { NodeSidebar } from './node-sidebar';
|
|
|
9
9
|
export const BaseNode = ({ title, variant, children, disableSourceHandle, disableTargetHandle, language, subtitle, details, subscribes, emits, data, }) => {
|
|
10
10
|
const [isOpen, setIsOpen] = useState(false);
|
|
11
11
|
const { sourcePosition, targetPosition, toggleTargetPosition, toggleSourcePosition } = useHandlePositions(data);
|
|
12
|
-
return (_jsxs("div", { className: "p-[1px] rounded-lg max-w-[350px]", children: [_jsx("div", { className: "rounded-lg bg-background border-2 border-muted border-solid border-muted-foreground/10", "data-testid": `node-${title?.toLowerCase().replace(/ /g, '-')}`, children: _jsxs("div", { className: "group relative", children: [_jsxs(NodeHeader, { text: title, variant: variant, subtitle: subtitle, children: [_jsx(LanguageIndicator, { language: language }), _jsx("div", { className: "flex justify-end gap-2", children: _jsx("div", { className: "p-[2px] cursor-pointer rounded-md hover:bg-muted-foreground/10", onClick: () => setIsOpen(true), children: _jsx(ChevronUp, { className: "w-4 h-4" }) }) })] }), children && _jsx("div", { className: "border-t-2 border-muted-foreground/10 p-4 space-y-3", children: children }), !disableTargetHandle && (_jsx(BaseHandle, { type: "target", position: targetPosition,
|
|
12
|
+
return (_jsxs("div", { className: "p-[1px] rounded-lg max-w-[350px]", children: [_jsx("div", { className: "rounded-lg bg-background border-2 border-muted border-solid border-muted-foreground/10", "data-testid": `node-${title?.toLowerCase().replace(/ /g, '-')}`, children: _jsxs("div", { className: "group relative", children: [_jsxs(NodeHeader, { text: title, variant: variant, subtitle: subtitle, children: [_jsx(LanguageIndicator, { language: language }), _jsx("div", { className: "flex justify-end gap-2", children: _jsx("div", { className: "p-[2px] cursor-pointer rounded-md hover:bg-muted-foreground/10", onClick: () => setIsOpen(true), children: _jsx(ChevronUp, { className: "w-4 h-4" }) }) })] }), children && _jsx("div", { className: "border-t-2 border-muted-foreground/10 p-4 space-y-3", children: children }), !disableTargetHandle && (_jsx(BaseHandle, { type: "target", position: targetPosition, onTogglePosition: toggleTargetPosition })), !disableSourceHandle && (_jsx(BaseHandle, { type: "source", position: sourcePosition, onTogglePosition: toggleSourcePosition }))] }) }), _jsx(NodeSidebar, { title: title, subtitle: subtitle, variant: variant, language: language, isOpen: isOpen, onClose: () => setIsOpen(false), details: details, subscribes: subscribes, emits: emits })] }));
|
|
13
13
|
};
|