@assistkick/create 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/create.js +0 -0
- package/package.json +9 -7
- package/templates/assistkick-product-system/.env.example +1 -0
- package/templates/assistkick-product-system/local.db +0 -0
- package/templates/assistkick-product-system/package.json +4 -2
- package/templates/assistkick-product-system/packages/backend/package.json +2 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +165 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +358 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +356 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +96 -1
- package/templates/assistkick-product-system/packages/backend/src/routes/graph.ts +1 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/kanban.ts +61 -6
- package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +200 -84
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +6 -3
- package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +53 -17
- package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +218 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +119 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +158 -0
- package/templates/assistkick-product-system/packages/backend/src/server.ts +60 -9
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +489 -0
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +416 -0
- package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.test.ts +189 -0
- package/templates/assistkick-product-system/packages/backend/src/services/bundle_service.ts +182 -0
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +43 -77
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +16 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +73 -2
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +4 -4
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +87 -11
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +210 -69
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +210 -215
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +162 -0
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +148 -0
- package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +11 -5
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.test.ts +64 -0
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +134 -0
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.test.ts +256 -0
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +258 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_group_service.ts +106 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.test.ts +275 -0
- package/templates/assistkick-product-system/packages/backend/src/services/workflow_service.ts +245 -0
- package/templates/assistkick-product-system/packages/frontend/package-lock.json +3455 -0
- package/templates/assistkick-product-system/packages/frontend/package.json +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/App.tsx +8 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +458 -18
- package/templates/assistkick-product-system/packages/frontend/src/api/client_files.test.ts +172 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client_video.test.ts +238 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +307 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/CoherenceView.tsx +82 -66
- package/templates/assistkick-product-system/packages/frontend/src/components/CompositionPlaceholder.tsx +97 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/DesignSystemView.tsx +20 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +57 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +313 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeContextMenu.tsx +61 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +73 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +404 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx +187 -56
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +71 -73
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphSettings.tsx +8 -8
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphView.tsx +1 -1
- package/templates/assistkick-product-system/packages/frontend/src/components/InviteUserDialog.tsx +15 -11
- package/templates/assistkick-product-system/packages/frontend/src/components/IterationCommentModal.tsx +80 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +263 -167
- package/templates/assistkick-product-system/packages/frontend/src/components/LoginPage.tsx +14 -14
- package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +54 -33
- package/templates/assistkick-product-system/packages/frontend/src/components/QaIssueSheet.tsx +32 -49
- package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +43 -48
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +121 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +20 -14
- package/templates/assistkick-product-system/packages/frontend/src/components/UsersView.tsx +52 -52
- package/templates/assistkick-product-system/packages/frontend/src/components/VideoGallery.tsx +313 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/VideographyView.tsx +250 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/WorkflowsView.tsx +474 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/AccentBorderList.tsx +53 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/Button.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonGroup.tsx +29 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ButtonShowcase.tsx +221 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/CardGlass.tsx +141 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/CompletionRing.tsx +30 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/ContentCard.tsx +34 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/IconButton.tsx +74 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCard.tsx +103 -87
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KanbanCardShowcase.tsx +9 -188
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/Kbd.tsx +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/KindBadge.tsx +21 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/NavBarSidekick.tsx +81 -37
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/SidePanelShowcase.tsx +370 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/SideSheet.tsx +64 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ds/StatusDot.tsx +18 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCardPositionNode.tsx +36 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/CheckCycleCountNode.tsx +60 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/EndNode.tsx +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GenerateTTSNode.tsx +52 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +189 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +123 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RebuildBundleNode.tsx +20 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RenderVideoNode.tsx +72 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/RunAgentNode.tsx +51 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/SetCardMetadataNode.tsx +53 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/StartNode.tsx +18 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/TransitionCardNode.tsx +59 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +341 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +643 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/autoLayout.ts +103 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/edgeColors.ts +35 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +246 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.test.ts +119 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +136 -0
- package/templates/assistkick-product-system/packages/frontend/src/constants/graph.ts +13 -11
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useAutoSave.ts +75 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useToast.tsx +16 -3
- package/templates/assistkick-product-system/packages/frontend/src/pages/accept_invitation_page.tsx +30 -27
- package/templates/assistkick-product-system/packages/frontend/src/pages/forgot_password_page.tsx +18 -15
- package/templates/assistkick-product-system/packages/frontend/src/pages/register_page.tsx +21 -18
- package/templates/assistkick-product-system/packages/frontend/src/pages/reset_password_page.tsx +28 -25
- package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +1 -1
- package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +13 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +6 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +6 -3
- package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +4 -4
- package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +275 -3535
- package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.test.ts +167 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/auto_save_service.ts +101 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.test.ts +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/composition_matcher.ts +17 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.test.ts +145 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/file_utils.ts +42 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.test.ts +4 -10
- package/templates/assistkick-product-system/packages/frontend/src/utils/task_status.ts +19 -1
- package/templates/assistkick-product-system/packages/frontend/vite.config.ts +5 -0
- package/templates/assistkick-product-system/packages/shared/db/local.db +0 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0004_tidy_matthew_murdock.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0005_mysterious_falcon.sql +692 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0006_next_venom.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0007_deep_barracuda.sql +39 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0008_puzzling_hannibal_king.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0009_amused_beast.sql +8 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0010_spotty_moira_mactaggert.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0011_goofy_snowbird.sql +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0011_supreme_doctor_octopus.sql +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0013_reflective_prowler.sql +15 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0014_nifty_punisher.sql +15 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0004_snapshot.json +921 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0005_snapshot.json +1042 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0006_snapshot.json +1101 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0007_snapshot.json +1336 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0008_snapshot.json +1275 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0009_snapshot.json +1327 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0010_snapshot.json +1393 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0011_snapshot.json +1436 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0013_snapshot.json +1538 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0014_snapshot.json +1545 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +77 -0
- package/templates/assistkick-product-system/packages/shared/db/schema.ts +114 -0
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +32 -7
- package/templates/assistkick-product-system/packages/shared/lib/constants.ts +9 -0
- package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +12 -4
- package/templates/assistkick-product-system/packages/shared/lib/graph.ts +5 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +1999 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +1437 -0
- package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +211 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +43 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +13 -2
- package/templates/assistkick-product-system/packages/shared/tools/get_kanban.ts +1 -1
- package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.test.ts +226 -0
- package/templates/assistkick-product-system/packages/shared/tools/migrate_epics.ts +251 -0
- package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -2
- package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.test.ts +10 -0
- package/templates/assistkick-product-system/packages/shared/utils/hello_workflow.ts +6 -0
- package/templates/assistkick-product-system/packages/video/Root.tsx +85 -0
- package/templates/assistkick-product-system/packages/video/components/email_scene.tsx +231 -0
- package/templates/assistkick-product-system/packages/video/components/outro_scene.tsx +153 -0
- package/templates/assistkick-product-system/packages/video/components/part_divider.tsx +90 -0
- package/templates/assistkick-product-system/packages/video/components/scene.tsx +226 -0
- package/templates/assistkick-product-system/packages/video/components/theme.ts +22 -0
- package/templates/assistkick-product-system/packages/video/components/title_scene.tsx +169 -0
- package/templates/assistkick-product-system/packages/video/components/video_split_layout.tsx +84 -0
- package/templates/assistkick-product-system/packages/video/compositions/.gitkeep +0 -0
- package/templates/assistkick-product-system/packages/video/index.ts +4 -0
- package/templates/assistkick-product-system/packages/video/package.json +28 -0
- package/templates/assistkick-product-system/packages/video/remotion.config.ts +11 -0
- package/templates/assistkick-product-system/packages/video/scripts/process_script.test.ts +326 -0
- package/templates/assistkick-product-system/packages/video/scripts/process_script.ts +630 -0
- package/templates/assistkick-product-system/packages/video/style.css +1 -0
- package/templates/assistkick-product-system/packages/video/tsconfig.json +18 -0
- package/templates/assistkick-product-system/tests/graph_legend.test.ts +2 -1
- package/templates/assistkick-product-system/tests/video_render_service.test.ts +181 -0
- package/templates/assistkick-product-system/tests/web_terminal.test.ts +219 -455
- package/templates/assistkick-product-system/tests/workflow_integration.test.ts +341 -0
- package/templates/skills/assistkick-developer/SKILL.md +3 -0
- package/templates/skills/assistkick-developer/references/react_development_guidelines.md +225 -0
- package/templates/skills/product-system/graph.json +1890 -0
- package/templates/skills/product-system/kanban.json +304 -0
- package/templates/skills/product-system/nodes/comp_001.md +56 -0
- package/templates/skills/product-system/nodes/comp_002.md +57 -0
- package/templates/skills/product-system/nodes/data_001.md +51 -0
- package/templates/skills/product-system/nodes/data_002.md +40 -0
- package/templates/skills/product-system/nodes/data_004.md +38 -0
- package/templates/skills/product-system/nodes/dec_001.md +34 -0
- package/templates/skills/product-system/nodes/dec_016.md +32 -0
- package/templates/skills/product-system/nodes/feat_008.md +30 -0
- package/templates/skills/video-composition-agent/SKILL.md +232 -0
- package/templates/skills/video-script-writer/SKILL.md +136 -0
package/templates/assistkick-product-system/packages/frontend/src/components/GitRepoModal.tsx
CHANGED
|
@@ -17,7 +17,16 @@ interface Repo {
|
|
|
17
17
|
cloneUrl: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
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';
|
|
21
30
|
|
|
22
31
|
export function GitRepoModal() {
|
|
23
32
|
const project = useGitModalStore((s) => s.project)!;
|
|
@@ -28,24 +37,27 @@ export function GitRepoModal() {
|
|
|
28
37
|
const [error, setError] = useState<string | null>(null);
|
|
29
38
|
const [success, setSuccess] = useState<string | null>(null);
|
|
30
39
|
|
|
31
|
-
// Status tab
|
|
32
40
|
const [gitStatus, setGitStatus] = useState<any>(null);
|
|
33
41
|
|
|
34
|
-
// GitHub tab
|
|
35
42
|
const [installations, setInstallations] = useState<Installation[]>([]);
|
|
36
43
|
const [selectedInstallation, setSelectedInstallation] = useState<string>('');
|
|
37
44
|
const [repos, setRepos] = useState<Repo[]>([]);
|
|
38
45
|
const [selectedRepo, setSelectedRepo] = useState<string>('');
|
|
39
46
|
const [githubConfigured, setGithubConfigured] = useState(false);
|
|
40
47
|
|
|
41
|
-
// URL tab
|
|
42
48
|
const [cloneUrl, setCloneUrl] = useState('');
|
|
43
49
|
|
|
50
|
+
// SSH state
|
|
51
|
+
const [sshPublicKey, setSshPublicKey] = useState<string | null>(null);
|
|
52
|
+
const [sshCloneUrl, setSshCloneUrl] = useState('');
|
|
53
|
+
const [copied, setCopied] = useState(false);
|
|
54
|
+
|
|
44
55
|
const loadStatus = useCallback(async () => {
|
|
45
56
|
try {
|
|
46
57
|
const data = await apiClient.getGitStatus(project.id);
|
|
47
58
|
setGitStatus(data);
|
|
48
59
|
setGithubConfigured(data.githubAppConfigured);
|
|
60
|
+
if (data.sshPublicKey) setSshPublicKey(data.sshPublicKey);
|
|
49
61
|
} catch (err: any) {
|
|
50
62
|
setError(err.message);
|
|
51
63
|
}
|
|
@@ -163,6 +175,50 @@ export function GitRepoModal() {
|
|
|
163
175
|
try {
|
|
164
176
|
await apiClient.disconnectGitRepo(project.id);
|
|
165
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');
|
|
166
222
|
onProjectUpdated();
|
|
167
223
|
await loadStatus();
|
|
168
224
|
} catch (err: any) {
|
|
@@ -173,98 +229,105 @@ export function GitRepoModal() {
|
|
|
173
229
|
};
|
|
174
230
|
|
|
175
231
|
return (
|
|
176
|
-
<div className="
|
|
177
|
-
<div className="
|
|
178
|
-
<div className="
|
|
179
|
-
<h3>Git Repository — {project.name}</h3>
|
|
180
|
-
<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>
|
|
181
237
|
</div>
|
|
182
238
|
|
|
183
|
-
{error && <div className="
|
|
184
|
-
{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>}
|
|
185
241
|
|
|
186
|
-
<div className="
|
|
187
|
-
<button className={
|
|
188
|
-
<button className={
|
|
189
|
-
<button className={
|
|
190
|
-
<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>
|
|
191
248
|
</div>
|
|
192
249
|
|
|
193
|
-
<div className="
|
|
250
|
+
<div className="px-5 py-4">
|
|
194
251
|
{tab === 'status' && (
|
|
195
|
-
<div
|
|
252
|
+
<div>
|
|
196
253
|
{gitStatus ? (
|
|
197
254
|
<>
|
|
198
|
-
<div className="
|
|
199
|
-
<span className="
|
|
200
|
-
<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'}`}>
|
|
201
258
|
{gitStatus.hasWorkspace ? 'Configured' : 'Not configured'}
|
|
202
259
|
</span>
|
|
203
260
|
</div>
|
|
204
261
|
{gitStatus.hasWorkspace && (
|
|
205
262
|
<>
|
|
206
|
-
<div className="
|
|
207
|
-
<span className="
|
|
208
|
-
<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'}`}>
|
|
209
266
|
{gitStatus.hasRemote ? 'Connected' : 'Local only'}
|
|
210
267
|
</span>
|
|
211
268
|
</div>
|
|
212
|
-
<div className="
|
|
213
|
-
<span className="
|
|
214
|
-
<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>
|
|
215
272
|
</div>
|
|
216
273
|
</>
|
|
217
274
|
)}
|
|
218
275
|
{project.githubRepoFullName && (
|
|
219
|
-
<div className="
|
|
220
|
-
<span className="
|
|
221
|
-
<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>
|
|
222
279
|
</div>
|
|
223
280
|
)}
|
|
224
281
|
{project.repoUrl && !project.githubRepoFullName && (
|
|
225
|
-
<div className="
|
|
226
|
-
<span className="
|
|
227
|
-
<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>
|
|
228
285
|
</div>
|
|
229
286
|
)}
|
|
230
|
-
<div className="
|
|
231
|
-
<span className="
|
|
232
|
-
<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'}`}>
|
|
233
296
|
{gitStatus.githubAppConfigured ? 'Configured' : 'Not configured'}
|
|
234
297
|
</span>
|
|
235
298
|
</div>
|
|
236
299
|
{gitStatus.hasWorkspace && (
|
|
237
|
-
<button className=
|
|
300
|
+
<button className={btnDanger} onClick={handleDisconnect} disabled={loading}>
|
|
238
301
|
Disconnect
|
|
239
302
|
</button>
|
|
240
303
|
)}
|
|
241
304
|
</>
|
|
242
305
|
) : (
|
|
243
|
-
<div className="
|
|
306
|
+
<div className="text-content-muted text-center py-5">Loading...</div>
|
|
244
307
|
)}
|
|
245
308
|
</div>
|
|
246
309
|
)}
|
|
247
310
|
|
|
248
311
|
{tab === 'github' && (
|
|
249
|
-
<div
|
|
312
|
+
<div>
|
|
250
313
|
{!githubConfigured ? (
|
|
251
|
-
<div className="
|
|
314
|
+
<div className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
252
315
|
GitHub App not configured. Set GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY environment variables.
|
|
253
|
-
<button className=
|
|
316
|
+
<button className={btnBase} onClick={handleTestConnection} disabled={loading}>
|
|
254
317
|
Test Connection
|
|
255
318
|
</button>
|
|
256
319
|
</div>
|
|
257
320
|
) : (
|
|
258
321
|
<>
|
|
259
322
|
{installations.length === 0 ? (
|
|
260
|
-
<div className="
|
|
323
|
+
<div className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
261
324
|
No GitHub App installations found. Install the app on your GitHub organization or account.
|
|
262
325
|
</div>
|
|
263
326
|
) : (
|
|
264
|
-
<div
|
|
265
|
-
<label className="
|
|
327
|
+
<div>
|
|
328
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5 mt-3">Installation:</label>
|
|
266
329
|
<select
|
|
267
|
-
className="
|
|
330
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-xs"
|
|
268
331
|
value={selectedInstallation}
|
|
269
332
|
onChange={e => handleLoadRepos(e.target.value)}
|
|
270
333
|
>
|
|
@@ -279,10 +342,10 @@ export function GitRepoModal() {
|
|
|
279
342
|
)}
|
|
280
343
|
|
|
281
344
|
{repos.length > 0 && (
|
|
282
|
-
<div
|
|
283
|
-
<label className="
|
|
345
|
+
<div>
|
|
346
|
+
<label className="block text-content-secondary text-[11px] uppercase tracking-wider mb-1.5 mt-3">Repository:</label>
|
|
284
347
|
<select
|
|
285
|
-
className="
|
|
348
|
+
className="w-full py-2 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-xs"
|
|
286
349
|
value={selectedRepo}
|
|
287
350
|
onChange={e => setSelectedRepo(e.target.value)}
|
|
288
351
|
>
|
|
@@ -294,7 +357,7 @@ export function GitRepoModal() {
|
|
|
294
357
|
))}
|
|
295
358
|
</select>
|
|
296
359
|
<button
|
|
297
|
-
className=
|
|
360
|
+
className={btnPrimary}
|
|
298
361
|
onClick={handleConnectGitHub}
|
|
299
362
|
disabled={loading || !selectedRepo}
|
|
300
363
|
>
|
|
@@ -307,11 +370,79 @@ export function GitRepoModal() {
|
|
|
307
370
|
</div>
|
|
308
371
|
)}
|
|
309
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
|
+
|
|
310
441
|
{tab === 'url' && (
|
|
311
|
-
<div
|
|
312
|
-
<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>
|
|
313
444
|
<input
|
|
314
|
-
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"
|
|
315
446
|
type="text"
|
|
316
447
|
placeholder="https://github.com/org/repo.git"
|
|
317
448
|
value={cloneUrl}
|
|
@@ -319,7 +450,7 @@ export function GitRepoModal() {
|
|
|
319
450
|
onKeyDown={e => { if (e.key === 'Enter') handleConnectUrl(); }}
|
|
320
451
|
/>
|
|
321
452
|
<button
|
|
322
|
-
className=
|
|
453
|
+
className={btnPrimary}
|
|
323
454
|
onClick={handleConnectUrl}
|
|
324
455
|
disabled={loading || !cloneUrl.trim()}
|
|
325
456
|
>
|
|
@@ -329,13 +460,13 @@ export function GitRepoModal() {
|
|
|
329
460
|
)}
|
|
330
461
|
|
|
331
462
|
{tab === 'init' && (
|
|
332
|
-
<div
|
|
333
|
-
<p className="
|
|
463
|
+
<div>
|
|
464
|
+
<p className="text-content-secondary text-xs leading-relaxed mb-3">
|
|
334
465
|
Initialize a new empty local git repository for this project.
|
|
335
466
|
You can connect it to a remote later.
|
|
336
467
|
</p>
|
|
337
468
|
<button
|
|
338
|
-
className=
|
|
469
|
+
className={btnPrimary}
|
|
339
470
|
onClick={handleInit}
|
|
340
471
|
disabled={loading}
|
|
341
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
|
);
|
package/templates/assistkick-product-system/packages/frontend/src/components/InviteUserDialog.tsx
CHANGED
|
@@ -50,22 +50,22 @@ export function InviteUserDialog({ isOpen, onClose }: InviteUserDialogProps) {
|
|
|
50
50
|
if (!isOpen) return null;
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
|
-
<div className="
|
|
54
|
-
<div className="
|
|
55
|
-
<div className="
|
|
56
|
-
<h2>Invite User</h2>
|
|
57
|
-
<button className="
|
|
53
|
+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-[1000]" onClick={handleClose}>
|
|
54
|
+
<div className="bg-surface border border-edge rounded-xl p-6 w-[400px] max-w-[90vw] shadow-[0_8px_32px_rgba(0,0,0,0.3)]" onClick={e => e.stopPropagation()}>
|
|
55
|
+
<div className="flex justify-between items-center mb-4">
|
|
56
|
+
<h2 className="m-0 text-lg text-content">Invite User</h2>
|
|
57
|
+
<button className="bg-none border-none text-[22px] text-content-secondary cursor-pointer px-1 leading-none hover:text-content" onClick={handleClose} type="button">×</button>
|
|
58
58
|
</div>
|
|
59
59
|
|
|
60
60
|
<form onSubmit={handleSubmit} noValidate>
|
|
61
|
-
{error && <div className="
|
|
62
|
-
{success && <div className="
|
|
61
|
+
{error && <div className="font-mono text-xs text-error bg-[rgba(255,107,107,0.08)] border border-[rgba(255,107,107,0.2)] rounded px-3 py-2 mb-3">{error}</div>}
|
|
62
|
+
{success && <div className="bg-surface-alt text-[#4caf50] px-3.5 py-2.5 rounded-md mb-3 text-sm">{success}</div>}
|
|
63
63
|
|
|
64
|
-
<div className="
|
|
65
|
-
<label className="
|
|
64
|
+
<div className="flex flex-col gap-1">
|
|
65
|
+
<label className="font-mono text-[11px] font-semibold text-content-secondary uppercase tracking-wider" htmlFor="invite-email">Email address</label>
|
|
66
66
|
<input
|
|
67
67
|
id="invite-email"
|
|
68
|
-
className={`
|
|
68
|
+
className={`w-full h-9 px-2.5 bg-surface-raised border rounded text-content font-mono text-[13px] outline-none transition-[border-color] duration-150 focus:border-accent placeholder:text-content-muted ${error ? 'border-error focus:border-error' : 'border-edge'}`}
|
|
69
69
|
type="email"
|
|
70
70
|
value={email}
|
|
71
71
|
onChange={e => setEmail(e.target.value)}
|
|
@@ -75,7 +75,11 @@ export function InviteUserDialog({ isOpen, onClose }: InviteUserDialogProps) {
|
|
|
75
75
|
/>
|
|
76
76
|
</div>
|
|
77
77
|
|
|
78
|
-
<button
|
|
78
|
+
<button
|
|
79
|
+
className="w-full h-9 mt-4 bg-transparent border border-accent rounded text-accent font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:enabled:bg-accent hover:enabled:text-white disabled:opacity-60 disabled:cursor-not-allowed"
|
|
80
|
+
type="submit"
|
|
81
|
+
disabled={submitting}
|
|
82
|
+
>
|
|
79
83
|
{submitting ? 'Sending...' : 'Send Invitation'}
|
|
80
84
|
</button>
|
|
81
85
|
</form>
|