@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
|
@@ -1,86 +1,164 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useCallback, useEffect } from 'react';
|
|
2
|
+
import { useLocation, useNavigate } from 'react-router-dom';
|
|
3
|
+
import {
|
|
4
|
+
Columns3, MessageSquare, Network, ShieldCheck, Palette, Users, Bot, Workflow,
|
|
5
|
+
FolderOpen, Maximize, Settings, Sun, Moon, Video,
|
|
6
|
+
} from 'lucide-react';
|
|
7
|
+
import { NavBarSidekick } from './ds/NavBarSidekick';
|
|
8
|
+
import type { NavItem } from './ds/NavBarSidekick';
|
|
2
9
|
import { ProjectSelector } from './ProjectSelector';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
projects: Project[];
|
|
17
|
-
selectedProjectId: string | null;
|
|
18
|
-
onProjectSelect: (id: string) => void;
|
|
19
|
-
onProjectCreate: (name: string) => Promise<any>;
|
|
20
|
-
onProjectRename: (id: string, name: string) => Promise<void>;
|
|
21
|
-
onProjectArchive: (id: string) => Promise<void>;
|
|
22
|
-
onOpenGitModal?: (project: Project) => void;
|
|
10
|
+
import { useProjectStore } from '../stores/useProjectStore';
|
|
11
|
+
import { useGraphStore } from '../stores/useGraphStore';
|
|
12
|
+
import { useGraphUIStore } from '../stores/useGraphUIStore';
|
|
13
|
+
import { useGitModalStore } from '../stores/useGitModalStore';
|
|
14
|
+
import { useTheme } from '../hooks/useTheme';
|
|
15
|
+
import { useAuth } from '../hooks/useAuth';
|
|
16
|
+
import { apiClient } from '../api/client';
|
|
17
|
+
|
|
18
|
+
const VALID_TABS = new Set(['graph', 'kanban', 'coherence', 'users', 'terminal', 'agents', 'workflows', 'design-system', 'files', 'videography']);
|
|
19
|
+
|
|
20
|
+
function tabFromPath(pathname: string): string {
|
|
21
|
+
const seg = pathname.replace(/^\//, '');
|
|
22
|
+
return VALID_TABS.has(seg) ? seg : 'kanban';
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
25
|
+
const ICON_PROPS = { size: 14, strokeWidth: 2 } as const;
|
|
26
|
+
|
|
27
|
+
const TAB_ITEMS: NavItem[] = [
|
|
28
|
+
{ id: 'kanban', label: 'Kanban', icon: <Columns3 {...ICON_PROPS} />, description: 'Board view of features', href: '/kanban' },
|
|
29
|
+
{ id: 'terminal', label: 'Chat', icon: <MessageSquare {...ICON_PROPS} />, description: 'AI assistant terminal', href: '/terminal' },
|
|
30
|
+
{ id: 'graph', label: 'Graph', icon: <Network {...ICON_PROPS} />, description: 'Knowledge graph visualization', href: '/graph' },
|
|
31
|
+
{ id: 'coherence', label: 'Coherence', icon: <ShieldCheck {...ICON_PROPS} />, description: 'Coherence analysis', href: '/coherence' },
|
|
32
|
+
{ id: 'agents', label: 'Agents', icon: <Bot {...ICON_PROPS} />, description: 'Manage agent prompts', href: '/agents' },
|
|
33
|
+
{ id: 'workflows', label: 'Workflows', icon: <Workflow {...ICON_PROPS} />, description: 'Visual workflow builder', href: '/workflows' },
|
|
34
|
+
{ id: 'files', label: 'Files', icon: <FolderOpen {...ICON_PROPS} />, description: 'Browse and edit project files', href: '/files' },
|
|
35
|
+
{ id: 'design-system', label: 'Design System', icon: <Palette {...ICON_PROPS} />, description: 'Living style guide', href: '/design-system' },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const VIDEOGRAPHY_ITEM: NavItem = { id: 'videography', label: 'Videography', icon: <Video {...ICON_PROPS} />, description: 'Video production pipeline', href: '/videography' };
|
|
39
|
+
const ADMIN_ITEM: NavItem = { id: 'users', label: 'Users', icon: <Users {...ICON_PROPS} />, description: 'User management', href: '/users' };
|
|
40
|
+
|
|
41
|
+
const iconBtnClass = (active?: boolean) => [
|
|
42
|
+
'flex h-8 w-8 items-center justify-center rounded-lg border',
|
|
43
|
+
'transition-all duration-150 cursor-pointer outline-none',
|
|
44
|
+
active
|
|
45
|
+
? 'border-accent/40 bg-accent/10 text-accent'
|
|
46
|
+
: 'border-edge text-content-muted hover:border-content/20 hover:text-content',
|
|
47
|
+
].join(' ');
|
|
48
|
+
|
|
49
|
+
export function Toolbar() {
|
|
50
|
+
const navigate = useNavigate();
|
|
51
|
+
const location = useLocation();
|
|
52
|
+
const activeTab = tabFromPath(location.pathname);
|
|
53
|
+
|
|
54
|
+
const { theme, toggleTheme } = useTheme();
|
|
55
|
+
const { user } = useAuth();
|
|
56
|
+
const isAdmin = user?.role === 'admin';
|
|
57
|
+
|
|
58
|
+
const projects = useProjectStore((s) => s.projects);
|
|
59
|
+
const selectedProjectId = useProjectStore((s) => s.selectedProjectId);
|
|
60
|
+
const selectProject = useProjectStore((s) => s.selectProject);
|
|
61
|
+
const createProject = useProjectStore((s) => s.createProject);
|
|
62
|
+
const renameProject = useProjectStore((s) => s.renameProject);
|
|
63
|
+
const archiveProject = useProjectStore((s) => s.archiveProject);
|
|
64
|
+
|
|
65
|
+
const graphData = useGraphStore((s) => s.graphData);
|
|
66
|
+
const onFit = useGraphUIStore((s) => s.onFit);
|
|
67
|
+
const settingsOpen = useGraphUIStore((s) => s.settingsOpen);
|
|
68
|
+
const onSettingsToggle = useGraphUIStore((s) => s.onSettingsToggle);
|
|
69
|
+
|
|
70
|
+
const openGitModal = useGitModalStore((s) => s.open);
|
|
71
|
+
|
|
72
|
+
const completeness = graphData
|
|
73
|
+
? Math.round((graphData.nodes.reduce((acc: number, n: any) => acc + (n.completeness || 0), 0) / Math.max(graphData.nodes.length, 1)) * 100)
|
|
74
|
+
: 0;
|
|
75
|
+
|
|
76
|
+
const selectedProject = projects.find(p => p.id === selectedProjectId);
|
|
77
|
+
const isVideoProject = selectedProject?.type === 'video';
|
|
78
|
+
|
|
79
|
+
const items = [
|
|
80
|
+
...TAB_ITEMS,
|
|
81
|
+
...(isVideoProject ? [VIDEOGRAPHY_ITEM] : []),
|
|
82
|
+
...(isAdmin ? [ADMIN_ITEM] : []),
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const handleLogout = useCallback(async () => {
|
|
86
|
+
try {
|
|
87
|
+
await apiClient.logout();
|
|
88
|
+
} catch {
|
|
89
|
+
// ignore
|
|
90
|
+
}
|
|
91
|
+
navigate('/login', { replace: true });
|
|
92
|
+
}, [navigate]);
|
|
34
93
|
|
|
35
|
-
|
|
94
|
+
// Global '/' shortcut — the NavBarSidekick handles its own cmd palette UI,
|
|
95
|
+
// but we wire the keyboard shortcut at the toolbar level for page-wide reach
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const handler = (e: KeyboardEvent) => {
|
|
98
|
+
if (e.key === '/' && !(e.target instanceof HTMLInputElement) && !(e.target instanceof HTMLTextAreaElement)) {
|
|
99
|
+
// Let the NavBarSidekick's own button handle it via a simulated click
|
|
100
|
+
const btn = document.querySelector('[data-cmd-trigger]') as HTMLButtonElement | null;
|
|
101
|
+
if (btn) { e.preventDefault(); btn.click(); }
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
document.addEventListener('keydown', handler);
|
|
105
|
+
return () => document.removeEventListener('keydown', handler);
|
|
106
|
+
}, []);
|
|
36
107
|
|
|
37
108
|
return (
|
|
38
|
-
<div className="
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
<div className="border-b border-edge">
|
|
110
|
+
<NavBarSidekick
|
|
111
|
+
items={items}
|
|
112
|
+
activeId={activeTab}
|
|
113
|
+
brand={
|
|
114
|
+
<ProjectSelector
|
|
115
|
+
projects={projects}
|
|
116
|
+
selectedProjectId={selectedProjectId}
|
|
117
|
+
onSelect={selectProject}
|
|
118
|
+
onCreate={createProject}
|
|
119
|
+
onRename={renameProject}
|
|
120
|
+
onArchive={archiveProject}
|
|
121
|
+
onOpenGitModal={openGitModal}
|
|
122
|
+
/>
|
|
123
|
+
}
|
|
124
|
+
center={
|
|
125
|
+
<div className="flex items-center justify-end gap-2 text-[11px] text-content-muted">
|
|
126
|
+
<span className="hidden lg:inline uppercase tracking-wider font-medium">Completeness</span>
|
|
127
|
+
<div className="w-20 h-1.5 rounded-full bg-completeness-bg overflow-hidden">
|
|
128
|
+
<div
|
|
129
|
+
className="h-full rounded-full bg-completeness-fill transition-all duration-300"
|
|
130
|
+
style={{ width: `${completeness}%` }}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
<span className="font-mono text-[11px] text-content-secondary w-8 text-right">{completeness}%</span>
|
|
134
|
+
</div>
|
|
135
|
+
}
|
|
136
|
+
actions={
|
|
137
|
+
<div className="flex items-center gap-1.5">
|
|
138
|
+
<button onClick={() => onFit?.()} title="Fit graph to viewport" className={iconBtnClass()}>
|
|
139
|
+
<Maximize size={14} strokeWidth={2} />
|
|
140
|
+
</button>
|
|
141
|
+
<button onClick={onSettingsToggle} title="Graph settings" className={iconBtnClass(settingsOpen)}>
|
|
142
|
+
<Settings size={14} strokeWidth={2} />
|
|
143
|
+
</button>
|
|
144
|
+
<div className="h-5 w-px bg-edge mx-1" />
|
|
145
|
+
</div>
|
|
146
|
+
}
|
|
147
|
+
trailing={
|
|
148
|
+
<div className="flex items-center gap-1.5">
|
|
149
|
+
<button onClick={toggleTheme} title="Toggle theme" className={iconBtnClass()}>
|
|
150
|
+
{theme === 'dark' ? <Sun size={14} strokeWidth={2} /> : <Moon size={14} strokeWidth={2} />}
|
|
151
|
+
</button>
|
|
152
|
+
<button
|
|
153
|
+
onClick={handleLogout}
|
|
154
|
+
title="Logout"
|
|
155
|
+
className="flex h-8 w-8 items-center justify-center rounded-full bg-accent text-[11px] font-bold text-surface cursor-pointer outline-none hover:opacity-90 transition-opacity"
|
|
156
|
+
>
|
|
157
|
+
{user?.email?.slice(0, 2).toUpperCase() || 'U'}
|
|
158
|
+
</button>
|
|
159
|
+
</div>
|
|
160
|
+
}
|
|
161
|
+
/>
|
|
84
162
|
</div>
|
|
85
163
|
);
|
|
86
164
|
}
|
|
@@ -110,43 +110,43 @@ export function UsersView({ visible }: UsersViewProps) {
|
|
|
110
110
|
if (!visible) return null;
|
|
111
111
|
|
|
112
112
|
return (
|
|
113
|
-
<div className="
|
|
114
|
-
<div className="
|
|
115
|
-
<h2>User Management</h2>
|
|
116
|
-
<button className="
|
|
113
|
+
<div className="p-6 max-w-[900px] mx-auto text-content">
|
|
114
|
+
<div className="flex justify-between items-center mb-5">
|
|
115
|
+
<h2 className="text-xl font-semibold">User Management</h2>
|
|
116
|
+
<button className="bg-accent text-white border-none rounded-md px-4 py-2 text-sm cursor-pointer font-mono hover:opacity-90" onClick={() => setInviteOpen(true)}>
|
|
117
117
|
+ Invite User
|
|
118
118
|
</button>
|
|
119
119
|
</div>
|
|
120
120
|
|
|
121
|
-
{error && <div className="
|
|
121
|
+
{error && <div className="bg-[rgba(255,107,107,0.15)] text-error px-3.5 py-2.5 rounded-md mb-4 text-sm flex justify-between items-center">{error}<button className="bg-none border-none text-error text-lg cursor-pointer px-1" onClick={() => setError('')}>×</button></div>}
|
|
122
122
|
|
|
123
123
|
{loading ? (
|
|
124
|
-
<div className="
|
|
124
|
+
<div className="text-content-secondary py-10 text-center">Loading...</div>
|
|
125
125
|
) : (
|
|
126
126
|
<>
|
|
127
|
-
<section className="
|
|
128
|
-
<h3>Registered Users ({users.length})</h3>
|
|
129
|
-
<table className="
|
|
127
|
+
<section className="mb-7">
|
|
128
|
+
<h3 className="text-[15px] font-semibold text-content-secondary mb-2.5">Registered Users ({users.length})</h3>
|
|
129
|
+
<table className="w-full border-collapse text-sm font-mono">
|
|
130
130
|
<thead>
|
|
131
131
|
<tr>
|
|
132
|
-
<th>Email</th>
|
|
133
|
-
<th>Role</th>
|
|
134
|
-
<th>Created</th>
|
|
135
|
-
<th></th>
|
|
132
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Email</th>
|
|
133
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Role</th>
|
|
134
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Created</th>
|
|
135
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide"></th>
|
|
136
136
|
</tr>
|
|
137
137
|
</thead>
|
|
138
138
|
<tbody>
|
|
139
139
|
{users.map(u => (
|
|
140
|
-
<tr key={u.id} className={u.id === currentUser?.id ? '
|
|
141
|
-
<td>{u.email}</td>
|
|
142
|
-
<td><span className={`
|
|
143
|
-
<td>{formatDate(u.createdAt)}</td>
|
|
144
|
-
<td>
|
|
140
|
+
<tr key={u.id} className={`hover:bg-surface-raised ${u.id === currentUser?.id ? 'bg-surface-alt' : ''}`}>
|
|
141
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{u.email}</td>
|
|
142
|
+
<td className="px-3 py-2.5 border-b border-edge text-content"><span className={`inline-block px-2 py-0.5 rounded text-xs font-medium ${u.role === 'admin' ? 'bg-[rgba(77,171,247,0.15)] text-accent' : 'bg-surface-raised text-content-secondary'}`}>{u.role}</span></td>
|
|
143
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(u.createdAt)}</td>
|
|
144
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">
|
|
145
145
|
{u.id === currentUser?.id ? (
|
|
146
|
-
<span className="
|
|
146
|
+
<span className="text-xs text-content-muted italic">you</span>
|
|
147
147
|
) : (
|
|
148
148
|
<button
|
|
149
|
-
className="
|
|
149
|
+
className="bg-none border border-edge text-error rounded px-2.5 py-1 text-xs cursor-pointer font-mono hover:bg-[rgba(255,107,107,0.1)] hover:border-error disabled:opacity-50 disabled:cursor-not-allowed"
|
|
150
150
|
onClick={() => handleDeleteUser(u.id, u.email)}
|
|
151
151
|
disabled={deletingId === u.id}
|
|
152
152
|
title={`Delete ${u.email}`}
|
|
@@ -161,31 +161,31 @@ export function UsersView({ visible }: UsersViewProps) {
|
|
|
161
161
|
</table>
|
|
162
162
|
</section>
|
|
163
163
|
|
|
164
|
-
<section className="
|
|
165
|
-
<h3>Pending Invitations ({pendingInvitations.length})</h3>
|
|
164
|
+
<section className="mb-7">
|
|
165
|
+
<h3 className="text-[15px] font-semibold text-content-secondary mb-2.5">Pending Invitations ({pendingInvitations.length})</h3>
|
|
166
166
|
{pendingInvitations.length === 0 ? (
|
|
167
|
-
<p className="
|
|
167
|
+
<p className="text-content-muted text-sm py-3">No pending invitations.</p>
|
|
168
168
|
) : (
|
|
169
|
-
<table className="
|
|
169
|
+
<table className="w-full border-collapse text-sm font-mono">
|
|
170
170
|
<thead>
|
|
171
171
|
<tr>
|
|
172
|
-
<th>Email</th>
|
|
173
|
-
<th>Invited By</th>
|
|
174
|
-
<th>Sent</th>
|
|
175
|
-
<th>Expires</th>
|
|
176
|
-
<th></th>
|
|
172
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Email</th>
|
|
173
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Invited By</th>
|
|
174
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Sent</th>
|
|
175
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Expires</th>
|
|
176
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide"></th>
|
|
177
177
|
</tr>
|
|
178
178
|
</thead>
|
|
179
179
|
<tbody>
|
|
180
180
|
{pendingInvitations.map(inv => (
|
|
181
|
-
<tr key={inv.id}>
|
|
182
|
-
<td>{inv.email}</td>
|
|
183
|
-
<td>{inv.invitedByEmail}</td>
|
|
184
|
-
<td>{formatDate(inv.createdAt)}</td>
|
|
185
|
-
<td>{formatDate(inv.expiresAt)}</td>
|
|
186
|
-
<td>
|
|
181
|
+
<tr key={inv.id} className="hover:bg-surface-raised">
|
|
182
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{inv.email}</td>
|
|
183
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{inv.invitedByEmail}</td>
|
|
184
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(inv.createdAt)}</td>
|
|
185
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(inv.expiresAt)}</td>
|
|
186
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">
|
|
187
187
|
<button
|
|
188
|
-
className="
|
|
188
|
+
className="bg-none border border-edge text-error rounded px-2.5 py-1 text-xs cursor-pointer font-mono hover:bg-[rgba(255,107,107,0.1)] hover:border-error disabled:opacity-50 disabled:cursor-not-allowed"
|
|
189
189
|
onClick={() => handleDeleteInvitation(inv.id, inv.email)}
|
|
190
190
|
disabled={deletingId === inv.id}
|
|
191
191
|
title={`Cancel invitation for ${inv.email}`}
|
|
@@ -201,32 +201,32 @@ export function UsersView({ visible }: UsersViewProps) {
|
|
|
201
201
|
</section>
|
|
202
202
|
|
|
203
203
|
{pastInvitations.length > 0 && (
|
|
204
|
-
<section className="
|
|
205
|
-
<h3>Past Invitations ({pastInvitations.length})</h3>
|
|
206
|
-
<table className="
|
|
204
|
+
<section className="mb-7">
|
|
205
|
+
<h3 className="text-[15px] font-semibold text-content-secondary mb-2.5">Past Invitations ({pastInvitations.length})</h3>
|
|
206
|
+
<table className="w-full border-collapse text-sm font-mono">
|
|
207
207
|
<thead>
|
|
208
208
|
<tr>
|
|
209
|
-
<th>Email</th>
|
|
210
|
-
<th>Invited By</th>
|
|
211
|
-
<th>Status</th>
|
|
212
|
-
<th>Date</th>
|
|
213
|
-
<th></th>
|
|
209
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Email</th>
|
|
210
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Invited By</th>
|
|
211
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Status</th>
|
|
212
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide">Date</th>
|
|
213
|
+
<th className="text-left px-3 py-2 border-b border-edge text-content-muted font-medium text-xs uppercase tracking-wide"></th>
|
|
214
214
|
</tr>
|
|
215
215
|
</thead>
|
|
216
216
|
<tbody>
|
|
217
217
|
{pastInvitations.map(inv => (
|
|
218
|
-
<tr key={inv.id} className="
|
|
219
|
-
<td>{inv.email}</td>
|
|
220
|
-
<td>{inv.invitedByEmail}</td>
|
|
221
|
-
<td>
|
|
222
|
-
<span className={`
|
|
218
|
+
<tr key={inv.id} className="opacity-70 hover:bg-surface-raised">
|
|
219
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{inv.email}</td>
|
|
220
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{inv.invitedByEmail}</td>
|
|
221
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">
|
|
222
|
+
<span className={`inline-block px-2 py-0.5 rounded text-xs font-medium ${inv.acceptedAt ? 'bg-[rgba(105,219,124,0.15)] text-completeness-fill' : 'bg-[rgba(255,107,107,0.15)] text-error'}`}>
|
|
223
223
|
{inv.acceptedAt ? 'Accepted' : 'Expired'}
|
|
224
224
|
</span>
|
|
225
225
|
</td>
|
|
226
|
-
<td>{formatDate(inv.acceptedAt || inv.expiresAt)}</td>
|
|
227
|
-
<td>
|
|
226
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">{formatDate(inv.acceptedAt || inv.expiresAt)}</td>
|
|
227
|
+
<td className="px-3 py-2.5 border-b border-edge text-content">
|
|
228
228
|
<button
|
|
229
|
-
className="
|
|
229
|
+
className="bg-none border border-edge text-error rounded px-2.5 py-1 text-xs cursor-pointer font-mono hover:bg-[rgba(255,107,107,0.1)] hover:border-error disabled:opacity-50 disabled:cursor-not-allowed"
|
|
230
230
|
onClick={() => handleDeleteInvitation(inv.id, inv.email)}
|
|
231
231
|
disabled={deletingId === inv.id}
|
|
232
232
|
title={`Delete invitation record for ${inv.email}`}
|