@assistkick/create 1.6.0 → 1.8.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/package.json +2 -2
- 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 +43 -4
- 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 +154 -0
- package/templates/assistkick-product-system/packages/backend/src/server.ts +81 -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 +28 -78
- 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 +222 -0
- package/templates/assistkick-product-system/packages/frontend/index.html +3 -0
- package/templates/assistkick-product-system/packages/frontend/package-lock.json +800 -11
- package/templates/assistkick-product-system/packages/frontend/package.json +11 -1
- package/templates/assistkick-product-system/packages/frontend/src/App.tsx +24 -7
- package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +456 -16
- 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 +383 -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 +193 -64
- 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/KanbanView.tsx +226 -291
- 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 +40 -66
- package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +55 -115
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +121 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +155 -77
- 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 +270 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCardShowcase.tsx +37 -0
- 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 +207 -0
- 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/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/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 +335 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +634 -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 +208 -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 +107 -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/useGraph.ts +6 -21
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +15 -80
- 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 +19 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +54 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +93 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +30 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +9 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +6 -0
- 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/useGitModalStore.ts +14 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useGraphStore.ts +36 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useGraphUIStore.ts +25 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +90 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useQaSheetStore.ts +27 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +76 -0
- package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +336 -3632
- 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 +7 -1
- 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/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/_journal.json +70 -0
- package/templates/assistkick-product-system/packages/shared/db/schema.ts +113 -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 +16 -5
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +1753 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +1281 -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 +179 -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-bootstrap/SKILL.md +3 -3
- package/templates/skills/assistkick-code-reviewer/SKILL.md +2 -2
- package/templates/skills/assistkick-debugger/SKILL.md +2 -2
- package/templates/skills/assistkick-developer/SKILL.md +6 -3
- package/templates/skills/assistkick-developer/references/react_development_guidelines.md +225 -0
- package/templates/skills/assistkick-interview/SKILL.md +2 -2
- 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,22 +1,14 @@
|
|
|
1
|
-
import React, { useState, useEffect,
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { apiClient } from '../api/client';
|
|
3
|
+
import { useQaSheetStore } from '../stores/useQaSheetStore';
|
|
4
|
+
import { SideSheet } from './ds/SideSheet';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
notes: any[];
|
|
10
|
-
reviews: any[];
|
|
11
|
-
onClose: () => void;
|
|
12
|
-
onNotesChanged: () => void;
|
|
13
|
-
}
|
|
6
|
+
export function QaIssueSheet() {
|
|
7
|
+
const {
|
|
8
|
+
isOpen, featureId, featureName, column, notes: initialNotes,
|
|
9
|
+
reviews: initialReviews, close,
|
|
10
|
+
} = useQaSheetStore();
|
|
14
11
|
|
|
15
|
-
export function QaIssueSheet({
|
|
16
|
-
isOpen, featureId, featureName, column, notes: initialNotes, reviews: initialReviews,
|
|
17
|
-
onClose, onNotesChanged,
|
|
18
|
-
}: QaIssueSheetProps) {
|
|
19
|
-
const sheetRef = useRef<HTMLDivElement>(null);
|
|
20
12
|
const [notes, setNotes] = useState<any[]>(initialNotes);
|
|
21
13
|
const [reviews, setReviews] = useState<any[]>(initialReviews);
|
|
22
14
|
const [newNoteText, setNewNoteText] = useState('');
|
|
@@ -25,7 +17,7 @@ export function QaIssueSheet({
|
|
|
25
17
|
|
|
26
18
|
const isEditable = column === 'qa';
|
|
27
19
|
|
|
28
|
-
// Sync when
|
|
20
|
+
// Sync when store data changes
|
|
29
21
|
useEffect(() => {
|
|
30
22
|
setNotes(initialNotes);
|
|
31
23
|
setReviews(initialReviews);
|
|
@@ -33,19 +25,6 @@ export function QaIssueSheet({
|
|
|
33
25
|
setNewNoteText('');
|
|
34
26
|
}, [featureId, initialNotes, initialReviews]);
|
|
35
27
|
|
|
36
|
-
// Close on outside click
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (!isOpen) return;
|
|
39
|
-
const handleClick = (e: MouseEvent) => {
|
|
40
|
-
if (sheetRef.current && !sheetRef.current.contains(e.target as Node)) {
|
|
41
|
-
if ((e.target as HTMLElement).closest('.kanban-issues-btn')) return;
|
|
42
|
-
onClose();
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
document.addEventListener('click', handleClick);
|
|
46
|
-
return () => document.removeEventListener('click', handleClick);
|
|
47
|
-
}, [isOpen, onClose]);
|
|
48
|
-
|
|
49
28
|
const refreshNotes = useCallback(async () => {
|
|
50
29
|
if (!featureId) return;
|
|
51
30
|
try {
|
|
@@ -55,11 +34,10 @@ export function QaIssueSheet({
|
|
|
55
34
|
setNotes(entry.notes || []);
|
|
56
35
|
setReviews(entry.reviews || []);
|
|
57
36
|
}
|
|
58
|
-
onNotesChanged();
|
|
59
37
|
} catch (err) {
|
|
60
38
|
console.error('Failed to refresh notes:', err);
|
|
61
39
|
}
|
|
62
|
-
}, [featureId
|
|
40
|
+
}, [featureId]);
|
|
63
41
|
|
|
64
42
|
const handleAddNote = async () => {
|
|
65
43
|
const text = newNoteText.trim();
|
|
@@ -105,63 +83,59 @@ export function QaIssueSheet({
|
|
|
105
83
|
};
|
|
106
84
|
|
|
107
85
|
return (
|
|
108
|
-
<
|
|
109
|
-
<div className="
|
|
110
|
-
<
|
|
111
|
-
<button className="qa-sheet-close" onClick={onClose}>×</button>
|
|
112
|
-
</div>
|
|
113
|
-
<div className="qa-sheet-body">
|
|
114
|
-
<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">
|
|
115
89
|
{isEditable ? 'Report and manage QA issues' : 'Issues (read-only)'}
|
|
116
90
|
</div>
|
|
117
91
|
|
|
118
92
|
{reviews.length > 0 && (
|
|
119
|
-
<div className="
|
|
120
|
-
<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>
|
|
121
95
|
{reviews.map((review: any, i: number) => (
|
|
122
|
-
<div key={i} className="
|
|
123
|
-
<div className="
|
|
124
|
-
<span className="
|
|
125
|
-
<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]'}`}>
|
|
126
100
|
{review.status === 'approved' ? 'Approved' : 'Rejected'}
|
|
127
101
|
</span>
|
|
128
|
-
<span className="
|
|
102
|
+
<span className="text-content-secondary text-[11px] ml-auto">{formatDate(review.timestamp)}</span>
|
|
129
103
|
</div>
|
|
130
|
-
{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>}
|
|
131
105
|
</div>
|
|
132
106
|
))}
|
|
133
107
|
</div>
|
|
134
108
|
)}
|
|
135
109
|
|
|
136
110
|
{notes.length === 0 ? (
|
|
137
|
-
<div className="
|
|
111
|
+
<div className="text-xs text-content-muted p-4 text-center">No issues reported yet.</div>
|
|
138
112
|
) : (
|
|
139
|
-
<div className="
|
|
113
|
+
<div className="flex flex-col gap-2">
|
|
140
114
|
{notes.map((note: any) => (
|
|
141
|
-
<div key={note.id} className="
|
|
115
|
+
<div key={note.id} className="bg-surface-raised border border-edge rounded px-3 py-2.5">
|
|
142
116
|
{editingNoteId === note.id ? (
|
|
143
|
-
<div className="
|
|
117
|
+
<div className="flex flex-col gap-2">
|
|
144
118
|
<textarea
|
|
145
|
-
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"
|
|
146
120
|
value={editText}
|
|
147
121
|
onChange={e => setEditText(e.target.value)}
|
|
148
122
|
rows={4}
|
|
149
123
|
autoFocus
|
|
150
124
|
/>
|
|
151
|
-
<div className="
|
|
152
|
-
<button className="
|
|
153
|
-
<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>
|
|
154
128
|
</div>
|
|
155
129
|
</div>
|
|
156
130
|
) : (
|
|
157
131
|
<>
|
|
158
|
-
<div className="
|
|
159
|
-
<div className="
|
|
160
|
-
<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>
|
|
161
135
|
{isEditable && (
|
|
162
|
-
<span className="
|
|
163
|
-
<button className="
|
|
164
|
-
<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>
|
|
165
139
|
</span>
|
|
166
140
|
)}
|
|
167
141
|
</div>
|
|
@@ -173,20 +147,20 @@ export function QaIssueSheet({
|
|
|
173
147
|
)}
|
|
174
148
|
|
|
175
149
|
{isEditable && (
|
|
176
|
-
<div className="
|
|
150
|
+
<div className="flex flex-col gap-2 mt-auto pt-3 border-t border-edge">
|
|
177
151
|
<textarea
|
|
178
|
-
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"
|
|
179
153
|
placeholder="Describe the issue..."
|
|
180
154
|
rows={4}
|
|
181
155
|
value={newNoteText}
|
|
182
156
|
onChange={e => setNewNoteText(e.target.value)}
|
|
183
157
|
/>
|
|
184
|
-
<div className="
|
|
185
|
-
<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>
|
|
186
160
|
</div>
|
|
187
161
|
</div>
|
|
188
162
|
)}
|
|
189
163
|
</div>
|
|
190
|
-
</
|
|
164
|
+
</SideSheet>
|
|
191
165
|
);
|
|
192
166
|
}
|