@assistkick/create 1.7.0 → 1.9.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/bin/create.js +0 -0
- package/package.json +9 -7
- package/templates/assistkick-product-system/.env.example +1 -0
- package/templates/assistkick-product-system/local.db +0 -0
- package/templates/assistkick-product-system/package.json +4 -2
- package/templates/assistkick-product-system/packages/backend/package.json +2 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +165 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +358 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +356 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +96 -1
- package/templates/assistkick-product-system/packages/backend/src/routes/graph.ts +1 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/kanban.ts +61 -6
- package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +200 -84
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +6 -3
- package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +53 -17
- package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +218 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +119 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +158 -0
- package/templates/assistkick-product-system/packages/backend/src/server.ts +60 -9
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +489 -0
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +416 -0
- package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.test.ts +189 -0
- package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.ts +182 -0
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +43 -77
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +16 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +73 -2
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +4 -4
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +87 -11
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +210 -69
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +210 -215
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +162 -0
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +148 -0
- package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +11 -5
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.test.ts +64 -0
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +134 -0
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.test.ts +256 -0
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +258 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_group_service.ts +106 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.test.ts +275 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.ts +245 -0
- package/templates/assistkick-product-system/packages/frontend/package-lock.json +3455 -0
- package/templates/assistkick-product-system/packages/frontend/package.json +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/App.tsx +8 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +458 -18
- package/templates/assistkick-product-system/packages/frontend/src/api/client_files.test.ts +172 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client_video.test.ts +238 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +307 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/CoherenceView.tsx +82 -66
- package/templates/assistkick-product-system/packages/frontend/src/components/CompositionPlaceholder.tsx +97 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/DesignSystemView.tsx +20 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +57 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +313 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeContextMenu.tsx +61 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +73 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +404 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx +187 -56
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +71 -73
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphSettings.tsx +8 -8
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphView.tsx +1 -1
- package/templates/assistkick-product-system/packages/frontend/src/components/InviteUserDialog.tsx +15 -11
- package/templates/assistkick-product-system/packages/frontend/src/components/IterationCommentModal.tsx +80 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +263 -167
- package/templates/assistkick-product-system/packages/frontend/src/components/LoginPage.tsx +14 -14
- package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +54 -33
- package/templates/assistkick-product-system/packages/frontend/src/components/QaIssueSheet.tsx +32 -49
- package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +43 -48
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +121 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +20 -14
- package/templates/assistkick-product-system/packages/frontend/src/components/UsersView.tsx +52 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/VideoGallery.tsx +313 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/VideographyView.tsx +250 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/WorkflowsView.tsx +474 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/AccentBorderList.tsx +53 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/Button.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonGroup.tsx +29 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonShowcase.tsx +221 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/CardGlass.tsx +141 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/CompletionRing.tsx +30 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ContentCard.tsx +34 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/IconButton.tsx +74 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCard.tsx +103 -87
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCardShowcase.tsx +9 -188
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/Kbd.tsx +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KindBadge.tsx +21 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/NavBarSidekick.tsx +81 -37
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/SidePanelShowcase.tsx +370 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/SideSheet.tsx +64 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/StatusDot.tsx +18 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCardPositionNode.tsx +36 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCycleCountNode.tsx +60 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/EndNode.tsx +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GenerateTTSNode.tsx +52 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +189 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +123 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RebuildBundleNode.tsx +20 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RenderVideoNode.tsx +72 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RunAgentNode.tsx +51 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/SetCardMetadataNode.tsx +53 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/StartNode.tsx +18 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/TransitionCardNode.tsx +59 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +341 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +643 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/autoLayout.ts +103 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/edgeColors.ts +35 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +246 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.test.ts +119 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +136 -0
- package/templates/assistkick-product-system/packages/frontend/src/constants/graph.ts +13 -11
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useAutoSave.ts +75 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useToast.tsx +16 -3
- package/templates/assistkick-product-system/packages/frontend/src/pages/accept_invitation_page.tsx +30 -27
- package/templates/assistkick-product-system/packages/frontend/src/pages/forgot_password_page.tsx +18 -15
- package/templates/assistkick-product-system/packages/frontend/src/pages/register_page.tsx +21 -18
- package/templates/assistkick-product-system/packages/frontend/src/pages/reset_password_page.tsx +28 -25
- package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +1 -1
- package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +6 -3
- package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +4 -4
- package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +275 -3535
- package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.test.ts +167 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.ts +101 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.test.ts +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.ts +17 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.test.ts +145 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.ts +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.test.ts +4 -10
- package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.ts +19 -1
- package/templates/assistkick-product-system/packages/frontend/vite.config.ts +5 -0
- package/templates/assistkick-product-system/packages/shared/db/local.db +0 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0004_tidy_matthew_murdock.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0005_mysterious_falcon.sql +692 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0006_next_venom.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0007_deep_barracuda.sql +39 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0008_puzzling_hannibal_king.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0009_amused_beast.sql +8 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0010_spotty_moira_mactaggert.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0011_goofy_snowbird.sql +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0011_supreme_doctor_octopus.sql +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0013_reflective_prowler.sql +15 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0014_nifty_punisher.sql +15 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0004_snapshot.json +921 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0005_snapshot.json +1042 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0006_snapshot.json +1101 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0007_snapshot.json +1336 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0008_snapshot.json +1275 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0009_snapshot.json +1327 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0010_snapshot.json +1393 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0011_snapshot.json +1436 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0013_snapshot.json +1538 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0014_snapshot.json +1545 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +77 -0
- package/templates/assistkick-product-system/packages/shared/db/schema.ts +114 -0
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +32 -7
- package/templates/assistkick-product-system/packages/shared/lib/constants.ts +9 -0
- package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +12 -4
- package/templates/assistkick-product-system/packages/shared/lib/graph.ts +5 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +1999 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +1437 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +211 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +43 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +13 -2
- package/templates/assistkick-product-system/packages/shared/tools/get_kanban.ts +1 -1
- package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.test.ts +226 -0
- package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.ts +251 -0
- package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -2
- package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.test.ts +10 -0
- package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.ts +6 -0
- package/templates/assistkick-product-system/packages/video/Root.tsx +85 -0
- package/templates/assistkick-product-system/packages/video/components/email_scene.tsx +231 -0
- package/templates/assistkick-product-system/packages/video/components/outro_scene.tsx +153 -0
- package/templates/assistkick-product-system/packages/video/components/part_divider.tsx +90 -0
- package/templates/assistkick-product-system/packages/video/components/scene.tsx +226 -0
- package/templates/assistkick-product-system/packages/video/components/theme.ts +22 -0
- package/templates/assistkick-product-system/packages/video/components/title_scene.tsx +169 -0
- package/templates/assistkick-product-system/packages/video/components/video_split_layout.tsx +84 -0
- package/templates/assistkick-product-system/packages/video/compositions/.gitkeep +0 -0
- package/templates/assistkick-product-system/packages/video/index.ts +4 -0
- package/templates/assistkick-product-system/packages/video/package.json +28 -0
- package/templates/assistkick-product-system/packages/video/remotion.config.ts +11 -0
- package/templates/assistkick-product-system/packages/video/scripts/process_script.test.ts +326 -0
- package/templates/assistkick-product-system/packages/video/scripts/process_script.ts +630 -0
- package/templates/assistkick-product-system/packages/video/style.css +1 -0
- package/templates/assistkick-product-system/packages/video/tsconfig.json +18 -0
- package/templates/assistkick-product-system/tests/graph_legend.test.ts +2 -1
- package/templates/assistkick-product-system/tests/video_render_service.test.ts +181 -0
- package/templates/assistkick-product-system/tests/web_terminal.test.ts +219 -455
- package/templates/assistkick-product-system/tests/workflow_integration.test.ts +341 -0
- package/templates/skills/assistkick-developer/SKILL.md +3 -0
- package/templates/skills/assistkick-developer/references/react_development_guidelines.md +225 -0
- package/templates/skills/product-system/graph.json +1890 -0
- package/templates/skills/product-system/kanban.json +304 -0
- package/templates/skills/product-system/nodes/comp_001.md +56 -0
- package/templates/skills/product-system/nodes/comp_002.md +57 -0
- package/templates/skills/product-system/nodes/data_001.md +51 -0
- package/templates/skills/product-system/nodes/data_002.md +40 -0
- package/templates/skills/product-system/nodes/data_004.md +38 -0
- package/templates/skills/product-system/nodes/dec_001.md +34 -0
- package/templates/skills/product-system/nodes/dec_016.md +32 -0
- package/templates/skills/product-system/nodes/feat_008.md +30 -0
- package/templates/skills/video-composition-agent/SKILL.md +232 -0
- package/templates/skills/video-script-writer/SKILL.md +136 -0
|
@@ -54,12 +54,12 @@ export function LoginPage({ onLoginSuccess }: LoginPageProps) {
|
|
|
54
54
|
}, [email, password, onLoginSuccess]);
|
|
55
55
|
|
|
56
56
|
return (
|
|
57
|
-
<div className="
|
|
58
|
-
<div className="
|
|
59
|
-
<div className="
|
|
60
|
-
<span className="
|
|
57
|
+
<div className="flex items-center justify-center w-full h-screen bg-surface">
|
|
58
|
+
<div className="w-[360px] p-8 bg-surface-alt border border-edge rounded">
|
|
59
|
+
<div className="flex items-center justify-between mb-6">
|
|
60
|
+
<span className="font-mono text-base text-content tracking-wide">login</span>
|
|
61
61
|
<button
|
|
62
|
-
className="
|
|
62
|
+
className="bg-transparent border border-edge rounded w-7 h-7 text-content-secondary text-sm cursor-pointer flex items-center justify-center transition-[border-color,color] duration-150 hover:border-content hover:text-content"
|
|
63
63
|
onClick={toggleTheme}
|
|
64
64
|
title={`Switch to ${theme === 'dark' ? 'light' : 'dark'} theme`}
|
|
65
65
|
>
|
|
@@ -67,11 +67,11 @@ export function LoginPage({ onLoginSuccess }: LoginPageProps) {
|
|
|
67
67
|
</button>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
70
|
-
<form className="
|
|
71
|
-
<label className="
|
|
70
|
+
<form className="flex flex-col gap-2" onSubmit={handleSubmit}>
|
|
71
|
+
<label className="font-mono text-[11px] text-content-secondary mt-1" htmlFor="login-email">email</label>
|
|
72
72
|
<input
|
|
73
73
|
id="login-email"
|
|
74
|
-
className="
|
|
74
|
+
className="bg-surface-raised border border-edge rounded text-content font-mono text-[13px] py-2 px-2.5 outline-none transition-[border-color] duration-150 focus:border-accent placeholder:text-content-muted disabled:opacity-60"
|
|
75
75
|
type="email"
|
|
76
76
|
value={email}
|
|
77
77
|
onChange={e => setEmail(e.target.value)}
|
|
@@ -81,10 +81,10 @@ export function LoginPage({ onLoginSuccess }: LoginPageProps) {
|
|
|
81
81
|
disabled={submitting}
|
|
82
82
|
/>
|
|
83
83
|
|
|
84
|
-
<label className="
|
|
84
|
+
<label className="font-mono text-[11px] text-content-secondary mt-1" htmlFor="login-password">password</label>
|
|
85
85
|
<input
|
|
86
86
|
id="login-password"
|
|
87
|
-
className="
|
|
87
|
+
className="bg-surface-raised border border-edge rounded text-content font-mono text-[13px] py-2 px-2.5 outline-none transition-[border-color] duration-150 focus:border-accent placeholder:text-content-muted disabled:opacity-60"
|
|
88
88
|
type="password"
|
|
89
89
|
value={password}
|
|
90
90
|
onChange={e => setPassword(e.target.value)}
|
|
@@ -93,10 +93,10 @@ export function LoginPage({ onLoginSuccess }: LoginPageProps) {
|
|
|
93
93
|
disabled={submitting}
|
|
94
94
|
/>
|
|
95
95
|
|
|
96
|
-
{error && <div className="
|
|
96
|
+
{error && <div className="font-mono text-[11px] text-error mt-1">{error}</div>}
|
|
97
97
|
|
|
98
98
|
<button
|
|
99
|
-
className="
|
|
99
|
+
className="mt-3 bg-transparent border border-accent rounded text-accent font-mono text-[13px] py-2 px-3.5 cursor-pointer transition-[background,color] duration-150 hover:enabled:bg-accent hover:enabled:text-white disabled:opacity-50 disabled:cursor-not-allowed"
|
|
100
100
|
type="submit"
|
|
101
101
|
disabled={submitting}
|
|
102
102
|
>
|
|
@@ -104,10 +104,10 @@ export function LoginPage({ onLoginSuccess }: LoginPageProps) {
|
|
|
104
104
|
</button>
|
|
105
105
|
</form>
|
|
106
106
|
|
|
107
|
-
<p className="
|
|
107
|
+
<p className="font-mono text-xs text-content-secondary mt-4 text-center">
|
|
108
108
|
<Link to="/forgot-password">Forgot password?</Link>
|
|
109
109
|
</p>
|
|
110
|
-
<p className="
|
|
110
|
+
<p className="font-mono text-xs text-content-secondary mt-2 text-center">
|
|
111
111
|
No account yet? <Link to="/register">Register</Link>
|
|
112
112
|
</p>
|
|
113
113
|
</div>
|
package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx
CHANGED
|
@@ -5,7 +5,7 @@ interface ProjectSelectorProps {
|
|
|
5
5
|
projects: Project[];
|
|
6
6
|
selectedProjectId: string | null;
|
|
7
7
|
onSelect: (id: string) => void;
|
|
8
|
-
onCreate: (name: string) => Promise<any>;
|
|
8
|
+
onCreate: (name: string, type?: string) => Promise<any>;
|
|
9
9
|
onRename: (id: string, name: string) => Promise<void>;
|
|
10
10
|
onArchive: (id: string) => Promise<void>;
|
|
11
11
|
onOpenGitModal?: (project: Project) => void;
|
|
@@ -17,6 +17,7 @@ export function ProjectSelector({
|
|
|
17
17
|
const [open, setOpen] = useState(false);
|
|
18
18
|
const [creating, setCreating] = useState(false);
|
|
19
19
|
const [newName, setNewName] = useState('');
|
|
20
|
+
const [newType, setNewType] = useState<'software' | 'video'>('software');
|
|
20
21
|
const [renamingId, setRenamingId] = useState<string | null>(null);
|
|
21
22
|
const [renameValue, setRenameValue] = useState('');
|
|
22
23
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
@@ -53,8 +54,9 @@ export function ProjectSelector({
|
|
|
53
54
|
const trimmed = newName.trim();
|
|
54
55
|
if (!trimmed) return;
|
|
55
56
|
try {
|
|
56
|
-
await onCreate(trimmed);
|
|
57
|
+
await onCreate(trimmed, newType);
|
|
57
58
|
setNewName('');
|
|
59
|
+
setNewType('software');
|
|
58
60
|
setCreating(false);
|
|
59
61
|
setOpen(false);
|
|
60
62
|
} catch {
|
|
@@ -83,30 +85,30 @@ export function ProjectSelector({
|
|
|
83
85
|
};
|
|
84
86
|
|
|
85
87
|
return (
|
|
86
|
-
<div className="
|
|
88
|
+
<div className="relative" ref={dropdownRef}>
|
|
87
89
|
<button
|
|
88
|
-
className="
|
|
90
|
+
className="flex items-center gap-1.5 py-[5px] px-2.5 bg-transparent border border-edge rounded text-content font-mono text-xs cursor-pointer transition-[border-color,background] duration-150 max-w-[200px] hover:bg-tab-hover hover:border-accent"
|
|
89
91
|
onClick={() => setOpen(v => !v)}
|
|
90
92
|
title="Select project"
|
|
91
93
|
>
|
|
92
|
-
<span className="
|
|
94
|
+
<span className="overflow-hidden text-ellipsis whitespace-nowrap">
|
|
93
95
|
{selectedProject?.name || 'No project'}
|
|
94
96
|
</span>
|
|
95
|
-
<span className="
|
|
97
|
+
<span className="text-[10px] text-content-muted shrink-0">{open ? '\u25B4' : '\u25BE'}</span>
|
|
96
98
|
</button>
|
|
97
99
|
|
|
98
100
|
{open && (
|
|
99
|
-
<div className="
|
|
100
|
-
<div className="
|
|
101
|
+
<div className="absolute top-[calc(100%+4px)] left-0 min-w-[220px] max-w-[300px] bg-panel border border-edge rounded-md shadow-[0_4px_12px_var(--panel-shadow)] z-[200] overflow-hidden">
|
|
102
|
+
<div className="max-h-60 overflow-y-auto py-1">
|
|
101
103
|
{projects.map(project => (
|
|
102
104
|
<div
|
|
103
105
|
key={project.id}
|
|
104
|
-
className={`
|
|
106
|
+
className={`group flex items-center pr-1 hover:bg-tab-hover${project.id === selectedProjectId ? ' bg-tab-active' : ''}`}
|
|
105
107
|
>
|
|
106
108
|
{renamingId === project.id ? (
|
|
107
109
|
<input
|
|
108
110
|
ref={renameInputRef}
|
|
109
|
-
className="
|
|
111
|
+
className="flex-1 py-[5px] px-2 bg-surface border border-accent rounded-sm text-content font-mono text-xs outline-none mx-1 my-0.5"
|
|
110
112
|
value={renameValue}
|
|
111
113
|
onChange={e => setRenameValue(e.target.value)}
|
|
112
114
|
onKeyDown={e => {
|
|
@@ -118,15 +120,18 @@ export function ProjectSelector({
|
|
|
118
120
|
) : (
|
|
119
121
|
<>
|
|
120
122
|
<button
|
|
121
|
-
className="
|
|
123
|
+
className="flex-1 flex items-center gap-1.5 text-left py-1.5 px-2 bg-none border-none text-content font-mono text-xs cursor-pointer overflow-hidden"
|
|
122
124
|
onClick={() => { onSelect(project.id); setOpen(false); }}
|
|
123
125
|
>
|
|
124
|
-
{project.name}
|
|
126
|
+
<span className="overflow-hidden text-ellipsis whitespace-nowrap">{project.name}</span>
|
|
127
|
+
{project.type === 'video' && (
|
|
128
|
+
<span className="shrink-0 rounded-full bg-purple-500/15 px-1.5 py-0.5 text-[9px] font-bold text-purple-400">Video</span>
|
|
129
|
+
)}
|
|
125
130
|
</button>
|
|
126
|
-
<div className="
|
|
131
|
+
<div className="flex gap-0.5 opacity-0 transition-opacity duration-150 group-hover:opacity-100">
|
|
127
132
|
{onOpenGitModal && (
|
|
128
133
|
<button
|
|
129
|
-
className={`
|
|
134
|
+
className={`bg-none border-none text-xs cursor-pointer px-1 py-0.5 rounded-sm transition-[color,background] duration-150 hover:text-content hover:bg-surface-raised ${project.repoUrl ? 'text-accent' : 'text-content-secondary'}`}
|
|
130
135
|
title="Git Repository"
|
|
131
136
|
onClick={(e) => {
|
|
132
137
|
e.stopPropagation();
|
|
@@ -140,7 +145,7 @@ export function ProjectSelector({
|
|
|
140
145
|
</button>
|
|
141
146
|
)}
|
|
142
147
|
<button
|
|
143
|
-
className="
|
|
148
|
+
className="bg-none border-none text-content-muted text-xs cursor-pointer px-1 py-0.5 rounded-sm transition-[color,background] duration-150 hover:text-content hover:bg-surface-raised"
|
|
144
149
|
title="Rename"
|
|
145
150
|
onClick={(e) => {
|
|
146
151
|
e.stopPropagation();
|
|
@@ -152,7 +157,7 @@ export function ProjectSelector({
|
|
|
152
157
|
</button>
|
|
153
158
|
{!project.isDefault && (
|
|
154
159
|
<button
|
|
155
|
-
className="
|
|
160
|
+
className="bg-none border-none text-content-muted text-xs cursor-pointer px-1 py-0.5 rounded-sm transition-[color,background] duration-150 hover:text-content hover:bg-surface-raised hover:!text-error"
|
|
156
161
|
title="Archive"
|
|
157
162
|
onClick={(e) => {
|
|
158
163
|
e.stopPropagation();
|
|
@@ -169,27 +174,43 @@ export function ProjectSelector({
|
|
|
169
174
|
))}
|
|
170
175
|
</div>
|
|
171
176
|
|
|
172
|
-
<div className="
|
|
177
|
+
<div className="border-t border-edge p-1">
|
|
173
178
|
{creating ? (
|
|
174
|
-
<div className="
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
179
|
+
<div className="flex flex-col gap-1">
|
|
180
|
+
<div className="flex gap-1 items-center">
|
|
181
|
+
<input
|
|
182
|
+
ref={createInputRef}
|
|
183
|
+
className="flex-1 py-[5px] px-2 bg-surface border border-accent rounded-sm text-content font-mono text-xs outline-none mx-1 my-0.5"
|
|
184
|
+
placeholder="Project name..."
|
|
185
|
+
value={newName}
|
|
186
|
+
onChange={e => setNewName(e.target.value)}
|
|
187
|
+
onKeyDown={e => {
|
|
188
|
+
if (e.key === 'Enter') handleCreate();
|
|
189
|
+
if (e.key === 'Escape') { setCreating(false); setNewName(''); setNewType('software'); }
|
|
190
|
+
}}
|
|
191
|
+
/>
|
|
192
|
+
<button className="bg-accent border-none text-white text-sm font-bold w-7 h-7 rounded-sm cursor-pointer flex items-center justify-center shrink-0" onClick={handleCreate}>
|
|
193
|
+
+
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
<div className="flex gap-1 px-1.5">
|
|
197
|
+
<button
|
|
198
|
+
className={`px-2 py-0.5 rounded-sm text-[10px] font-mono border cursor-pointer transition-colors ${newType === 'software' ? 'bg-accent/15 border-accent text-accent' : 'bg-transparent border-edge text-content-muted hover:border-content/30'}`}
|
|
199
|
+
onClick={() => setNewType('software')}
|
|
200
|
+
>
|
|
201
|
+
Software
|
|
202
|
+
</button>
|
|
203
|
+
<button
|
|
204
|
+
className={`px-2 py-0.5 rounded-sm text-[10px] font-mono border cursor-pointer transition-colors ${newType === 'video' ? 'bg-accent/15 border-accent text-accent' : 'bg-transparent border-edge text-content-muted hover:border-content/30'}`}
|
|
205
|
+
onClick={() => setNewType('video')}
|
|
206
|
+
>
|
|
207
|
+
Video
|
|
208
|
+
</button>
|
|
209
|
+
</div>
|
|
189
210
|
</div>
|
|
190
211
|
) : (
|
|
191
212
|
<button
|
|
192
|
-
className="
|
|
213
|
+
className="w-full py-1.5 px-2 bg-none border-none text-accent font-mono text-xs cursor-pointer text-left rounded-sm transition-background duration-150 hover:bg-tab-hover"
|
|
193
214
|
onClick={() => setCreating(true)}
|
|
194
215
|
>
|
|
195
216
|
+ New Project
|
package/templates/assistkick-product-system/packages/frontend/src/components/QaIssueSheet.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React, { useState, useEffect,
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { apiClient } from '../api/client';
|
|
3
3
|
import { useQaSheetStore } from '../stores/useQaSheetStore';
|
|
4
|
+
import { SideSheet } from './ds/SideSheet';
|
|
4
5
|
|
|
5
6
|
export function QaIssueSheet() {
|
|
6
7
|
const {
|
|
@@ -8,7 +9,6 @@ export function QaIssueSheet() {
|
|
|
8
9
|
reviews: initialReviews, close,
|
|
9
10
|
} = useQaSheetStore();
|
|
10
11
|
|
|
11
|
-
const sheetRef = useRef<HTMLDivElement>(null);
|
|
12
12
|
const [notes, setNotes] = useState<any[]>(initialNotes);
|
|
13
13
|
const [reviews, setReviews] = useState<any[]>(initialReviews);
|
|
14
14
|
const [newNoteText, setNewNoteText] = useState('');
|
|
@@ -25,19 +25,6 @@ export function QaIssueSheet() {
|
|
|
25
25
|
setNewNoteText('');
|
|
26
26
|
}, [featureId, initialNotes, initialReviews]);
|
|
27
27
|
|
|
28
|
-
// Close on outside click
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (!isOpen) return;
|
|
31
|
-
const handleClick = (e: MouseEvent) => {
|
|
32
|
-
if (sheetRef.current && !sheetRef.current.contains(e.target as Node)) {
|
|
33
|
-
if ((e.target as HTMLElement).closest('.kanban-issues-btn')) return;
|
|
34
|
-
close();
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
document.addEventListener('click', handleClick);
|
|
38
|
-
return () => document.removeEventListener('click', handleClick);
|
|
39
|
-
}, [isOpen, close]);
|
|
40
|
-
|
|
41
28
|
const refreshNotes = useCallback(async () => {
|
|
42
29
|
if (!featureId) return;
|
|
43
30
|
try {
|
|
@@ -96,63 +83,59 @@ export function QaIssueSheet() {
|
|
|
96
83
|
};
|
|
97
84
|
|
|
98
85
|
return (
|
|
99
|
-
<
|
|
100
|
-
<div className="
|
|
101
|
-
<
|
|
102
|
-
<button className="qa-sheet-close" onClick={close}>×</button>
|
|
103
|
-
</div>
|
|
104
|
-
<div className="qa-sheet-body">
|
|
105
|
-
<div className="qa-sheet-subtitle">
|
|
86
|
+
<SideSheet isOpen={isOpen} onClose={close} title={`${featureId} — ${featureName}`} zIndex={260}>
|
|
87
|
+
<div className="flex flex-col gap-3">
|
|
88
|
+
<div className="text-[11px] text-content-muted uppercase tracking-wider">
|
|
106
89
|
{isEditable ? 'Report and manage QA issues' : 'Issues (read-only)'}
|
|
107
90
|
</div>
|
|
108
91
|
|
|
109
92
|
{reviews.length > 0 && (
|
|
110
|
-
<div className="
|
|
111
|
-
<div className="
|
|
93
|
+
<div className="mb-4 border-b border-edge pb-3">
|
|
94
|
+
<div className="text-[11px] font-semibold uppercase tracking-wide text-content-secondary mb-2">Review History</div>
|
|
112
95
|
{reviews.map((review: any, i: number) => (
|
|
113
|
-
<div key={i} className="
|
|
114
|
-
<div className="
|
|
115
|
-
<span className="
|
|
116
|
-
<span className={`
|
|
96
|
+
<div key={i} className="bg-surface-alt rounded-md px-2.5 py-2 mb-1.5">
|
|
97
|
+
<div className="flex items-center gap-2 text-xs">
|
|
98
|
+
<span className="font-semibold text-content">Cycle {review.cycle}</span>
|
|
99
|
+
<span className={`text-[10px] font-semibold px-1.5 py-px rounded-sm uppercase ${review.status === 'approved' ? 'bg-[#16a34a22] text-[#16a34a]' : 'bg-[#dc262622] text-[#dc2626]'}`}>
|
|
117
100
|
{review.status === 'approved' ? 'Approved' : 'Rejected'}
|
|
118
101
|
</span>
|
|
119
|
-
<span className="
|
|
102
|
+
<span className="text-content-secondary text-[11px] ml-auto">{formatDate(review.timestamp)}</span>
|
|
120
103
|
</div>
|
|
121
|
-
{review.reason && <div className="
|
|
104
|
+
{review.reason && <div className="mt-1.5 text-xs text-content-secondary whitespace-pre-wrap leading-snug max-h-[120px] overflow-y-auto">{review.reason}</div>}
|
|
122
105
|
</div>
|
|
123
106
|
))}
|
|
124
107
|
</div>
|
|
125
108
|
)}
|
|
126
109
|
|
|
127
110
|
{notes.length === 0 ? (
|
|
128
|
-
<div className="
|
|
111
|
+
<div className="text-xs text-content-muted p-4 text-center">No issues reported yet.</div>
|
|
129
112
|
) : (
|
|
130
|
-
<div className="
|
|
113
|
+
<div className="flex flex-col gap-2">
|
|
131
114
|
{notes.map((note: any) => (
|
|
132
|
-
<div key={note.id} className="
|
|
115
|
+
<div key={note.id} className="bg-surface-raised border border-edge rounded px-3 py-2.5">
|
|
133
116
|
{editingNoteId === note.id ? (
|
|
134
|
-
<div className="
|
|
117
|
+
<div className="flex flex-col gap-2">
|
|
135
118
|
<textarea
|
|
136
|
-
className="
|
|
119
|
+
className="w-full bg-surface-raised border border-edge rounded text-content font-mono text-xs px-3 py-2.5 resize-y leading-relaxed focus:outline-none focus:border-accent placeholder:text-content-muted"
|
|
137
120
|
value={editText}
|
|
138
121
|
onChange={e => setEditText(e.target.value)}
|
|
139
122
|
rows={4}
|
|
140
123
|
autoFocus
|
|
141
124
|
/>
|
|
142
|
-
<div className="
|
|
143
|
-
<button className="
|
|
144
|
-
<button className="
|
|
125
|
+
<div className="flex gap-2">
|
|
126
|
+
<button className="bg-transparent border border-accent rounded text-accent font-mono text-[11px] px-3.5 py-1.5 cursor-pointer transition-[background,color] duration-150 hover:bg-accent hover:text-white" onClick={() => handleUpdateNote(note.id)}>Save</button>
|
|
127
|
+
<button className="bg-transparent border border-edge rounded text-content-secondary font-mono text-[11px] px-3.5 py-1.5 cursor-pointer hover:border-content hover:text-content" onClick={() => setEditingNoteId(null)}>Cancel</button>
|
|
145
128
|
</div>
|
|
146
129
|
</div>
|
|
147
130
|
) : (
|
|
148
131
|
<>
|
|
149
|
-
<div className="
|
|
150
|
-
<div className="
|
|
151
|
-
<span className="
|
|
132
|
+
<div className="text-xs text-content leading-relaxed whitespace-pre-wrap break-words">{note.text}</div>
|
|
133
|
+
<div className="flex items-center justify-between mt-2">
|
|
134
|
+
<span className="text-[10px] text-content-muted">{formatDate(note.created_at || note.timestamp)}</span>
|
|
152
135
|
{isEditable && (
|
|
153
|
-
<span className="
|
|
154
|
-
<button className="
|
|
155
|
-
<button className="
|
|
136
|
+
<span className="flex gap-1.5">
|
|
137
|
+
<button className="bg-transparent border-none text-content-muted text-[11px] font-mono cursor-pointer px-1.5 py-0.5 rounded-sm hover:bg-surface hover:text-content" onClick={() => { setEditingNoteId(note.id); setEditText(note.text); }}>Edit</button>
|
|
138
|
+
<button className="bg-transparent border-none text-content-muted text-[11px] font-mono cursor-pointer px-1.5 py-0.5 rounded-sm hover:bg-surface hover:text-error" onClick={() => handleDeleteNote(note.id)}>Delete</button>
|
|
156
139
|
</span>
|
|
157
140
|
)}
|
|
158
141
|
</div>
|
|
@@ -164,20 +147,20 @@ export function QaIssueSheet() {
|
|
|
164
147
|
)}
|
|
165
148
|
|
|
166
149
|
{isEditable && (
|
|
167
|
-
<div className="
|
|
150
|
+
<div className="flex flex-col gap-2 mt-auto pt-3 border-t border-edge">
|
|
168
151
|
<textarea
|
|
169
|
-
className="
|
|
152
|
+
className="w-full bg-surface-raised border border-edge rounded text-content font-mono text-xs px-3 py-2.5 resize-y leading-relaxed focus:outline-none focus:border-accent placeholder:text-content-muted"
|
|
170
153
|
placeholder="Describe the issue..."
|
|
171
154
|
rows={4}
|
|
172
155
|
value={newNoteText}
|
|
173
156
|
onChange={e => setNewNoteText(e.target.value)}
|
|
174
157
|
/>
|
|
175
|
-
<div className="
|
|
176
|
-
<button className="
|
|
158
|
+
<div className="flex gap-2">
|
|
159
|
+
<button className="bg-transparent border border-accent rounded text-accent font-mono text-[11px] px-3.5 py-1.5 cursor-pointer transition-[background,color] duration-150 hover:bg-accent hover:text-white" onClick={handleAddNote}>Add Issue</button>
|
|
177
160
|
</div>
|
|
178
161
|
</div>
|
|
179
162
|
)}
|
|
180
163
|
</div>
|
|
181
|
-
</
|
|
164
|
+
</SideSheet>
|
|
182
165
|
);
|
|
183
166
|
}
|
|
@@ -3,7 +3,8 @@ import { marked } from 'marked';
|
|
|
3
3
|
import { useSidePanelStore } from '../stores/useSidePanelStore';
|
|
4
4
|
import { useGraphStore } from '../stores/useGraphStore';
|
|
5
5
|
import { useGraphUIStore } from '../stores/useGraphUIStore';
|
|
6
|
-
import { getTaskCssClass, getTaskIcon, shouldShowTaskList } from '../utils/task_status';
|
|
6
|
+
import { getTaskCssClass, getTaskIcon, getTaskIconClass, getTaskNameClass, shouldShowTaskList } from '../utils/task_status';
|
|
7
|
+
import { SideSheet } from './ds/SideSheet';
|
|
7
8
|
|
|
8
9
|
export function SidePanel() {
|
|
9
10
|
const {
|
|
@@ -32,14 +33,12 @@ export function SidePanel() {
|
|
|
32
33
|
return edges;
|
|
33
34
|
};
|
|
34
35
|
|
|
36
|
+
const title = node ? `${node.name} (${node.id})` : '';
|
|
37
|
+
|
|
35
38
|
if (!node) return (
|
|
36
|
-
<
|
|
37
|
-
<div className="panel-
|
|
38
|
-
|
|
39
|
-
<button className="panel-close" onClick={close}>×</button>
|
|
40
|
-
</div>
|
|
41
|
-
<div className="panel-body" />
|
|
42
|
-
</div>
|
|
39
|
+
<SideSheet isOpen={isOpen} onClose={close} title="" zIndex={200}>
|
|
40
|
+
<div className="panel-body text-sm leading-relaxed" />
|
|
41
|
+
</SideSheet>
|
|
43
42
|
);
|
|
44
43
|
|
|
45
44
|
const statusLabel = (node.status || 'draft').replace(/_/g, ' ');
|
|
@@ -48,34 +47,30 @@ export function SidePanel() {
|
|
|
48
47
|
const edges = findEdges(node.id);
|
|
49
48
|
|
|
50
49
|
return (
|
|
51
|
-
<
|
|
52
|
-
<div className="panel-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div className="panel-status-section">
|
|
58
|
-
<span className="panel-type-badge">{typeLabel}</span>
|
|
59
|
-
<span className={`panel-status-badge panel-status-${node.status || 'draft'}`}>{statusLabel}</span>
|
|
60
|
-
<span className="panel-completeness">{completeness}% complete</span>
|
|
50
|
+
<SideSheet isOpen={isOpen} onClose={close} title={title} zIndex={200}>
|
|
51
|
+
<div className="panel-body text-sm leading-relaxed">
|
|
52
|
+
<div className="flex items-center gap-2 mb-3 pb-2.5 border-b border-edge flex-wrap">
|
|
53
|
+
<span className="text-[10px] text-content-muted uppercase tracking-wide bg-surface-raised px-2 py-0.5 rounded-sm">{typeLabel}</span>
|
|
54
|
+
<span className={`text-[10px] px-2 py-0.5 rounded-sm font-semibold capitalize panel-status-${node.status || 'draft'}`}>{statusLabel}</span>
|
|
55
|
+
<span className="text-[11px] text-content-secondary ml-auto">{completeness}% complete</span>
|
|
61
56
|
</div>
|
|
62
57
|
{shouldShowTaskList(tasks) && (
|
|
63
|
-
<div className="
|
|
58
|
+
<div className="my-2 border border-edge rounded">
|
|
64
59
|
<button
|
|
65
|
-
className="
|
|
60
|
+
className="bg-none border-none text-content font-mono text-xs cursor-pointer py-1.5 px-2 w-full text-left flex items-center gap-1.5 hover:text-content hover:bg-surface-raised"
|
|
66
61
|
onClick={toggleTasks}
|
|
67
62
|
>
|
|
68
|
-
<span className={`
|
|
63
|
+
<span className={`inline-block text-[9px] transition-transform duration-150${expandedTasks ? ' rotate-90' : ''}`}>{'\u25B6'}</span>
|
|
69
64
|
Tasks ({tasks!.completed}/{tasks!.total})
|
|
70
65
|
</button>
|
|
71
66
|
{expandedTasks && tasks!.items?.length > 0 && (
|
|
72
|
-
<div className="
|
|
67
|
+
<div className="px-2 pt-1 pb-1.5 flex flex-col gap-[3px] border-t border-edge">
|
|
73
68
|
{tasks!.items.map((task: any, idx: number) => (
|
|
74
69
|
<div key={idx} className={getTaskCssClass(task.status)}>
|
|
75
|
-
<span className=
|
|
70
|
+
<span className={`shrink-0 w-3 text-center text-[10px] ${getTaskIconClass(task.status)}`}>
|
|
76
71
|
{getTaskIcon(task.status)}
|
|
77
72
|
</span>
|
|
78
|
-
<span className=
|
|
73
|
+
<span className={getTaskNameClass(task.status)}>{task.name}</span>
|
|
79
74
|
</div>
|
|
80
75
|
))}
|
|
81
76
|
</div>
|
|
@@ -84,21 +79,21 @@ export function SidePanel() {
|
|
|
84
79
|
)}
|
|
85
80
|
<div dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }} />
|
|
86
81
|
{workSummaries.length > 0 && (
|
|
87
|
-
<div className="
|
|
82
|
+
<div className="mt-3 border-t border-edge pt-2">
|
|
88
83
|
<button
|
|
89
|
-
className="
|
|
84
|
+
className="bg-none border-none text-content-secondary text-[13px] font-mono cursor-pointer py-1 w-full text-left hover:text-content"
|
|
90
85
|
onClick={toggleSummaries}
|
|
91
86
|
>
|
|
92
87
|
{expandedSummaries ? '\u25BC' : '\u25B6'} Work Summary ({workSummaries.length} cycle{workSummaries.length !== 1 ? 's' : ''})
|
|
93
88
|
</button>
|
|
94
89
|
{expandedSummaries && (
|
|
95
|
-
<div className="
|
|
90
|
+
<div className="mt-2 text-xs text-content-secondary">
|
|
96
91
|
{workSummaries.map((ws, idx) => (
|
|
97
|
-
<div key={idx} className="
|
|
98
|
-
<div className="
|
|
92
|
+
<div key={idx} className="mb-3 pb-2 border-b border-edge last:border-b-0 last:mb-0">
|
|
93
|
+
<div className="font-semibold font-mono text-content mb-1">Cycle {ws.cycle}</div>
|
|
99
94
|
{ws.filesCreated?.length > 0 && (
|
|
100
|
-
<div
|
|
101
|
-
<span className="
|
|
95
|
+
<div>
|
|
96
|
+
<span className="font-semibold text-content-secondary font-mono text-[11px] uppercase tracking-wider" style={{ color: '#4caf50' }}>Created:</span>
|
|
102
97
|
<ul>
|
|
103
98
|
{ws.filesCreated.map((f, fi) => (
|
|
104
99
|
<li key={fi}>{f}</li>
|
|
@@ -107,8 +102,8 @@ export function SidePanel() {
|
|
|
107
102
|
</div>
|
|
108
103
|
)}
|
|
109
104
|
{ws.filesUpdated?.length > 0 && (
|
|
110
|
-
<div
|
|
111
|
-
<span className="
|
|
105
|
+
<div>
|
|
106
|
+
<span className="font-semibold text-content-secondary font-mono text-[11px] uppercase tracking-wider" style={{ color: '#ff9800' }}>Updated:</span>
|
|
112
107
|
<ul>
|
|
113
108
|
{ws.filesUpdated.map((f, fi) => (
|
|
114
109
|
<li key={fi}>{f}</li>
|
|
@@ -117,8 +112,8 @@ export function SidePanel() {
|
|
|
117
112
|
</div>
|
|
118
113
|
)}
|
|
119
114
|
{ws.filesDeleted?.length > 0 && (
|
|
120
|
-
<div
|
|
121
|
-
<span className="
|
|
115
|
+
<div>
|
|
116
|
+
<span className="font-semibold text-content-secondary font-mono text-[11px] uppercase tracking-wider" style={{ color: '#f44336' }}>Deleted:</span>
|
|
122
117
|
<ul>
|
|
123
118
|
{ws.filesDeleted.map((f, fi) => (
|
|
124
119
|
<li key={fi}>{f}</li>
|
|
@@ -127,14 +122,14 @@ export function SidePanel() {
|
|
|
127
122
|
</div>
|
|
128
123
|
)}
|
|
129
124
|
{ws.approach && (
|
|
130
|
-
<div
|
|
131
|
-
<span className="
|
|
125
|
+
<div>
|
|
126
|
+
<span className="font-semibold text-content-secondary font-mono text-[11px] uppercase tracking-wider">Approach:</span>
|
|
132
127
|
<p>{ws.approach}</p>
|
|
133
128
|
</div>
|
|
134
129
|
)}
|
|
135
130
|
{ws.decisions?.length > 0 && (
|
|
136
|
-
<div
|
|
137
|
-
<span className="
|
|
131
|
+
<div>
|
|
132
|
+
<span className="font-semibold text-content-secondary font-mono text-[11px] uppercase tracking-wider">Decisions:</span>
|
|
138
133
|
<ul>
|
|
139
134
|
{ws.decisions.map((d, di) => (
|
|
140
135
|
<li key={di}>{d}</li>
|
|
@@ -149,21 +144,21 @@ export function SidePanel() {
|
|
|
149
144
|
</div>
|
|
150
145
|
)}
|
|
151
146
|
{edges.length > 0 && (
|
|
152
|
-
<div className="
|
|
153
|
-
<h3>Relationships</h3>
|
|
154
|
-
<ul className="
|
|
147
|
+
<div className="mt-4 pt-3 border-t border-edge">
|
|
148
|
+
<h3 className="text-xs text-content mb-2 uppercase tracking-wide">Relationships</h3>
|
|
149
|
+
<ul className="list-none p-0 m-0 flex flex-col gap-1">
|
|
155
150
|
{edges.map((edge, i) => {
|
|
156
151
|
const neighborNode = graphData?.nodes.find((n: any) => n.id === edge.neighborId);
|
|
157
152
|
const name = neighborNode ? neighborNode.name : edge.neighborId;
|
|
158
153
|
const direction = edge.direction === 'outgoing' ? '\u2192' : '\u2190';
|
|
159
154
|
return (
|
|
160
|
-
<li key={i} className="
|
|
161
|
-
<span className="
|
|
162
|
-
<span className="
|
|
163
|
-
<a className="
|
|
155
|
+
<li key={i} className="flex items-center gap-1.5 px-1.5 py-1 rounded-sm transition-background duration-150 hover:bg-surface-raised">
|
|
156
|
+
<span className="text-[11px] text-content-muted w-3.5 text-center shrink-0">{direction}</span>
|
|
157
|
+
<span className="text-[10px] text-content-muted min-w-20 shrink-0">{edge.relation.replace(/_/g, ' ')}</span>
|
|
158
|
+
<a className="text-xs text-accent no-underline cursor-pointer flex-1 overflow-hidden text-ellipsis whitespace-nowrap hover:underline" href="#" onClick={(e) => { e.preventDefault(); onEdgeClick?.(edge.neighborId); }}>
|
|
164
159
|
{name}
|
|
165
160
|
</a>
|
|
166
|
-
<span className="
|
|
161
|
+
<span className="text-[10px] text-content-muted shrink-0">{edge.neighborId}</span>
|
|
167
162
|
</li>
|
|
168
163
|
);
|
|
169
164
|
})}
|
|
@@ -171,6 +166,6 @@ export function SidePanel() {
|
|
|
171
166
|
</div>
|
|
172
167
|
)}
|
|
173
168
|
</div>
|
|
174
|
-
</
|
|
169
|
+
</SideSheet>
|
|
175
170
|
);
|
|
176
171
|
}
|