@sudobility/testomniac_ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/dist/components/bundles/AddToBundleButton.d.ts +8 -0
- package/dist/components/bundles/AddToBundleButton.d.ts.map +1 -0
- package/dist/components/bundles/AddToBundleButton.js +64 -0
- package/dist/components/bundles/AddToBundleButton.js.map +1 -0
- package/dist/components/cells/BundleCell.d.ts +10 -0
- package/dist/components/cells/BundleCell.d.ts.map +1 -0
- package/dist/components/cells/BundleCell.js +8 -0
- package/dist/components/cells/BundleCell.js.map +1 -0
- package/dist/components/cells/InteractionCell.d.ts +17 -0
- package/dist/components/cells/InteractionCell.d.ts.map +1 -0
- package/dist/components/cells/InteractionCell.js +13 -0
- package/dist/components/cells/InteractionCell.js.map +1 -0
- package/dist/components/cells/ListCell.d.ts +29 -0
- package/dist/components/cells/ListCell.d.ts.map +1 -0
- package/dist/components/cells/ListCell.js +19 -0
- package/dist/components/cells/ListCell.js.map +1 -0
- package/dist/components/cells/PersonaCell.d.ts +10 -0
- package/dist/components/cells/PersonaCell.d.ts.map +1 -0
- package/dist/components/cells/PersonaCell.js +7 -0
- package/dist/components/cells/PersonaCell.js.map +1 -0
- package/dist/components/cells/ScaffoldCell.d.ts +12 -0
- package/dist/components/cells/ScaffoldCell.d.ts.map +1 -0
- package/dist/components/cells/ScaffoldCell.js +10 -0
- package/dist/components/cells/ScaffoldCell.js.map +1 -0
- package/dist/components/cells/ScenarioCell.d.ts +12 -0
- package/dist/components/cells/ScenarioCell.d.ts.map +1 -0
- package/dist/components/cells/ScenarioCell.js +8 -0
- package/dist/components/cells/ScenarioCell.js.map +1 -0
- package/dist/components/cells/SurfaceCell.d.ts +14 -0
- package/dist/components/cells/SurfaceCell.d.ts.map +1 -0
- package/dist/components/cells/SurfaceCell.js +23 -0
- package/dist/components/cells/SurfaceCell.js.map +1 -0
- package/dist/components/cells/index.d.ts +9 -0
- package/dist/components/cells/index.d.ts.map +1 -0
- package/dist/components/cells/index.js +9 -0
- package/dist/components/cells/index.js.map +1 -0
- package/dist/components/cells/scaffoldMeta.d.ts +6 -0
- package/dist/components/cells/scaffoldMeta.d.ts.map +1 -0
- package/dist/components/cells/scaffoldMeta.js +47 -0
- package/dist/components/cells/scaffoldMeta.js.map +1 -0
- package/dist/components/dashboard/DashboardSidebar.d.ts +6 -0
- package/dist/components/dashboard/DashboardSidebar.d.ts.map +1 -0
- package/dist/components/dashboard/DashboardSidebar.js +163 -0
- package/dist/components/dashboard/DashboardSidebar.js.map +1 -0
- package/dist/components/data/DataTable.d.ts +16 -0
- package/dist/components/data/DataTable.d.ts.map +1 -0
- package/dist/components/data/DataTable.js +54 -0
- package/dist/components/data/DataTable.js.map +1 -0
- package/dist/components/data/JsonViewer.d.ts +6 -0
- package/dist/components/data/JsonViewer.d.ts.map +1 -0
- package/dist/components/data/JsonViewer.js +5 -0
- package/dist/components/data/JsonViewer.js.map +1 -0
- package/dist/components/data/index.d.ts +3 -0
- package/dist/components/data/index.d.ts.map +1 -0
- package/dist/components/data/index.js +3 -0
- package/dist/components/data/index.js.map +1 -0
- package/dist/components/forms/SelectField.d.ts +22 -0
- package/dist/components/forms/SelectField.d.ts.map +1 -0
- package/dist/components/forms/SelectField.js +14 -0
- package/dist/components/forms/SelectField.js.map +1 -0
- package/dist/components/navigation/BackLink.d.ts +7 -0
- package/dist/components/navigation/BackLink.d.ts.map +1 -0
- package/dist/components/navigation/BackLink.js +6 -0
- package/dist/components/navigation/BackLink.js.map +1 -0
- package/dist/components/pages/PagesListView.d.ts +12 -0
- package/dist/components/pages/PagesListView.d.ts.map +1 -0
- package/dist/components/pages/PagesListView.js +19 -0
- package/dist/components/pages/PagesListView.js.map +1 -0
- package/dist/components/pages/PagesMapView.d.ts +15 -0
- package/dist/components/pages/PagesMapView.d.ts.map +1 -0
- package/dist/components/pages/PagesMapView.js +232 -0
- package/dist/components/pages/PagesMapView.js.map +1 -0
- package/dist/components/scanner/EventLog.d.ts +8 -0
- package/dist/components/scanner/EventLog.d.ts.map +1 -0
- package/dist/components/scanner/EventLog.js +18 -0
- package/dist/components/scanner/EventLog.js.map +1 -0
- package/dist/components/scanner/LiveCounters.d.ts +9 -0
- package/dist/components/scanner/LiveCounters.d.ts.map +1 -0
- package/dist/components/scanner/LiveCounters.js +33 -0
- package/dist/components/scanner/LiveCounters.js.map +1 -0
- package/dist/components/scanner/PhaseIndicator.d.ts +6 -0
- package/dist/components/scanner/PhaseIndicator.d.ts.map +1 -0
- package/dist/components/scanner/PhaseIndicator.js +31 -0
- package/dist/components/scanner/PhaseIndicator.js.map +1 -0
- package/dist/components/scanner/RunSummaryCard.d.ts +12 -0
- package/dist/components/scanner/RunSummaryCard.d.ts.map +1 -0
- package/dist/components/scanner/RunSummaryCard.js +7 -0
- package/dist/components/scanner/RunSummaryCard.js.map +1 -0
- package/dist/components/scanner/ScanForm.d.ts +9 -0
- package/dist/components/scanner/ScanForm.d.ts.map +1 -0
- package/dist/components/scanner/ScanForm.js +31 -0
- package/dist/components/scanner/ScanForm.js.map +1 -0
- package/dist/components/scanner/ScanProgressPanel.d.ts +16 -0
- package/dist/components/scanner/ScanProgressPanel.d.ts.map +1 -0
- package/dist/components/scanner/ScanProgressPanel.js +8 -0
- package/dist/components/scanner/ScanProgressPanel.js.map +1 -0
- package/dist/components/scanner/StatusBadge.d.ts +7 -0
- package/dist/components/scanner/StatusBadge.d.ts.map +1 -0
- package/dist/components/scanner/StatusBadge.js +65 -0
- package/dist/components/scanner/StatusBadge.js.map +1 -0
- package/dist/components/scanner/index.d.ts +8 -0
- package/dist/components/scanner/index.d.ts.map +1 -0
- package/dist/components/scanner/index.js +8 -0
- package/dist/components/scanner/index.js.map +1 -0
- package/dist/components/scenarios/AddScenarioForm.d.ts +14 -0
- package/dist/components/scenarios/AddScenarioForm.d.ts.map +1 -0
- package/dist/components/scenarios/AddScenarioForm.js +43 -0
- package/dist/components/scenarios/AddScenarioForm.js.map +1 -0
- package/dist/components/scripts/ScriptPanel.d.ts +17 -0
- package/dist/components/scripts/ScriptPanel.d.ts.map +1 -0
- package/dist/components/scripts/ScriptPanel.js +32 -0
- package/dist/components/scripts/ScriptPanel.js.map +1 -0
- package/dist/components/states/index.d.ts +19 -0
- package/dist/components/states/index.d.ts.map +1 -0
- package/dist/components/states/index.js +16 -0
- package/dist/components/states/index.js.map +1 -0
- package/dist/config/priorityConfig.d.ts +12 -0
- package/dist/config/priorityConfig.d.ts.map +1 -0
- package/dist/config/priorityConfig.js +39 -0
- package/dist/config/priorityConfig.js.map +1 -0
- package/dist/context/config.d.ts +53 -0
- package/dist/context/config.d.ts.map +1 -0
- package/dist/context/config.js +32 -0
- package/dist/context/config.js.map +1 -0
- package/dist/context/routing.d.ts +42 -0
- package/dist/context/routing.d.ts.map +1 -0
- package/dist/context/routing.js +33 -0
- package/dist/context/routing.js.map +1 -0
- package/dist/hooks/useDashboardEnvironmentContext.d.ts +15 -0
- package/dist/hooks/useDashboardEnvironmentContext.d.ts.map +1 -0
- package/dist/hooks/useDashboardEnvironmentContext.js +89 -0
- package/dist/hooks/useDashboardEnvironmentContext.js.map +1 -0
- package/dist/hooks/useEnvBasePath.d.ts +8 -0
- package/dist/hooks/useEnvBasePath.d.ts.map +1 -0
- package/dist/hooks/useEnvBasePath.js +12 -0
- package/dist/hooks/useEnvBasePath.js.map +1 -0
- package/dist/hooks/useLocalizedNavigate.d.ts +12 -0
- package/dist/hooks/useLocalizedNavigate.d.ts.map +1 -0
- package/dist/hooks/useLocalizedNavigate.js +14 -0
- package/dist/hooks/useLocalizedNavigate.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/BundleDetailPage.d.ts +2 -0
- package/dist/pages/BundleDetailPage.d.ts.map +1 -0
- package/dist/pages/BundleDetailPage.js +155 -0
- package/dist/pages/BundleDetailPage.js.map +1 -0
- package/dist/pages/BundlesPage.d.ts +2 -0
- package/dist/pages/BundlesPage.d.ts.map +1 -0
- package/dist/pages/BundlesPage.js +61 -0
- package/dist/pages/BundlesPage.js.map +1 -0
- package/dist/pages/DashboardOverview.d.ts +2 -0
- package/dist/pages/DashboardOverview.d.ts.map +1 -0
- package/dist/pages/DashboardOverview.js +179 -0
- package/dist/pages/DashboardOverview.js.map +1 -0
- package/dist/pages/FindingsListPage.d.ts +2 -0
- package/dist/pages/FindingsListPage.d.ts.map +1 -0
- package/dist/pages/FindingsListPage.js +160 -0
- package/dist/pages/FindingsListPage.js.map +1 -0
- package/dist/pages/PageDetailPage.d.ts +2 -0
- package/dist/pages/PageDetailPage.d.ts.map +1 -0
- package/dist/pages/PageDetailPage.js +120 -0
- package/dist/pages/PageDetailPage.js.map +1 -0
- package/dist/pages/PageGraphPage.d.ts +3 -0
- package/dist/pages/PageGraphPage.d.ts.map +1 -0
- package/dist/pages/PageGraphPage.js +72 -0
- package/dist/pages/PageGraphPage.js.map +1 -0
- package/dist/pages/PageStateDetailPage.d.ts +2 -0
- package/dist/pages/PageStateDetailPage.d.ts.map +1 -0
- package/dist/pages/PageStateDetailPage.js +69 -0
- package/dist/pages/PageStateDetailPage.js.map +1 -0
- package/dist/pages/PagesPage.d.ts +2 -0
- package/dist/pages/PagesPage.d.ts.map +1 -0
- package/dist/pages/PagesPage.js +83 -0
- package/dist/pages/PagesPage.js.map +1 -0
- package/dist/pages/PatternsPage.d.ts +2 -0
- package/dist/pages/PatternsPage.d.ts.map +1 -0
- package/dist/pages/PatternsPage.js +102 -0
- package/dist/pages/PatternsPage.js.map +1 -0
- package/dist/pages/PersonasPage.d.ts +2 -0
- package/dist/pages/PersonasPage.d.ts.map +1 -0
- package/dist/pages/PersonasPage.js +151 -0
- package/dist/pages/PersonasPage.js.map +1 -0
- package/dist/pages/RunRedirect.d.ts +2 -0
- package/dist/pages/RunRedirect.d.ts.map +1 -0
- package/dist/pages/RunRedirect.js +25 -0
- package/dist/pages/RunRedirect.js.map +1 -0
- package/dist/pages/RunSurfaceRunDetailPage.d.ts +2 -0
- package/dist/pages/RunSurfaceRunDetailPage.d.ts.map +1 -0
- package/dist/pages/RunSurfaceRunDetailPage.js +38 -0
- package/dist/pages/RunSurfaceRunDetailPage.js.map +1 -0
- package/dist/pages/RunSurfaceRunsPage.d.ts +2 -0
- package/dist/pages/RunSurfaceRunsPage.d.ts.map +1 -0
- package/dist/pages/RunSurfaceRunsPage.js +35 -0
- package/dist/pages/RunSurfaceRunsPage.js.map +1 -0
- package/dist/pages/RunTestInteractionRunDetailPage.d.ts +2 -0
- package/dist/pages/RunTestInteractionRunDetailPage.d.ts.map +1 -0
- package/dist/pages/RunTestInteractionRunDetailPage.js +55 -0
- package/dist/pages/RunTestInteractionRunDetailPage.js.map +1 -0
- package/dist/pages/RunTestInteractionRunsPage.d.ts +2 -0
- package/dist/pages/RunTestInteractionRunsPage.d.ts.map +1 -0
- package/dist/pages/RunTestInteractionRunsPage.js +38 -0
- package/dist/pages/RunTestInteractionRunsPage.js.map +1 -0
- package/dist/pages/RunnerGraphPage.d.ts +3 -0
- package/dist/pages/RunnerGraphPage.d.ts.map +1 -0
- package/dist/pages/RunnerGraphPage.js +86 -0
- package/dist/pages/RunnerGraphPage.js.map +1 -0
- package/dist/pages/ScaffoldDetailPage.d.ts +2 -0
- package/dist/pages/ScaffoldDetailPage.d.ts.map +1 -0
- package/dist/pages/ScaffoldDetailPage.js +56 -0
- package/dist/pages/ScaffoldDetailPage.js.map +1 -0
- package/dist/pages/ScaffoldsPage.d.ts +2 -0
- package/dist/pages/ScaffoldsPage.d.ts.map +1 -0
- package/dist/pages/ScaffoldsPage.js +35 -0
- package/dist/pages/ScaffoldsPage.js.map +1 -0
- package/dist/pages/ScanProgressPage.d.ts +2 -0
- package/dist/pages/ScanProgressPage.d.ts.map +1 -0
- package/dist/pages/ScanProgressPage.js +30 -0
- package/dist/pages/ScanProgressPage.js.map +1 -0
- package/dist/pages/SchedulesPage.d.ts +2 -0
- package/dist/pages/SchedulesPage.d.ts.map +1 -0
- package/dist/pages/SchedulesPage.js +165 -0
- package/dist/pages/SchedulesPage.js.map +1 -0
- package/dist/pages/StartScanPage.d.ts +2 -0
- package/dist/pages/StartScanPage.d.ts.map +1 -0
- package/dist/pages/StartScanPage.js +97 -0
- package/dist/pages/StartScanPage.js.map +1 -0
- package/dist/pages/TestInteractionDetailPage.d.ts +2 -0
- package/dist/pages/TestInteractionDetailPage.d.ts.map +1 -0
- package/dist/pages/TestInteractionDetailPage.js +60 -0
- package/dist/pages/TestInteractionDetailPage.js.map +1 -0
- package/dist/pages/TestInteractionsPage.d.ts +2 -0
- package/dist/pages/TestInteractionsPage.d.ts.map +1 -0
- package/dist/pages/TestInteractionsPage.js +96 -0
- package/dist/pages/TestInteractionsPage.js.map +1 -0
- package/dist/pages/TestRunDetailPage.d.ts +2 -0
- package/dist/pages/TestRunDetailPage.d.ts.map +1 -0
- package/dist/pages/TestRunDetailPage.js +81 -0
- package/dist/pages/TestRunDetailPage.js.map +1 -0
- package/dist/pages/TestRunsListPage.d.ts +2 -0
- package/dist/pages/TestRunsListPage.d.ts.map +1 -0
- package/dist/pages/TestRunsListPage.js +18 -0
- package/dist/pages/TestRunsListPage.js.map +1 -0
- package/dist/pages/TestScenarioDetailPage.d.ts +2 -0
- package/dist/pages/TestScenarioDetailPage.d.ts.map +1 -0
- package/dist/pages/TestScenarioDetailPage.js +101 -0
- package/dist/pages/TestScenarioDetailPage.js.map +1 -0
- package/dist/pages/TestScenariosPage.d.ts +2 -0
- package/dist/pages/TestScenariosPage.d.ts.map +1 -0
- package/dist/pages/TestScenariosPage.js +73 -0
- package/dist/pages/TestScenariosPage.js.map +1 -0
- package/dist/pages/TestSurfaceDetailPage.d.ts +2 -0
- package/dist/pages/TestSurfaceDetailPage.d.ts.map +1 -0
- package/dist/pages/TestSurfaceDetailPage.js +33 -0
- package/dist/pages/TestSurfaceDetailPage.js.map +1 -0
- package/dist/pages/TestSurfacesListPage.d.ts +2 -0
- package/dist/pages/TestSurfacesListPage.d.ts.map +1 -0
- package/dist/pages/TestSurfacesListPage.js +73 -0
- package/dist/pages/TestSurfacesListPage.js.map +1 -0
- package/dist/utils/formatDateTime.d.ts +13 -0
- package/dist/utils/formatDateTime.d.ts.map +1 -0
- package/dist/utils/formatDateTime.js +27 -0
- package/dist/utils/formatDateTime.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useCallback } from 'react';
|
|
3
|
+
import { ReactFlow, Background, Controls, MiniMap, useNodesState, useEdgesState, } from '@xyflow/react';
|
|
4
|
+
import '@xyflow/react/dist/style.css';
|
|
5
|
+
import { usePageStates, buildArtifactUrl } from '@sudobility/testomniac_client';
|
|
6
|
+
import { layoutDagreGraph } from '@sudobility/testomniac_lib';
|
|
7
|
+
import { SEOHead, useTestomniacApi } from '../context/config';
|
|
8
|
+
import { useRouteParams } from '../context/routing';
|
|
9
|
+
import BackLink from '../components/navigation/BackLink';
|
|
10
|
+
import { useLocalizedNavigate } from '../hooks/useLocalizedNavigate';
|
|
11
|
+
const NODE_WIDTH = 200;
|
|
12
|
+
const NODE_HEIGHT = 160;
|
|
13
|
+
function layoutGraph(nodes, edges) {
|
|
14
|
+
const positions = layoutDagreGraph(nodes, edges, {
|
|
15
|
+
nodeWidth: NODE_WIDTH,
|
|
16
|
+
nodeHeight: NODE_HEIGHT,
|
|
17
|
+
});
|
|
18
|
+
return nodes.map(node => ({
|
|
19
|
+
...node,
|
|
20
|
+
position: positions.get(node.id) ?? node.position,
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
function PageStateNode({ data }) {
|
|
24
|
+
return (_jsxs("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden shadow-sm", style: { width: NODE_WIDTH, height: NODE_HEIGHT }, children: [_jsx("div", { className: "w-full h-[120px] bg-gray-100 dark:bg-gray-900 flex items-center justify-center overflow-hidden", children: data.screenshotUrl ? (_jsx("img", { src: data.screenshotUrl, alt: "", className: "w-full h-full object-cover object-top", loading: "lazy" })) : (_jsxs("svg", { className: "w-8 h-8 text-gray-300 dark:text-gray-600", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("path", { d: "M3 15l5-5 4 4 3-3 6 6" })] })) }), _jsx("div", { className: "px-2 py-1.5 text-center", children: _jsx("span", { className: "text-xs font-medium text-gray-700 dark:text-gray-300 truncate block", children: data.label }) })] }));
|
|
25
|
+
}
|
|
26
|
+
const nodeTypes = { pageState: PageStateNode };
|
|
27
|
+
export function PageGraphPage() {
|
|
28
|
+
const { pageId, envId, entitySlug } = useRouteParams();
|
|
29
|
+
const { networkClient, token, baseUrl } = useTestomniacApi();
|
|
30
|
+
const { navigate } = useLocalizedNavigate();
|
|
31
|
+
const numericPageId = Number(pageId);
|
|
32
|
+
const { pageStates, isLoading: statesLoading } = usePageStates({
|
|
33
|
+
networkClient,
|
|
34
|
+
baseUrl,
|
|
35
|
+
pageId: numericPageId,
|
|
36
|
+
token: token ?? '',
|
|
37
|
+
enabled: !!pageId && !!token,
|
|
38
|
+
});
|
|
39
|
+
const isLoading = statesLoading;
|
|
40
|
+
const { initialNodes, initialEdges } = useMemo(() => {
|
|
41
|
+
if (pageStates.length === 0)
|
|
42
|
+
return { initialNodes: [], initialEdges: [] };
|
|
43
|
+
const rawNodes = pageStates.map(ps => {
|
|
44
|
+
const screenshotUrl = ps.screenshotPath
|
|
45
|
+
? buildArtifactUrl(baseUrl, ps.screenshotPath, { thumbnail: true })
|
|
46
|
+
: undefined;
|
|
47
|
+
return {
|
|
48
|
+
id: String(ps.id),
|
|
49
|
+
type: 'pageState',
|
|
50
|
+
data: {
|
|
51
|
+
label: `${ps.sizeClass} (#${ps.id})`,
|
|
52
|
+
screenshotUrl,
|
|
53
|
+
},
|
|
54
|
+
position: { x: 0, y: 0 },
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
const rawEdges = [];
|
|
58
|
+
const layoutNodes = layoutGraph(rawNodes, rawEdges);
|
|
59
|
+
return { initialNodes: layoutNodes, initialEdges: rawEdges };
|
|
60
|
+
}, [pageStates, baseUrl]);
|
|
61
|
+
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
|
62
|
+
const [edges, , onEdgesChange] = useEdgesState(initialEdges);
|
|
63
|
+
const onNodeClick = useCallback((_, node) => {
|
|
64
|
+
navigate(`/dashboard/${entitySlug}/environments/${envId}/pages/${pageId}/states/${node.id}`);
|
|
65
|
+
}, [navigate, entitySlug, envId, pageId]);
|
|
66
|
+
const pagesBasePath = `/dashboard/${entitySlug}/environments/${envId}/pages/${pageId}`;
|
|
67
|
+
if (isLoading) {
|
|
68
|
+
return (_jsx("div", { className: "p-6", children: _jsx("div", { className: "text-center text-gray-500 dark:text-gray-400 py-8", children: "Loading graph..." }) }));
|
|
69
|
+
}
|
|
70
|
+
return (_jsxs("div", { className: "p-6", children: [_jsx(SEOHead, { title: "Page Graph", description: "", noIndex: true }), _jsx(BackLink, { label: "Page Detail", onClick: () => navigate(pagesBasePath) }), _jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-gray-100 mb-6", children: "Page Graph" }), pageStates.length === 0 ? (_jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "No page states found." })) : (_jsx("div", { className: "w-full h-[600px] border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden", children: _jsxs(ReactFlow, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onNodeClick: onNodeClick, nodeTypes: nodeTypes, fitView: true, className: "bg-gray-50 dark:bg-gray-900", children: [_jsx(Background, {}), _jsx(Controls, {}), _jsx(MiniMap, {})] }) }))] }));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=PageGraphPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageGraphPage.js","sourceRoot":"","sources":["../../src/pages/PageGraphPage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageStateDetailPage.d.ts","sourceRoot":"","sources":["../../src/pages/PageStateDetailPage.tsx"],"names":[],"mappings":"AAeA,wBAAgB,mBAAmB,gCAoQlC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useMemo } from 'react';
|
|
3
|
+
import { usePageStates, useHtmlElement, usePageStateScaffolds, buildArtifactUrl, } from '@sudobility/testomniac_client';
|
|
4
|
+
import { Tabs, TabsList, TabsTrigger, Card } from '@sudobility/components';
|
|
5
|
+
import { useTestomniacApi } from '../context/config';
|
|
6
|
+
import { useRouteParams } from '../context/routing';
|
|
7
|
+
import BackLink from '../components/navigation/BackLink';
|
|
8
|
+
import { useLocalizedNavigate } from '../hooks/useLocalizedNavigate';
|
|
9
|
+
export function PageStateDetailPage() {
|
|
10
|
+
const { pageStateId, pageId, envId, entitySlug, runId } = useRouteParams();
|
|
11
|
+
const { networkClient, token, baseUrl } = useTestomniacApi();
|
|
12
|
+
const { navigate } = useLocalizedNavigate();
|
|
13
|
+
const [activeTab, setActiveTab] = useState('body');
|
|
14
|
+
const [bodyView, setBodyView] = useState('rendered');
|
|
15
|
+
const [contentView, setContentView] = useState('rendered');
|
|
16
|
+
const { pageStates, isLoading: statesLoading } = usePageStates({
|
|
17
|
+
networkClient,
|
|
18
|
+
baseUrl,
|
|
19
|
+
pageId: Number(pageId),
|
|
20
|
+
token: token ?? '',
|
|
21
|
+
enabled: !!pageId && !!token,
|
|
22
|
+
});
|
|
23
|
+
const state = useMemo(() => pageStates.find(s => s.id === Number(pageStateId)) ?? null, [pageStates, pageStateId]);
|
|
24
|
+
const { htmlElement: bodyHtmlElement, isLoading: bodyLoading } = useHtmlElement({
|
|
25
|
+
networkClient,
|
|
26
|
+
baseUrl,
|
|
27
|
+
id: state?.bodyHtmlElementId ?? 0,
|
|
28
|
+
token: token ?? '',
|
|
29
|
+
enabled: !!state?.bodyHtmlElementId && !!token,
|
|
30
|
+
});
|
|
31
|
+
const { htmlElement: contentHtmlElement, isLoading: contentLoading } = useHtmlElement({
|
|
32
|
+
networkClient,
|
|
33
|
+
baseUrl,
|
|
34
|
+
id: state?.contentHtmlElementId ?? 0,
|
|
35
|
+
token: token ?? '',
|
|
36
|
+
enabled: !!state?.contentHtmlElementId && !!token,
|
|
37
|
+
});
|
|
38
|
+
const { scaffolds, isLoading: scaffoldsLoading } = usePageStateScaffolds({
|
|
39
|
+
networkClient,
|
|
40
|
+
baseUrl,
|
|
41
|
+
pageStateId: Number(pageStateId),
|
|
42
|
+
token: token ?? '',
|
|
43
|
+
enabled: !!pageStateId && !!token,
|
|
44
|
+
});
|
|
45
|
+
if (statesLoading) {
|
|
46
|
+
return (_jsx("div", { className: "p-6", children: _jsx("div", { className: "text-center text-gray-500 dark:text-gray-400 py-8", children: "Loading..." }) }));
|
|
47
|
+
}
|
|
48
|
+
if (!state) {
|
|
49
|
+
return (_jsx("div", { className: "p-6", children: _jsx("div", { className: "text-center text-gray-500 dark:text-gray-400 py-8", children: "Page state not found." }) }));
|
|
50
|
+
}
|
|
51
|
+
const tabs = [
|
|
52
|
+
{ key: 'body', label: 'Body' },
|
|
53
|
+
{ key: 'content', label: 'Content' },
|
|
54
|
+
{ key: 'scaffolds', label: 'Scaffolds' },
|
|
55
|
+
];
|
|
56
|
+
const pageBasePath = runId
|
|
57
|
+
? `/dashboard/${entitySlug}/environments/${envId}/runs/${runId}/pages/${pageId}`
|
|
58
|
+
: `/dashboard/${entitySlug}/environments/${envId}/pages/${pageId}`;
|
|
59
|
+
return (_jsxs("div", { className: "p-6", children: [_jsx(BackLink, { label: `Page #${pageId}`, onClick: () => navigate(pageBasePath) }), _jsxs("div", { className: "mb-6", children: [_jsxs("h1", { className: "text-2xl font-bold text-gray-900 dark:text-gray-100", children: ["Page State #", pageStateId] }), _jsxs("div", { className: "flex items-center gap-3 mt-2", children: [_jsx("span", { className: "px-2 py-0.5 text-xs rounded bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400", children: state.sizeClass }), _jsxs("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: ["Environment #", envId, " / Page #", pageId] }), state.capturedAt && (_jsxs("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: ["Captured: ", new Date(state.capturedAt).toLocaleString()] }))] })] }), _jsx(Tabs, { value: activeTab, onValueChange: v => setActiveTab(v), className: "mb-6", children: _jsx(TabsList, { children: tabs.map(tab => (_jsx(TabsTrigger, { value: tab.key, children: tab.label }, tab.key))) }) }), activeTab === 'body' && (_jsxs("div", { children: [_jsxs("div", { className: "flex gap-2 mb-4", children: [_jsx("button", { onClick: () => setBodyView('rendered'), className: `px-3 py-1.5 text-sm rounded-md border ${bodyView === 'rendered'
|
|
60
|
+
? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300'
|
|
61
|
+
: 'border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300'}`, children: "Rendered" }), _jsx("button", { onClick: () => setBodyView('source'), className: `px-3 py-1.5 text-sm rounded-md border ${bodyView === 'source'
|
|
62
|
+
? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300'
|
|
63
|
+
: 'border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300'}`, children: "Source" })] }), bodyView === 'rendered' ? (state.rawHtmlPath ? (_jsx("iframe", { sandbox: "allow-same-origin", src: buildArtifactUrl(baseUrl, state.rawHtmlPath), className: "w-full h-[600px] border border-gray-200 dark:border-gray-700 rounded-lg bg-white", title: "Rendered body HTML" })) : (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "No raw HTML available." }))) : bodyLoading ? (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "Loading source..." })) : bodyHtmlElement ? (_jsx("pre", { className: "p-4 bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg text-xs text-gray-800 dark:text-gray-200 overflow-auto max-h-[600px]", children: bodyHtmlElement.html })) : (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "No body HTML element available." }))] })), activeTab === 'content' && (_jsxs("div", { children: [_jsxs("div", { className: "flex gap-2 mb-4", children: [_jsx("button", { onClick: () => setContentView('rendered'), className: `px-3 py-1.5 text-sm rounded-md border ${contentView === 'rendered'
|
|
64
|
+
? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300'
|
|
65
|
+
: 'border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300'}`, children: "Rendered" }), _jsx("button", { onClick: () => setContentView('source'), className: `px-3 py-1.5 text-sm rounded-md border ${contentView === 'source'
|
|
66
|
+
? 'border-blue-500 bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300'
|
|
67
|
+
: 'border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300'}`, children: "Source" })] }), contentView === 'rendered' ? (_jsxs("div", { className: "space-y-4", children: [state.contentText && (_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: "Content Text" }), _jsx("div", { className: "p-4 bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg text-sm text-gray-800 dark:text-gray-200 whitespace-pre-wrap max-h-[400px] overflow-auto", children: state.contentText })] })), !state.contentText && (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "No content text available." }))] })) : contentLoading ? (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "Loading source..." })) : contentHtmlElement ? (_jsx("pre", { className: "p-4 bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg text-xs text-gray-800 dark:text-gray-200 overflow-auto max-h-[600px]", children: contentHtmlElement.html })) : (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "No content HTML element available." }))] })), activeTab === 'scaffolds' && (_jsx("div", { children: scaffoldsLoading ? (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "Loading..." })) : scaffolds.length === 0 ? (_jsx("div", { className: "text-gray-500 dark:text-gray-400 py-8 text-center", children: "No scaffolds found." })) : (_jsx("div", { className: "space-y-3", children: scaffolds.map(element => (_jsxs(Card, { variant: "bordered", padding: "md", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: ["Scaffold #", element.scaffoldId] }), _jsx("span", { className: "px-1.5 py-0.5 text-xs rounded bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300", children: "Scaffold" })] }), _jsxs("div", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: ["Page State #", element.pageStateId] })] }, element.id))) })) }))] }));
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=PageStateDetailPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageStateDetailPage.js","sourceRoot":"","sources":["../../src/pages/PageStateDetailPage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PagesPage.d.ts","sourceRoot":"","sources":["../../src/pages/PagesPage.tsx"],"names":[],"mappings":"AAaA,wBAAgB,SAAS,gCAoJxB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useMemo } from 'react';
|
|
3
|
+
import { useEnvironmentPages, useEnvironmentTestInteractions, useRunPages, useRunTestInteractions, useRunnerPageStates, } from '@sudobility/testomniac_client';
|
|
4
|
+
import { SEOHead, useTestomniacApi } from '../context/config';
|
|
5
|
+
import { useRouteParams } from '../context/routing';
|
|
6
|
+
import { PagesListView } from '../components/pages/PagesListView';
|
|
7
|
+
import { PagesMapView } from '../components/pages/PagesMapView';
|
|
8
|
+
export function PagesPage() {
|
|
9
|
+
const { entitySlug, envId, runId } = useRouteParams();
|
|
10
|
+
const { networkClient, token, baseUrl } = useTestomniacApi();
|
|
11
|
+
const [view, setView] = useState('list');
|
|
12
|
+
const runScoped = Boolean(runId);
|
|
13
|
+
const environmentPagesQuery = useEnvironmentPages({
|
|
14
|
+
networkClient,
|
|
15
|
+
baseUrl,
|
|
16
|
+
envId: Number(envId),
|
|
17
|
+
token: token ?? '',
|
|
18
|
+
enabled: !!envId && !!token && !runScoped,
|
|
19
|
+
});
|
|
20
|
+
const runPagesQuery = useRunPages({
|
|
21
|
+
networkClient,
|
|
22
|
+
baseUrl,
|
|
23
|
+
runId: Number(runId),
|
|
24
|
+
token: token ?? '',
|
|
25
|
+
enabled: !!runId && !!token,
|
|
26
|
+
});
|
|
27
|
+
const environmentElementsQuery = useEnvironmentTestInteractions({
|
|
28
|
+
networkClient,
|
|
29
|
+
baseUrl,
|
|
30
|
+
envId: Number(envId),
|
|
31
|
+
token: token ?? '',
|
|
32
|
+
enabled: !!envId && !!token && !runScoped,
|
|
33
|
+
});
|
|
34
|
+
const runElementsQuery = useRunTestInteractions({
|
|
35
|
+
networkClient,
|
|
36
|
+
baseUrl,
|
|
37
|
+
runId: Number(runId),
|
|
38
|
+
token: token ?? '',
|
|
39
|
+
enabled: !!runId && !!token,
|
|
40
|
+
});
|
|
41
|
+
const pages = runScoped ? runPagesQuery.pages : environmentPagesQuery.pages;
|
|
42
|
+
const testInteractions = runScoped
|
|
43
|
+
? runElementsQuery.testInteractions
|
|
44
|
+
: environmentElementsQuery.testInteractions;
|
|
45
|
+
const pagesLoading = runScoped ? runPagesQuery.isLoading : environmentPagesQuery.isLoading;
|
|
46
|
+
const elementsLoading = runScoped
|
|
47
|
+
? runElementsQuery.isLoading
|
|
48
|
+
: environmentElementsQuery.isLoading;
|
|
49
|
+
const pagesError = runScoped ? runPagesQuery.error : environmentPagesQuery.error;
|
|
50
|
+
const elementsError = runScoped ? runElementsQuery.error : environmentElementsQuery.error;
|
|
51
|
+
const isLoading = pagesLoading || elementsLoading;
|
|
52
|
+
const error = pagesError || elementsError;
|
|
53
|
+
// Fetch page states for screenshot paths (used in both list and map views)
|
|
54
|
+
const primaryRunnerId = pages.length > 0 ? pages[0].runnerId : 0;
|
|
55
|
+
const { pageStates } = useRunnerPageStates({
|
|
56
|
+
networkClient,
|
|
57
|
+
baseUrl,
|
|
58
|
+
runnerId: primaryRunnerId,
|
|
59
|
+
token: token ?? '',
|
|
60
|
+
enabled: !!primaryRunnerId && !!token,
|
|
61
|
+
});
|
|
62
|
+
const screenshotsByPageId = useMemo(() => {
|
|
63
|
+
const map = new Map();
|
|
64
|
+
for (const ps of pageStates) {
|
|
65
|
+
if (ps.screenshotPath && !map.has(ps.pageId)) {
|
|
66
|
+
map.set(ps.pageId, ps.screenshotPath);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return map;
|
|
70
|
+
}, [pageStates]);
|
|
71
|
+
if (isLoading) {
|
|
72
|
+
return (_jsx("div", { className: "p-6", children: _jsx("div", { className: "py-8 text-center text-gray-500 dark:text-gray-400", children: "Loading..." }) }));
|
|
73
|
+
}
|
|
74
|
+
if (error) {
|
|
75
|
+
return (_jsx("div", { className: "p-6", children: _jsxs("div", { className: "py-8 text-center text-red-600 dark:text-red-400", children: ["Error: ", error] }) }));
|
|
76
|
+
}
|
|
77
|
+
return (_jsxs("div", { className: "p-6", children: [_jsx(SEOHead, { title: "Discovered Pages", description: "", noIndex: true }), _jsxs("div", { className: "mb-6 flex items-center justify-between", children: [_jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-gray-100", children: runScoped ? `Run #${runId} Pages` : 'Discovered Pages' }), _jsxs("div", { className: "flex rounded-lg border border-gray-200 dark:border-gray-700", children: [_jsx("button", { onClick: () => setView('list'), className: `px-4 py-1.5 text-sm font-medium transition-colors ${view === 'list'
|
|
78
|
+
? 'bg-gray-900 text-white dark:bg-gray-100 dark:text-gray-900'
|
|
79
|
+
: 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100'} rounded-l-md`, children: "List" }), _jsx("button", { onClick: () => setView('map'), className: `px-4 py-1.5 text-sm font-medium transition-colors ${view === 'map'
|
|
80
|
+
? 'bg-gray-900 text-white dark:bg-gray-100 dark:text-gray-900'
|
|
81
|
+
: 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100'} rounded-r-md`, children: "Map" })] })] }), pages.length === 0 ? (_jsx("p", { className: "text-gray-500 dark:text-gray-400", children: "No pages discovered yet." })) : view === 'list' ? (_jsx(PagesListView, { pages: pages, envId: envId, entitySlug: entitySlug, runId: runId, screenshotsByPageId: screenshotsByPageId, apiUrl: baseUrl })) : (_jsx(PagesMapView, { pages: pages, testInteractions: testInteractions, envId: envId, entitySlug: entitySlug, runId: runId, screenshotsByPageId: screenshotsByPageId, apiUrl: baseUrl }))] }));
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=PagesPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PagesPage.js","sourceRoot":"","sources":["../../src/pages/PagesPage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PatternsPage.d.ts","sourceRoot":"","sources":["../../src/pages/PatternsPage.tsx"],"names":[],"mappings":"AA2VA,wBAAgB,YAAY,gCA4H3B"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import { useRunPatterns } from '@sudobility/testomniac_client';
|
|
4
|
+
import { Card } from '@sudobility/components';
|
|
5
|
+
import { SEOHead, useTestomniacApi } from '../context/config';
|
|
6
|
+
import { useRouteParams } from '../context/routing';
|
|
7
|
+
import { SelectField } from '../components/forms/SelectField';
|
|
8
|
+
import { useDashboardEnvironmentContext } from '../hooks/useDashboardEnvironmentContext';
|
|
9
|
+
import { EmptyState } from '../components/states';
|
|
10
|
+
const PATTERN_LABELS = {
|
|
11
|
+
card: 'Card',
|
|
12
|
+
table: 'Table',
|
|
13
|
+
form: 'Form',
|
|
14
|
+
modal: 'Modal',
|
|
15
|
+
toast: 'Toast',
|
|
16
|
+
alert: 'Alert',
|
|
17
|
+
tabs: 'Tabs',
|
|
18
|
+
accordion: 'Accordion',
|
|
19
|
+
carousel: 'Carousel',
|
|
20
|
+
dropdown: 'Dropdown',
|
|
21
|
+
pagination: 'Pagination',
|
|
22
|
+
skeleton: 'Skeleton',
|
|
23
|
+
emptyState: 'Empty State',
|
|
24
|
+
errorMessage: 'Error Message',
|
|
25
|
+
progressBar: 'Progress Bar',
|
|
26
|
+
tooltip: 'Tooltip',
|
|
27
|
+
badge: 'Badge',
|
|
28
|
+
avatar: 'Avatar',
|
|
29
|
+
tag: 'Tag',
|
|
30
|
+
stepper: 'Stepper',
|
|
31
|
+
};
|
|
32
|
+
const PATTERN_ICONS = {
|
|
33
|
+
card: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "2", width: "12", height: "10", rx: "1" }), _jsx("line", { x1: "1", y1: "5.5", x2: "13", y2: "5.5" })] })),
|
|
34
|
+
table: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "12", height: "12", rx: "1" }), _jsx("line", { x1: "1", y1: "5", x2: "13", y2: "5" }), _jsx("line", { x1: "1", y1: "9", x2: "13", y2: "9" }), _jsx("line", { x1: "5", y1: "1", x2: "5", y2: "13" }), _jsx("line", { x1: "9", y1: "1", x2: "9", y2: "13" })] })),
|
|
35
|
+
form: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "2", width: "10", height: "3", rx: "0.5" }), _jsx("rect", { x: "2", y: "7", width: "10", height: "3", rx: "0.5" }), _jsx("rect", { x: "4", y: "11.5", width: "6", height: "1.5", rx: "0.5" })] })),
|
|
36
|
+
modal: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "3", width: "10", height: "8", rx: "1" }), _jsx("line", { x1: "10", y1: "4.5", x2: "10.5", y2: "4.5", strokeWidth: "2" })] })),
|
|
37
|
+
toast: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "9", width: "12", height: "4", rx: "1" }), _jsx("line", { x1: "3", y1: "11", x2: "8", y2: "11" })] })),
|
|
38
|
+
alert: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M7 1L13 12H1L7 1z" }), _jsx("line", { x1: "7", y1: "5", x2: "7", y2: "8" }), _jsx("circle", { cx: "7", cy: "10", r: "0.5", fill: "currentColor" })] })),
|
|
39
|
+
tabs: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "4", width: "12", height: "9", rx: "0.5" }), _jsx("rect", { x: "1", y: "1", width: "4", height: "3", rx: "0.5" }), _jsx("rect", { x: "5.5", y: "1", width: "4", height: "3", rx: "0.5" })] })),
|
|
40
|
+
accordion: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "1", width: "12", height: "3", rx: "0.5" }), _jsx("rect", { x: "1", y: "5.5", width: "12", height: "3", rx: "0.5" }), _jsx("rect", { x: "1", y: "10", width: "12", height: "3", rx: "0.5" }), _jsx("polyline", { points: "10,2.5 11,3 10,3.5" })] })),
|
|
41
|
+
carousel: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { x: "3", y: "2", width: "8", height: "8", rx: "0.5" }), _jsx("polyline", { points: "1,5 2,7 1,9" }), _jsx("polyline", { points: "13,5 12,7 13,9" }), _jsx("circle", { cx: "5.5", cy: "12", r: "0.7", fill: "currentColor" }), _jsx("circle", { cx: "7", cy: "12", r: "0.7", fill: "currentColor" }), _jsx("circle", { cx: "8.5", cy: "12", r: "0.7", fill: "currentColor" })] })),
|
|
42
|
+
dropdown: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "2", width: "10", height: "3", rx: "0.5" }), _jsx("polyline", { points: "9,3 10,4 11,3" }), _jsx("rect", { x: "2", y: "6", width: "10", height: "7", rx: "0.5" }), _jsx("line", { x1: "4", y1: "8", x2: "10", y2: "8" }), _jsx("line", { x1: "4", y1: "10.5", x2: "10", y2: "10.5" })] })),
|
|
43
|
+
pagination: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("polyline", { points: "2,7 3.5,5.5 2,4" }), _jsx("rect", { x: "4.5", y: "4.5", width: "2", height: "5", rx: "0.5" }), _jsx("rect", { x: "7.5", y: "4.5", width: "2", height: "5", rx: "0.5" }), _jsx("polyline", { points: "12,4 10.5,5.5 12,7" })] })),
|
|
44
|
+
skeleton: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "2", width: "5", height: "3", rx: "0.5", strokeDasharray: "2 1" }), _jsx("rect", { x: "8", y: "2", width: "5", height: "3", rx: "0.5", strokeDasharray: "2 1" }), _jsx("rect", { x: "1", y: "7", width: "12", height: "2", rx: "0.5", strokeDasharray: "2 1" }), _jsx("rect", { x: "1", y: "11", width: "8", height: "2", rx: "0.5", strokeDasharray: "2 1" })] })),
|
|
45
|
+
emptyState: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "2", width: "10", height: "10", rx: "1", strokeDasharray: "2 2" }), _jsx("line", { x1: "5", y1: "7", x2: "9", y2: "7" })] })),
|
|
46
|
+
errorMessage: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("circle", { cx: "7", cy: "7", r: "5.5" }), _jsx("line", { x1: "7", y1: "4", x2: "7", y2: "7.5" }), _jsx("circle", { cx: "7", cy: "9.5", r: "0.5", fill: "currentColor" })] })),
|
|
47
|
+
progressBar: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "1", y: "5.5", width: "12", height: "3", rx: "1.5" }), _jsx("rect", { x: "1", y: "5.5", width: "7", height: "3", rx: "1.5", fill: "currentColor", opacity: "0.3" })] })),
|
|
48
|
+
tooltip: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "2", width: "10", height: "6", rx: "1" }), _jsx("path", { d: "M6 8L7 10L8 8" })] })),
|
|
49
|
+
badge: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("rect", { x: "2", y: "4.5", width: "10", height: "5", rx: "2.5" }), _jsx("line", { x1: "5", y1: "7", x2: "9", y2: "7" })] })),
|
|
50
|
+
avatar: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("circle", { cx: "7", cy: "5", r: "3" }), _jsx("path", { d: "M2 13c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5" })] })),
|
|
51
|
+
tag: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M1 7.5V2.5C1 1.9 1.4 1.5 2 1.5H7L13 7.5L7.5 13L1 7.5z" }), _jsx("circle", { cx: "4", cy: "4.5", r: "1", fill: "currentColor" })] })),
|
|
52
|
+
stepper: (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: [_jsx("circle", { cx: "3", cy: "7", r: "2" }), _jsx("circle", { cx: "7", cy: "7", r: "2" }), _jsx("circle", { cx: "11", cy: "7", r: "2" }), _jsx("line", { x1: "5", y1: "7", x2: "5", y2: "7" }), _jsx("line", { x1: "9", y1: "7", x2: "9", y2: "7" })] })),
|
|
53
|
+
};
|
|
54
|
+
export function PatternsPage() {
|
|
55
|
+
const { envId } = useRouteParams();
|
|
56
|
+
const { networkClient, token, baseUrl } = useTestomniacApi();
|
|
57
|
+
const [typeFilter, setTypeFilter] = useState('');
|
|
58
|
+
const { latestRun, isLoading: contextLoading, error: contextError, } = useDashboardEnvironmentContext();
|
|
59
|
+
const { patterns, isLoading, error } = useRunPatterns({
|
|
60
|
+
networkClient,
|
|
61
|
+
baseUrl,
|
|
62
|
+
runId: latestRun?.id ?? 0,
|
|
63
|
+
token: token ?? '',
|
|
64
|
+
enabled: !!envId && !!token && !!latestRun,
|
|
65
|
+
});
|
|
66
|
+
const grouped = useMemo(() => {
|
|
67
|
+
const map = new Map();
|
|
68
|
+
for (const p of patterns) {
|
|
69
|
+
const existing = map.get(p.patternType);
|
|
70
|
+
if (existing) {
|
|
71
|
+
existing.totalCount += p.count;
|
|
72
|
+
if (!existing.pageStateIds.includes(p.pageStateId)) {
|
|
73
|
+
existing.pageStateIds.push(p.pageStateId);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
map.set(p.patternType, {
|
|
78
|
+
patternType: p.patternType,
|
|
79
|
+
totalCount: p.count,
|
|
80
|
+
pageStateIds: [p.pageStateId],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return Array.from(map.values()).sort((a, b) => a.patternType.localeCompare(b.patternType));
|
|
85
|
+
}, [patterns]);
|
|
86
|
+
const uniqueTypes = useMemo(() => grouped.map(g => g.patternType), [grouped]);
|
|
87
|
+
const filteredPatterns = typeFilter ? grouped.filter(g => g.patternType === typeFilter) : grouped;
|
|
88
|
+
if (contextLoading || isLoading) {
|
|
89
|
+
return (_jsx("div", { className: "p-6", children: _jsx("div", { className: "text-center text-gray-500 dark:text-gray-400 py-8", children: "Loading..." }) }));
|
|
90
|
+
}
|
|
91
|
+
if (contextError || error) {
|
|
92
|
+
return (_jsx("div", { className: "p-6", children: _jsxs("div", { className: "text-center text-red-600 dark:text-red-400 py-8", children: ["Error: ", contextError || error] }) }));
|
|
93
|
+
}
|
|
94
|
+
return (_jsxs("div", { className: "p-6", children: [_jsx(SEOHead, { title: "UI Patterns", description: "", noIndex: true }), _jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-gray-100 mb-6", children: "UI Patterns" }), uniqueTypes.length > 1 && (_jsx("div", { className: "mb-4", children: _jsx(SelectField, { value: typeFilter, onChange: setTypeFilter, options: [
|
|
95
|
+
{ value: '', label: 'All Types' },
|
|
96
|
+
...uniqueTypes.map(type => ({
|
|
97
|
+
value: type,
|
|
98
|
+
label: PATTERN_LABELS[type] ?? type,
|
|
99
|
+
})),
|
|
100
|
+
] }) })), filteredPatterns.length === 0 ? (_jsx(EmptyState, { title: "No UI patterns detected", description: "UI patterns will appear here after a scan detects them." })) : (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: filteredPatterns.map(pattern => (_jsxs(Card, { variant: "bordered", padding: "md", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx("span", { className: "text-gray-500 dark:text-gray-400", children: PATTERN_ICONS[pattern.patternType] ?? (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: _jsx("rect", { x: "2", y: "2", width: "10", height: "10", rx: "1" }) })) }), _jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: PATTERN_LABELS[pattern.patternType] ?? pattern.patternType })] }), _jsxs("div", { className: "flex items-center justify-between text-xs text-gray-500 dark:text-gray-400", children: [_jsxs("span", { children: [pattern.totalCount, " instance", pattern.totalCount !== 1 ? 's' : ''] }), _jsxs("span", { children: [pattern.pageStateIds.length, " page state", pattern.pageStateIds.length !== 1 ? 's' : ''] })] })] }, pattern.patternType))) }))] }));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=PatternsPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PatternsPage.js","sourceRoot":"","sources":["../../src/pages/PatternsPage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersonasPage.d.ts","sourceRoot":"","sources":["../../src/pages/PersonasPage.tsx"],"names":[],"mappings":"AAwDA,wBAAgB,YAAY,gCAwR3B"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Alert, Button, ActionButton, Card, Input, Label, TextArea } from '@sudobility/components';
|
|
4
|
+
import { useProductPersonas, useCreatePersona, useUpdatePersona, useDeletePersona, useDetectPersonas, usePersonaUseCases, } from '@sudobility/testomniac_client';
|
|
5
|
+
import { SEOHead, useTestomniacApi } from '../context/config';
|
|
6
|
+
import { useRouteParams } from '../context/routing';
|
|
7
|
+
import { PersonaCell } from '../components/cells';
|
|
8
|
+
import { useDashboardEnvironmentContext } from '../hooks/useDashboardEnvironmentContext';
|
|
9
|
+
import { ErrorState, LoadingState, EmptyState } from '../components/states';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Sub-component: Use Cases (expandable per persona)
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
function PersonaUseCases({ personaId }) {
|
|
14
|
+
const { networkClient, token, baseUrl } = useTestomniacApi();
|
|
15
|
+
const { useCases, isLoading } = usePersonaUseCases({
|
|
16
|
+
networkClient,
|
|
17
|
+
baseUrl,
|
|
18
|
+
personaId,
|
|
19
|
+
token: token ?? '',
|
|
20
|
+
});
|
|
21
|
+
if (isLoading) {
|
|
22
|
+
return _jsx("div", { className: "text-xs text-gray-400 py-2", children: "Loading use cases..." });
|
|
23
|
+
}
|
|
24
|
+
if (useCases.length === 0) {
|
|
25
|
+
return _jsx("div", { className: "text-xs text-gray-400 py-2", children: "No use cases." });
|
|
26
|
+
}
|
|
27
|
+
return (_jsx("div", { className: "space-y-2", children: useCases.map(uc => (_jsxs("div", { className: "text-sm", children: [_jsx("span", { className: "font-medium text-gray-800 dark:text-gray-200", children: uc.title }), uc.description && (_jsxs("span", { className: "text-gray-500 dark:text-gray-400", children: [" \u2014 ", uc.description] }))] }, uc.id))) }));
|
|
28
|
+
}
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Main page
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
export function PersonasPage() {
|
|
33
|
+
const { envId } = useRouteParams();
|
|
34
|
+
const { baseUrl } = useTestomniacApi();
|
|
35
|
+
const { networkClient, token, productId, isLoading: contextLoading, error: contextError, } = useDashboardEnvironmentContext();
|
|
36
|
+
// Data
|
|
37
|
+
const { personas, isLoading, error, refetch } = useProductPersonas({
|
|
38
|
+
networkClient,
|
|
39
|
+
baseUrl,
|
|
40
|
+
productId: productId ?? 0,
|
|
41
|
+
token,
|
|
42
|
+
enabled: !!envId && !!token && !!productId,
|
|
43
|
+
});
|
|
44
|
+
// Mutations
|
|
45
|
+
const { createPersona, isCreating } = useCreatePersona({
|
|
46
|
+
networkClient,
|
|
47
|
+
baseUrl,
|
|
48
|
+
token,
|
|
49
|
+
});
|
|
50
|
+
const { updatePersona, isUpdating } = useUpdatePersona({
|
|
51
|
+
networkClient,
|
|
52
|
+
baseUrl,
|
|
53
|
+
token,
|
|
54
|
+
});
|
|
55
|
+
const { deletePersona } = useDeletePersona({
|
|
56
|
+
networkClient,
|
|
57
|
+
baseUrl,
|
|
58
|
+
token,
|
|
59
|
+
});
|
|
60
|
+
const { detectPersonas, isDetecting } = useDetectPersonas({
|
|
61
|
+
networkClient,
|
|
62
|
+
baseUrl,
|
|
63
|
+
token,
|
|
64
|
+
});
|
|
65
|
+
// Form state
|
|
66
|
+
const [showForm, setShowForm] = useState(false);
|
|
67
|
+
const [editingPersona, setEditingPersona] = useState(null);
|
|
68
|
+
const [formTitle, setFormTitle] = useState('');
|
|
69
|
+
const [formDescription, setFormDescription] = useState('');
|
|
70
|
+
const [formError, setFormError] = useState(null);
|
|
71
|
+
// Detect state
|
|
72
|
+
const [showDetectWarning, setShowDetectWarning] = useState(false);
|
|
73
|
+
const [detectError, setDetectError] = useState(null);
|
|
74
|
+
// Expand state
|
|
75
|
+
const [expandedId, setExpandedId] = useState(null);
|
|
76
|
+
// Handlers
|
|
77
|
+
const openCreateForm = () => {
|
|
78
|
+
setEditingPersona(null);
|
|
79
|
+
setFormTitle('');
|
|
80
|
+
setFormDescription('');
|
|
81
|
+
setFormError(null);
|
|
82
|
+
setShowForm(true);
|
|
83
|
+
};
|
|
84
|
+
const openEditForm = (persona) => {
|
|
85
|
+
setEditingPersona(persona);
|
|
86
|
+
setFormTitle(persona.title);
|
|
87
|
+
setFormDescription(persona.description ?? '');
|
|
88
|
+
setFormError(null);
|
|
89
|
+
setShowForm(true);
|
|
90
|
+
};
|
|
91
|
+
const closeForm = () => {
|
|
92
|
+
setShowForm(false);
|
|
93
|
+
setEditingPersona(null);
|
|
94
|
+
setFormError(null);
|
|
95
|
+
};
|
|
96
|
+
const handleSave = async () => {
|
|
97
|
+
if (!formTitle.trim()) {
|
|
98
|
+
setFormError('Title is required');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
setFormError(null);
|
|
102
|
+
try {
|
|
103
|
+
if (editingPersona) {
|
|
104
|
+
await updatePersona({
|
|
105
|
+
personaId: editingPersona.id,
|
|
106
|
+
title: formTitle.trim(),
|
|
107
|
+
description: formDescription.trim() || undefined,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
await createPersona({
|
|
112
|
+
productId: productId,
|
|
113
|
+
title: formTitle.trim(),
|
|
114
|
+
description: formDescription.trim(),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
closeForm();
|
|
118
|
+
refetch();
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
setFormError(err instanceof Error ? err.message : 'Save failed');
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const handleDelete = async (personaId) => {
|
|
125
|
+
await deletePersona(personaId);
|
|
126
|
+
refetch();
|
|
127
|
+
};
|
|
128
|
+
const handleDetect = async () => {
|
|
129
|
+
if (personas.length > 0) {
|
|
130
|
+
setShowDetectWarning(true);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
await runDetect();
|
|
134
|
+
};
|
|
135
|
+
const runDetect = async () => {
|
|
136
|
+
setShowDetectWarning(false);
|
|
137
|
+
setDetectError(null);
|
|
138
|
+
try {
|
|
139
|
+
await detectPersonas({ productId: productId });
|
|
140
|
+
refetch();
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
setDetectError(err instanceof Error ? err.message : 'Detection failed');
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
if (contextError || error) {
|
|
147
|
+
return _jsx(ErrorState, { message: contextError || error || '' });
|
|
148
|
+
}
|
|
149
|
+
return (_jsxs("div", { className: "p-6", children: [_jsx(SEOHead, { title: "Personas", description: "", noIndex: true }), _jsxs("div", { className: "flex items-center justify-between mb-6", children: [_jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-gray-100", children: "Personas" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ActionButton, { variant: "primary", className: "bg-purple-600 hover:bg-purple-700", onClick: handleDetect, disabled: !productId, isLoading: isDetecting, loadingText: "Detecting...", children: "Detect Personas" }), _jsx(Button, { variant: "primary", onClick: showForm ? closeForm : openCreateForm, children: showForm ? 'Cancel' : 'New Persona' })] })] }), detectError && _jsx(Alert, { variant: "error", description: detectError, className: "mb-4" }), showDetectWarning && (_jsxs("div", { className: "mb-4 p-4 rounded-lg border border-amber-300 dark:border-amber-600 bg-amber-50 dark:bg-amber-900/20", children: [_jsxs("p", { className: "text-sm font-medium text-amber-800 dark:text-amber-200", children: ["Detecting personas will replace all ", personas.length, " existing persona", personas.length !== 1 ? 's' : '', ". This cannot be undone."] }), _jsxs("div", { className: "flex items-center gap-2 mt-3", children: [_jsx(ActionButton, { variant: "primary", size: "sm", className: "bg-amber-600 hover:bg-amber-700", onClick: runDetect, isLoading: isDetecting, loadingText: "Detecting...", children: "Continue" }), _jsx(Button, { variant: "secondary", size: "sm", onClick: () => setShowDetectWarning(false), children: "Cancel" })] })] })), showForm && (_jsxs(Card, { variant: "bordered", className: "mb-6", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3", children: editingPersona ? 'Edit Persona' : 'New Persona' }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx(Label, { className: "mb-1 block", children: "Title" }), _jsx(Input, { type: "text", value: formTitle, onChange: e => setFormTitle(e.target.value), placeholder: "e.g. Power User, First-Time Visitor", className: "w-full" })] }), _jsxs("div", { children: [_jsx(Label, { className: "mb-1 block", children: "Description" }), _jsx(TextArea, { value: formDescription, onChange: setFormDescription, placeholder: "Describe this persona's goals, behavior, and technical proficiency", rows: 3 })] }), formError && _jsx("div", { className: "text-sm text-red-600 dark:text-red-400", children: formError }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ActionButton, { variant: "primary", onClick: handleSave, isLoading: isCreating || isUpdating, loadingText: "Saving...", children: "Save" }), _jsx(Button, { variant: "secondary", onClick: closeForm, children: "Cancel" })] })] })] })), (contextLoading || isLoading) && _jsx(LoadingState, { message: "Loading personas..." }), !isLoading && personas.length === 0 && !showForm && (_jsx(EmptyState, { title: "No personas yet", description: 'Create a persona manually or use "Detect Personas" to generate them from your discovered pages.' })), !isLoading && personas.length > 0 && (_jsx("div", { className: "space-y-2", children: personas.map((persona) => (_jsxs("div", { children: [_jsx(PersonaCell, { persona: persona, onClick: () => setExpandedId(expandedId === persona.id ? null : persona.id), actions: _jsxs(_Fragment, { children: [_jsx(Button, { variant: "link", size: "sm", onClick: () => openEditForm(persona), children: "Edit" }), _jsx(Button, { variant: "link", size: "sm", className: "text-red-600 hover:text-red-700", onClick: () => handleDelete(persona.id), children: "Delete" })] }) }), expandedId === persona.id && (_jsxs(Card, { variant: "bordered", className: "mt-1", children: [_jsx("h4", { className: "text-xs font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-2", children: "Use Cases" }), _jsx(PersonaUseCases, { personaId: persona.id })] }))] }, persona.id))) }))] }));
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=PersonasPage.js.map
|