@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
package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { apiClient } from '../api/client';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
interface GitRepoModalProps {
|
|
6
|
-
project: Project;
|
|
7
|
-
onClose: () => void;
|
|
8
|
-
onProjectUpdated: () => void;
|
|
9
|
-
}
|
|
3
|
+
import { useGitModalStore } from '../stores/useGitModalStore';
|
|
4
|
+
import { useProjectStore } from '../stores/useProjectStore';
|
|
10
5
|
|
|
11
6
|
interface Installation {
|
|
12
7
|
id: number;
|
|
@@ -22,32 +17,47 @@ interface Repo {
|
|
|
22
17
|
cloneUrl: string;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
type Tab = 'status' | 'github' | 'url' | 'init';
|
|
20
|
+
type Tab = 'status' | 'github' | 'ssh' | 'url' | 'init';
|
|
21
|
+
|
|
22
|
+
const tabCls = (active: boolean) =>
|
|
23
|
+
`bg-none border-none cursor-pointer font-mono text-xs px-3 py-2.5 border-b-2 ${
|
|
24
|
+
active ? 'text-accent border-b-accent' : 'text-content-secondary border-b-transparent hover:text-content'
|
|
25
|
+
}`;
|
|
26
|
+
|
|
27
|
+
const btnBase = 'inline-block px-4 py-2 border border-edge rounded bg-surface-raised text-content font-mono text-xs cursor-pointer mt-3 hover:bg-tab-hover disabled:opacity-50 disabled:cursor-not-allowed';
|
|
28
|
+
const btnPrimary = 'inline-block px-4 py-2 rounded font-mono text-xs cursor-pointer mt-3 bg-accent text-white border border-accent hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed';
|
|
29
|
+
const btnDanger = 'inline-block px-4 py-2 rounded font-mono text-xs cursor-pointer mt-4 bg-transparent border border-error text-error hover:bg-[rgba(255,107,107,0.1)] disabled:opacity-50 disabled:cursor-not-allowed';
|
|
26
30
|
|
|
27
|
-
export function GitRepoModal(
|
|
31
|
+
export function GitRepoModal() {
|
|
32
|
+
const project = useGitModalStore((s) => s.project)!;
|
|
33
|
+
const onClose = useGitModalStore((s) => s.close);
|
|
34
|
+
const onProjectUpdated = useProjectStore((s) => s.refetchProjects);
|
|
28
35
|
const [tab, setTab] = useState<Tab>('status');
|
|
29
36
|
const [loading, setLoading] = useState(false);
|
|
30
37
|
const [error, setError] = useState<string | null>(null);
|
|
31
38
|
const [success, setSuccess] = useState<string | null>(null);
|
|
32
39
|
|
|
33
|
-
// Status tab
|
|
34
40
|
const [gitStatus, setGitStatus] = useState<any>(null);
|
|
35
41
|
|
|
36
|
-
// GitHub tab
|
|
37
42
|
const [installations, setInstallations] = useState<Installation[]>([]);
|
|
38
43
|
const [selectedInstallation, setSelectedInstallation] = useState<string>('');
|
|
39
44
|
const [repos, setRepos] = useState<Repo[]>([]);
|
|
40
45
|
const [selectedRepo, setSelectedRepo] = useState<string>('');
|
|
41
46
|
const [githubConfigured, setGithubConfigured] = useState(false);
|
|
42
47
|
|
|
43
|
-
// URL tab
|
|
44
48
|
const [cloneUrl, setCloneUrl] = useState('');
|
|
45
49
|
|
|
50
|
+
// SSH state
|
|
51
|
+
const [sshPublicKey, setSshPublicKey] = useState<string | null>(null);
|
|
52
|
+
const [sshCloneUrl, setSshCloneUrl] = useState('');
|
|
53
|
+
const [copied, setCopied] = useState(false);
|
|
54
|
+
|
|
46
55
|
const loadStatus = useCallback(async () => {
|
|
47
56
|
try {
|
|
48
57
|
const data = await apiClient.getGitStatus(project.id);
|
|
49
58
|
setGitStatus(data);
|
|
50
59
|
setGithubConfigured(data.githubAppConfigured);
|
|
60
|
+
if (data.sshPublicKey) setSshPublicKey(data.sshPublicKey);
|
|
51
61
|
} catch (err: any) {
|
|
52
62
|
setError(err.message);
|
|
53
63
|
}
|
|
@@ -165,6 +175,50 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
165
175
|
try {
|
|
166
176
|
await apiClient.disconnectGitRepo(project.id);
|
|
167
177
|
setSuccess('Repository disconnected');
|
|
178
|
+
setSshPublicKey(null);
|
|
179
|
+
onProjectUpdated();
|
|
180
|
+
await loadStatus();
|
|
181
|
+
} catch (err: any) {
|
|
182
|
+
setError(err.message);
|
|
183
|
+
} finally {
|
|
184
|
+
setLoading(false);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const handleGenerateSshKey = async () => {
|
|
189
|
+
setLoading(true);
|
|
190
|
+
setError(null);
|
|
191
|
+
setCopied(false);
|
|
192
|
+
try {
|
|
193
|
+
const data = await apiClient.generateSshKey(project.id);
|
|
194
|
+
setSshPublicKey(data.publicKey);
|
|
195
|
+
setSuccess(sshPublicKey ? 'SSH keypair regenerated — old key is now invalid' : 'SSH keypair generated');
|
|
196
|
+
onProjectUpdated();
|
|
197
|
+
} catch (err: any) {
|
|
198
|
+
setError(err.message);
|
|
199
|
+
} finally {
|
|
200
|
+
setLoading(false);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const handleCopyPublicKey = async () => {
|
|
205
|
+
if (!sshPublicKey) return;
|
|
206
|
+
try {
|
|
207
|
+
await navigator.clipboard.writeText(sshPublicKey);
|
|
208
|
+
setCopied(true);
|
|
209
|
+
setTimeout(() => setCopied(false), 2000);
|
|
210
|
+
} catch {
|
|
211
|
+
setError('Failed to copy to clipboard');
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const handleConnectSsh = async () => {
|
|
216
|
+
if (!sshCloneUrl.trim()) return;
|
|
217
|
+
setLoading(true);
|
|
218
|
+
setError(null);
|
|
219
|
+
try {
|
|
220
|
+
await apiClient.connectSshRepo(project.id, sshCloneUrl.trim());
|
|
221
|
+
setSuccess('Repository connected via SSH');
|
|
168
222
|
onProjectUpdated();
|
|
169
223
|
await loadStatus();
|
|
170
224
|
} catch (err: any) {
|
|
@@ -175,98 +229,105 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
175
229
|
};
|
|
176
230
|
|
|
177
231
|
return (
|
|
178
|
-
<div className="
|
|
179
|
-
<div className="
|
|
180
|
-
<div className="
|
|
181
|
-
<h3>Git Repository — {project.name}</h3>
|
|
182
|
-
<button className="
|
|
232
|
+
<div className="fixed inset-0 bg-black/50 z-[1000] flex items-center justify-center" onClick={onClose}>
|
|
233
|
+
<div className="bg-surface-alt border border-edge rounded-lg w-[480px] max-w-[90vw] max-h-[80vh] overflow-y-auto shadow-[0_8px_32px_var(--panel-shadow)] font-mono text-[13px]" onClick={e => e.stopPropagation()}>
|
|
234
|
+
<div className="flex justify-between items-center px-5 pt-4 pb-3 border-b border-edge">
|
|
235
|
+
<h3 className="m-0 text-sm text-content font-semibold">Git Repository — {project.name}</h3>
|
|
236
|
+
<button className="bg-none border-none text-content-secondary cursor-pointer text-lg px-1 leading-none hover:text-content" onClick={onClose}>×</button>
|
|
183
237
|
</div>
|
|
184
238
|
|
|
185
|
-
{error && <div className="
|
|
186
|
-
{success && <div className="
|
|
239
|
+
{error && <div className="px-5 py-2 text-error text-xs bg-[rgba(255,107,107,0.08)] border-b border-edge">{error}</div>}
|
|
240
|
+
{success && <div className="px-5 py-2 text-[#69db7c] text-xs bg-[rgba(105,219,124,0.08)] border-b border-edge">{success}</div>}
|
|
187
241
|
|
|
188
|
-
<div className="
|
|
189
|
-
<button className={
|
|
190
|
-
<button className={
|
|
191
|
-
<button className={
|
|
192
|
-
<button className={
|
|
242
|
+
<div className="flex border-b border-edge px-4">
|
|
243
|
+
<button className={tabCls(tab === 'status')} onClick={() => { setTab('status'); setError(null); setSuccess(null); }}>Status</button>
|
|
244
|
+
<button className={tabCls(tab === 'github')} onClick={() => { setTab('github'); setError(null); setSuccess(null); handleLoadInstallations(); }}>GitHub</button>
|
|
245
|
+
<button className={tabCls(tab === 'ssh')} onClick={() => { setTab('ssh'); setError(null); setSuccess(null); }}>SSH Key</button>
|
|
246
|
+
<button className={tabCls(tab === 'url')} onClick={() => { setTab('url'); setError(null); setSuccess(null); }}>Clone URL</button>
|
|
247
|
+
<button className={tabCls(tab === 'init')} onClick={() => { setTab('init'); setError(null); setSuccess(null); }}>Init</button>
|
|
193
248
|
</div>
|
|
194
249
|
|
|
195
|
-
<div className="
|
|
250
|
+
<div className="px-5 py-4">
|
|
196
251
|
{tab === 'status' && (
|
|
197
|
-
<div
|
|
252
|
+
<div>
|
|
198
253
|
{gitStatus ? (
|
|
199
254
|
<>
|
|
200
|
-
<div className="
|
|
201
|
-
<span className="
|
|
202
|
-
<span className={`
|
|
255
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
256
|
+
<span className="text-content-secondary text-xs">Workspace:</span>
|
|
257
|
+
<span className={`text-xs ${gitStatus.hasWorkspace ? 'text-[#69db7c]' : 'text-content'}`}>
|
|
203
258
|
{gitStatus.hasWorkspace ? 'Configured' : 'Not configured'}
|
|
204
259
|
</span>
|
|
205
260
|
</div>
|
|
206
261
|
{gitStatus.hasWorkspace && (
|
|
207
262
|
<>
|
|
208
|
-
<div className="
|
|
209
|
-
<span className="
|
|
210
|
-
<span className={`
|
|
263
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
264
|
+
<span className="text-content-secondary text-xs">Remote:</span>
|
|
265
|
+
<span className={`text-xs ${gitStatus.hasRemote ? 'text-[#69db7c]' : 'text-content'}`}>
|
|
211
266
|
{gitStatus.hasRemote ? 'Connected' : 'Local only'}
|
|
212
267
|
</span>
|
|
213
268
|
</div>
|
|
214
|
-
<div className="
|
|
215
|
-
<span className="
|
|
216
|
-
<span className="
|
|
269
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
270
|
+
<span className="text-content-secondary text-xs">Branch:</span>
|
|
271
|
+
<span className="text-xs text-content">{gitStatus.currentBranch || '-'}</span>
|
|
217
272
|
</div>
|
|
218
273
|
</>
|
|
219
274
|
)}
|
|
220
275
|
{project.githubRepoFullName && (
|
|
221
|
-
<div className="
|
|
222
|
-
<span className="
|
|
223
|
-
<span className="
|
|
276
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
277
|
+
<span className="text-content-secondary text-xs">GitHub Repo:</span>
|
|
278
|
+
<span className="text-xs text-content">{project.githubRepoFullName}</span>
|
|
224
279
|
</div>
|
|
225
280
|
)}
|
|
226
281
|
{project.repoUrl && !project.githubRepoFullName && (
|
|
227
|
-
<div className="
|
|
228
|
-
<span className="
|
|
229
|
-
<span className="
|
|
282
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
283
|
+
<span className="text-content-secondary text-xs">Clone URL:</span>
|
|
284
|
+
<span className="text-xs text-content max-w-60 overflow-hidden text-ellipsis whitespace-nowrap">{project.repoUrl}</span>
|
|
230
285
|
</div>
|
|
231
286
|
)}
|
|
232
|
-
<div className="
|
|
233
|
-
<span className="
|
|
234
|
-
<span className=
|
|
287
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
288
|
+
<span className="text-content-secondary text-xs">Auth Method:</span>
|
|
289
|
+
<span className="text-xs text-content">
|
|
290
|
+
{gitStatus.gitAuthMethod === 'ssh_key' ? 'SSH Key' : gitStatus.gitAuthMethod === 'github_app' ? 'GitHub App' : 'None'}
|
|
291
|
+
</span>
|
|
292
|
+
</div>
|
|
293
|
+
<div className="flex justify-between py-1.5 border-b border-edge">
|
|
294
|
+
<span className="text-content-secondary text-xs">GitHub App:</span>
|
|
295
|
+
<span className={`text-xs ${gitStatus.githubAppConfigured ? 'text-[#69db7c]' : 'text-content'}`}>
|
|
235
296
|
{gitStatus.githubAppConfigured ? 'Configured' : 'Not configured'}
|
|
236
297
|
</span>
|
|
237
298
|
</div>
|
|
238
299
|
{gitStatus.hasWorkspace && (
|
|
239
|
-
<button className=
|
|
300
|
+
<button className={btnDanger} onClick={handleDisconnect} disabled={loading}>
|
|
240
301
|
Disconnect
|
|
241
302
|
</button>
|
|
242
303
|
)}
|
|
243
304
|
</>
|
|
244
305
|
) : (
|
|
245
|
-
<div className="
|
|
306
|
+
<div className="text-content-muted text-center py-5">Loading...</div>
|
|
246
307
|
)}
|
|
247
308
|
</div>
|
|
248
309
|
)}
|
|
249
310
|
|
|
250
311
|
{tab === 'github' && (
|
|
251
|
-
<div
|
|
312
|
+
<div>
|
|
252
313
|
{!githubConfigured ? (
|
|
253
|
-
<div className="
|
|
314
|
+
<div className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
254
315
|
GitHub App not configured. Set GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY environment variables.
|
|
255
|
-
<button className=
|
|
316
|
+
<button className={btnBase} onClick={handleTestConnection} disabled={loading}>
|
|
256
317
|
Test Connection
|
|
257
318
|
</button>
|
|
258
319
|
</div>
|
|
259
320
|
) : (
|
|
260
321
|
<>
|
|
261
322
|
{installations.length === 0 ? (
|
|
262
|
-
<div className="
|
|
323
|
+
<div className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
263
324
|
No GitHub App installations found. Install the app on your GitHub organization or account.
|
|
264
325
|
</div>
|
|
265
326
|
) : (
|
|
266
|
-
<div
|
|
267
|
-
<label className="
|
|
327
|
+
<div>
|
|
328
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5 mt-3">Installation:</label>
|
|
268
329
|
<select
|
|
269
|
-
className="
|
|
330
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-xs"
|
|
270
331
|
value={selectedInstallation}
|
|
271
332
|
onChange={e => handleLoadRepos(e.target.value)}
|
|
272
333
|
>
|
|
@@ -281,10 +342,10 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
281
342
|
)}
|
|
282
343
|
|
|
283
344
|
{repos.length > 0 && (
|
|
284
|
-
<div
|
|
285
|
-
<label className="
|
|
345
|
+
<div>
|
|
346
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5 mt-3">Repository:</label>
|
|
286
347
|
<select
|
|
287
|
-
className="
|
|
348
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-xs"
|
|
288
349
|
value={selectedRepo}
|
|
289
350
|
onChange={e => setSelectedRepo(e.target.value)}
|
|
290
351
|
>
|
|
@@ -296,7 +357,7 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
296
357
|
))}
|
|
297
358
|
</select>
|
|
298
359
|
<button
|
|
299
|
-
className=
|
|
360
|
+
className={btnPrimary}
|
|
300
361
|
onClick={handleConnectGitHub}
|
|
301
362
|
disabled={loading || !selectedRepo}
|
|
302
363
|
>
|
|
@@ -309,11 +370,79 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
309
370
|
</div>
|
|
310
371
|
)}
|
|
311
372
|
|
|
373
|
+
{tab === 'ssh' && (
|
|
374
|
+
<div>
|
|
375
|
+
<p className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
376
|
+
Generate an SSH deploy key for this project. Add the public key to your GitHub repository
|
|
377
|
+
as a deploy key to enable SSH-based git operations.
|
|
378
|
+
</p>
|
|
379
|
+
|
|
380
|
+
{!sshPublicKey ? (
|
|
381
|
+
<button
|
|
382
|
+
className={btnPrimary}
|
|
383
|
+
onClick={handleGenerateSshKey}
|
|
384
|
+
disabled={loading}
|
|
385
|
+
>
|
|
386
|
+
{loading ? 'Generating...' : 'Generate SSH Key'}
|
|
387
|
+
</button>
|
|
388
|
+
) : (
|
|
389
|
+
<>
|
|
390
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5 mt-3">Public key:</label>
|
|
391
|
+
<div className="relative">
|
|
392
|
+
<textarea
|
|
393
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-[11px] outline-none resize-none h-16"
|
|
394
|
+
readOnly
|
|
395
|
+
value={sshPublicKey}
|
|
396
|
+
/>
|
|
397
|
+
<button
|
|
398
|
+
className="absolute top-1.5 right-1.5 px-2 py-1 bg-surface-raised border border-edge rounded text-[10px] text-content-secondary hover:text-content cursor-pointer"
|
|
399
|
+
onClick={handleCopyPublicKey}
|
|
400
|
+
>
|
|
401
|
+
{copied ? 'Copied!' : 'Copy'}
|
|
402
|
+
</button>
|
|
403
|
+
</div>
|
|
404
|
+
|
|
405
|
+
<div className="mt-3 p-2.5 bg-[rgba(255,200,50,0.08)] border border-[rgba(255,200,50,0.2)] rounded text-xs text-content-secondary leading-relaxed">
|
|
406
|
+
Add this key as a <strong className="text-content">deploy key</strong> in your GitHub repo settings.
|
|
407
|
+
Make sure to check <strong className="text-content">"Allow write access"</strong> so the system can push commits.
|
|
408
|
+
</div>
|
|
409
|
+
|
|
410
|
+
<div className="mt-4 border-t border-edge pt-4">
|
|
411
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5">SSH clone URL:</label>
|
|
412
|
+
<input
|
|
413
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-xs outline-none focus:border-accent"
|
|
414
|
+
type="text"
|
|
415
|
+
placeholder="git@github.com:org/repo.git"
|
|
416
|
+
value={sshCloneUrl}
|
|
417
|
+
onChange={e => setSshCloneUrl(e.target.value)}
|
|
418
|
+
onKeyDown={e => { if (e.key === 'Enter') handleConnectSsh(); }}
|
|
419
|
+
/>
|
|
420
|
+
<button
|
|
421
|
+
className={btnPrimary}
|
|
422
|
+
onClick={handleConnectSsh}
|
|
423
|
+
disabled={loading || !sshCloneUrl.trim()}
|
|
424
|
+
>
|
|
425
|
+
{loading ? 'Cloning...' : 'Clone & Connect via SSH'}
|
|
426
|
+
</button>
|
|
427
|
+
</div>
|
|
428
|
+
|
|
429
|
+
<button
|
|
430
|
+
className={`${btnBase} mt-4`}
|
|
431
|
+
onClick={handleGenerateSshKey}
|
|
432
|
+
disabled={loading}
|
|
433
|
+
>
|
|
434
|
+
{loading ? 'Regenerating...' : 'Regenerate Key'}
|
|
435
|
+
</button>
|
|
436
|
+
</>
|
|
437
|
+
)}
|
|
438
|
+
</div>
|
|
439
|
+
)}
|
|
440
|
+
|
|
312
441
|
{tab === 'url' && (
|
|
313
|
-
<div
|
|
314
|
-
<label className="
|
|
442
|
+
<div>
|
|
443
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5 mt-3">Git clone URL:</label>
|
|
315
444
|
<input
|
|
316
|
-
className="
|
|
445
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-xs outline-none focus:border-accent"
|
|
317
446
|
type="text"
|
|
318
447
|
placeholder="https://github.com/org/repo.git"
|
|
319
448
|
value={cloneUrl}
|
|
@@ -321,7 +450,7 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
321
450
|
onKeyDown={e => { if (e.key === 'Enter') handleConnectUrl(); }}
|
|
322
451
|
/>
|
|
323
452
|
<button
|
|
324
|
-
className=
|
|
453
|
+
className={btnPrimary}
|
|
325
454
|
onClick={handleConnectUrl}
|
|
326
455
|
disabled={loading || !cloneUrl.trim()}
|
|
327
456
|
>
|
|
@@ -331,13 +460,13 @@ export function GitRepoModal({ project, onClose, onProjectUpdated }: GitRepoModa
|
|
|
331
460
|
)}
|
|
332
461
|
|
|
333
462
|
{tab === 'init' && (
|
|
334
|
-
<div
|
|
335
|
-
<p className="
|
|
463
|
+
<div>
|
|
464
|
+
<p className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
336
465
|
Initialize a new empty local git repository for this project.
|
|
337
466
|
You can connect it to a remote later.
|
|
338
467
|
</p>
|
|
339
468
|
<button
|
|
340
|
-
className=
|
|
469
|
+
className={btnPrimary}
|
|
341
470
|
onClick={handleInit}
|
|
342
471
|
disabled={loading}
|
|
343
472
|
>
|
package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx
CHANGED
|
@@ -35,86 +35,84 @@ export function GraphLegend({ visible, onTypeToggle, onSearchChange }: GraphLege
|
|
|
35
35
|
if (!visible) return null;
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
|
-
<div
|
|
39
|
-
<div className="
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
<div className="fixed bottom-4 left-4 bg-surface-alt border border-edge rounded-md z-[150] max-h-[calc(100vh-116px)] overflow-y-auto min-w-[180px] shadow-[0_2px_8px_var(--panel-shadow)]">
|
|
39
|
+
<div className="relative flex flex-wrap items-center gap-1.5 px-2.5 py-2 border-b border-edge" id="search-container">
|
|
40
|
+
<input
|
|
41
|
+
type="text"
|
|
42
|
+
className="flex-1 min-w-0 h-7 px-2 bg-surface-raised border border-edge rounded text-content font-mono text-[11px] outline-none transition-[border-color] duration-150 focus:border-accent placeholder:text-content-muted"
|
|
43
|
+
placeholder="Search nodes..."
|
|
44
|
+
onChange={(e) => onSearchChange(e.target.value)}
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
<div className="flex items-center gap-1.5 px-3 py-2 text-content-secondary font-mono text-[11px] font-semibold uppercase tracking-wide"><span>Legend</span></div>
|
|
48
|
+
<div className="px-3 pb-2.5">
|
|
49
|
+
<div className="mt-2 first:mt-0">
|
|
50
|
+
<div className="text-[10px] text-content-muted uppercase tracking-wider mb-1">Node Types</div>
|
|
51
|
+
<div className="flex flex-col gap-[3px]">
|
|
52
|
+
{Object.entries(NODE_COLORS).map(([type, color]) => {
|
|
53
|
+
const shape = NODE_SHAPES[type] || 'circle';
|
|
54
|
+
const pathD = nodeShapePath(shape, 6);
|
|
55
|
+
const active = !hiddenTypes.has(type);
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
key={type}
|
|
59
|
+
className={`flex items-center gap-2 cursor-pointer transition-opacity duration-150 rounded px-1 py-0.5 -mx-1 -my-0.5 hover:bg-surface-raised ${active ? 'opacity-100' : 'opacity-40'}`}
|
|
60
|
+
onClick={() => handleTypeClick(type)}
|
|
61
|
+
title={`Toggle ${LEGEND_LABELS[type]}`}
|
|
62
|
+
>
|
|
63
|
+
<svg className="shrink-0" width="16" height="16" viewBox="-8 -8 16 16">
|
|
64
|
+
<path d={pathD} fill={color} />
|
|
65
|
+
</svg>
|
|
66
|
+
<span className="text-[11px] text-content-secondary whitespace-nowrap">{LEGEND_LABELS[type] || type}</span>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
})}
|
|
70
|
+
</div>
|
|
47
71
|
</div>
|
|
48
|
-
<div className="
|
|
49
|
-
|
|
50
|
-
<div className="
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const pathD = nodeShapePath(shape, 6);
|
|
56
|
-
const active = !hiddenTypes.has(type);
|
|
57
|
-
return (
|
|
58
|
-
<div
|
|
59
|
-
key={type}
|
|
60
|
-
className={`legend-item legend-type-toggle${active ? ' active' : ''}`}
|
|
61
|
-
onClick={() => handleTypeClick(type)}
|
|
62
|
-
title={`Toggle ${LEGEND_LABELS[type]}`}
|
|
63
|
-
>
|
|
64
|
-
<svg className="legend-node-svg" width="16" height="16" viewBox="-8 -8 16 16">
|
|
65
|
-
<path d={pathD} fill={color} />
|
|
66
|
-
</svg>
|
|
67
|
-
<span className="legend-item-label">{LEGEND_LABELS[type] || type}</span>
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
})}
|
|
71
|
-
</div>
|
|
72
|
+
<div className="mt-2 first:mt-0">
|
|
73
|
+
<div className="text-[10px] text-content-muted uppercase tracking-wider mb-1">Node Size</div>
|
|
74
|
+
<div className="flex items-center gap-1.5">
|
|
75
|
+
<span className="w-2 h-2 rounded-full" style={{ background: 'var(--text-muted)' }} />
|
|
76
|
+
<span className="text-[10px] text-content-muted">{'\u2192'}</span>
|
|
77
|
+
<span className="w-[18px] h-[18px] rounded-full" style={{ background: 'var(--text-muted)' }} />
|
|
78
|
+
<span className="text-[11px] text-content-secondary whitespace-nowrap">more connections = larger</span>
|
|
72
79
|
</div>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
<button className="flex items-center gap-1.5 w-full px-3 py-1.5 bg-transparent border-none border-t border-edge text-content-secondary font-mono text-[11px] font-semibold cursor-pointer uppercase tracking-wide hover:text-content" onClick={toggleEdges} title="Toggle edge relations">
|
|
83
|
+
<span className="text-[9px]" dangerouslySetInnerHTML={{ __html: edgesCollapsed ? '▶' : '▼' }} />
|
|
84
|
+
<span>Edge Relations</span>
|
|
85
|
+
</button>
|
|
86
|
+
<div className={edgesCollapsed ? 'hidden' : 'px-3 pb-2.5'}>
|
|
87
|
+
<div className="mt-2 first:mt-0">
|
|
88
|
+
<div className="flex flex-col gap-[3px]">
|
|
89
|
+
{Object.entries(EDGE_COLORS).map(([relation, color]) => (
|
|
90
|
+
<div key={relation} className="flex items-center gap-2">
|
|
91
|
+
<span className="w-5 h-[3px] rounded-sm shrink-0" style={{ background: color }} />
|
|
92
|
+
<span className="text-[11px] text-content-secondary whitespace-nowrap">{EDGE_LABELS[relation] || relation}</span>
|
|
93
|
+
</div>
|
|
94
|
+
))}
|
|
81
95
|
</div>
|
|
82
96
|
</div>
|
|
83
|
-
<
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<div className="legend-items">
|
|
90
|
-
{Object.entries(EDGE_COLORS).map(([relation, color]) => (
|
|
91
|
-
<div key={relation} className="legend-item">
|
|
92
|
-
<span className="legend-edge-swatch" style={{ background: color }} />
|
|
93
|
-
<span className="legend-item-label">{EDGE_LABELS[relation] || relation}</span>
|
|
94
|
-
</div>
|
|
95
|
-
))}
|
|
97
|
+
<div className="mt-2 first:mt-0">
|
|
98
|
+
<div className="text-[10px] text-content-muted uppercase tracking-wider mb-1">Node Border</div>
|
|
99
|
+
<div className="flex flex-col gap-[3px]">
|
|
100
|
+
<div className="flex items-center gap-2">
|
|
101
|
+
<span className="w-3 h-3 rounded-full shrink-0 !bg-surface-raised border-2 border-[#ffd43b]" />
|
|
102
|
+
<span className="text-[11px] text-content-secondary whitespace-nowrap">incomplete</span>
|
|
96
103
|
</div>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<div className="legend-items">
|
|
101
|
-
<div className="legend-item">
|
|
102
|
-
<span className="legend-node-swatch legend-border-yellow" />
|
|
103
|
-
<span className="legend-item-label">incomplete</span>
|
|
104
|
-
</div>
|
|
105
|
-
<div className="legend-item">
|
|
106
|
-
<span className="legend-node-swatch legend-border-red" />
|
|
107
|
-
<span className="legend-item-label">has open questions</span>
|
|
108
|
-
</div>
|
|
104
|
+
<div className="flex items-center gap-2">
|
|
105
|
+
<span className="w-3 h-3 rounded-full shrink-0 !bg-surface-raised border-2 border-[#ff6b6b]" />
|
|
106
|
+
<span className="text-[11px] text-content-secondary whitespace-nowrap">has open questions</span>
|
|
109
107
|
</div>
|
|
110
108
|
</div>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
</
|
|
109
|
+
</div>
|
|
110
|
+
<div className="mt-2 first:mt-0">
|
|
111
|
+
<div className="text-[10px] text-content-muted uppercase tracking-wider mb-1">Gap Indicators</div>
|
|
112
|
+
<div className="flex flex-col gap-[3px]">
|
|
113
|
+
<div className="flex items-center gap-2">
|
|
114
|
+
<span className="w-3 h-3 rounded-full shrink-0 legend-gap-pulse" />
|
|
115
|
+
<span className="text-[11px] text-content-secondary whitespace-nowrap">{'\u26A0'} pulsing = open questions</span>
|
|
118
116
|
</div>
|
|
119
117
|
</div>
|
|
120
118
|
</div>
|
package/templates/assistkick-product-system/packages/frontend/src/components/GraphSettings.tsx
CHANGED
|
@@ -89,18 +89,18 @@ export function GraphSettings({ isOpen, onClose, graphRef }: GraphSettingsProps)
|
|
|
89
89
|
];
|
|
90
90
|
|
|
91
91
|
return (
|
|
92
|
-
<div className={`
|
|
93
|
-
<div className="
|
|
94
|
-
<span className="
|
|
95
|
-
<button className="
|
|
92
|
+
<div className={`fixed top-[84px] right-0 w-[280px] bg-panel border-l border-edge shadow-[-4px_0_16px_var(--panel-shadow)] transition-transform duration-[250ms] ease-out z-[250] flex flex-col ${isOpen ? 'translate-x-0' : 'translate-x-full'}`} ref={sheetRef}>
|
|
93
|
+
<div className="flex items-center justify-between px-4 py-3 border-b border-edge min-h-12">
|
|
94
|
+
<span className="text-[13px] font-semibold text-content uppercase tracking-wide">Settings</span>
|
|
95
|
+
<button className="bg-transparent border-none text-content-secondary text-lg cursor-pointer px-2 py-1 rounded hover:bg-tab-hover hover:text-content" onClick={onClose}>×</button>
|
|
96
96
|
</div>
|
|
97
|
-
<div className="
|
|
97
|
+
<div className="px-4 py-3 flex flex-col">
|
|
98
98
|
{toggleItems.map(({ key, label }) => (
|
|
99
|
-
<label key={key} className="
|
|
100
|
-
<span className="
|
|
99
|
+
<label key={key} className="flex items-center justify-between py-2.5 border-b border-edge cursor-pointer last:border-b-0">
|
|
100
|
+
<span className="text-xs text-content-secondary">{label}</span>
|
|
101
101
|
<input
|
|
102
102
|
type="checkbox"
|
|
103
|
-
className="settings-toggle"
|
|
103
|
+
className="settings-toggle appearance-none w-9 h-5 bg-surface-raised border border-edge rounded-[10px] relative cursor-pointer transition-[background,border-color] duration-150 shrink-0 checked:bg-[rgba(77,171,247,0.2)] checked:border-accent"
|
|
104
104
|
checked={settings[key]}
|
|
105
105
|
onChange={() => handleToggle(key)}
|
|
106
106
|
/>
|
|
@@ -365,6 +365,6 @@ export const GraphView = forwardRef<GraphViewHandle, GraphViewProps>(
|
|
|
365
365
|
return () => window.removeEventListener('resize', handleResize);
|
|
366
366
|
}, [visible]);
|
|
367
367
|
|
|
368
|
-
return <div
|
|
368
|
+
return <div className="w-full h-[calc(100vh-44px)] overflow-hidden" ref={containerRef} style={{ display: visible ? 'block' : 'none' }} />;
|
|
369
369
|
}
|
|
370
370
|
);
|