@shepai/cli 1.177.0 → 1.178.1
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/apis/json-schema/Language.yaml +1 -0
- package/dist/packages/core/src/application/ports/output/services/agent-auth-detector.interface.d.ts +23 -0
- package/dist/packages/core/src/application/ports/output/services/agent-auth-detector.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/agent-auth-detector.interface.js +13 -0
- package/dist/packages/core/src/application/ports/output/services/file-system-service.interface.d.ts +18 -0
- package/dist/packages/core/src/application/ports/output/services/file-system-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/file-system-service.interface.js +7 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +3 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/project-scaffold-service.interface.d.ts +33 -0
- package/dist/packages/core/src/application/ports/output/services/project-scaffold-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/project-scaffold-service.interface.js +9 -0
- package/dist/packages/core/src/application/use-cases/agents/check-agent-auth.use-case.d.ts +42 -0
- package/dist/packages/core/src/application/use-cases/agents/check-agent-auth.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/agents/check-agent-auth.use-case.js +134 -0
- package/dist/packages/core/src/application/use-cases/projects/create-project.use-case.d.ts +43 -0
- package/dist/packages/core/src/application/use-cases/projects/create-project.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/projects/create-project.use-case.js +84 -0
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts +13 -2
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.js +14 -3
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +16 -0
- package/dist/packages/core/src/infrastructure/services/agent-auth-detector/platform-agent-auth-detector.service.d.ts +35 -0
- package/dist/packages/core/src/infrastructure/services/agent-auth-detector/platform-agent-auth-detector.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agent-auth-detector/platform-agent-auth-detector.service.js +165 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +31 -5
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts +14 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +63 -0
- package/dist/packages/core/src/infrastructure/services/file-system.service.d.ts +10 -0
- package/dist/packages/core/src/infrastructure/services/file-system.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/file-system.service.js +22 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +57 -10
- package/dist/packages/core/src/infrastructure/services/project-scaffold/fs-project-scaffold.service.d.ts +22 -0
- package/dist/packages/core/src/infrastructure/services/project-scaffold/fs-project-scaffold.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/project-scaffold/fs-project-scaffold.service.js +74 -0
- package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts +10 -2
- package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/check-agent-auth.js +7 -199
- package/dist/src/presentation/web/app/actions/create-project-folder.d.ts +16 -0
- package/dist/src/presentation/web/app/actions/create-project-folder.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/create-project-folder.js +18 -0
- package/dist/src/presentation/web/app/actions/delete-repository.d.ts +4 -1
- package/dist/src/presentation/web/app/actions/delete-repository.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/delete-repository.js +2 -2
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +2 -2
- package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts +3 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.js +13 -4
- package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +5 -3
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +134 -124
- package/dist/src/presentation/web/components/features/control-center/new-project-dialog.d.ts +8 -0
- package/dist/src/presentation/web/components/features/control-center/new-project-dialog.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/control-center/new-project-dialog.js +43 -0
- package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.d.ts +27 -0
- package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.js +84 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +3 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +4 -2
- package/dist/src/presentation/web/components/features/control-center/use-fab-actions.d.ts +21 -0
- package/dist/src/presentation/web/components/features/control-center/use-fab-actions.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-fab-actions.js +70 -0
- package/dist/src/presentation/web/components/features/control-center/use-workspace-fit-view.d.ts +27 -0
- package/dist/src/presentation/web/components/features/control-center/use-workspace-fit-view.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-workspace-fit-view.js +48 -0
- package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.js +8 -1
- package/dist/src/presentation/web/components/features/features-canvas/canvas-toolbar.d.ts +3 -1
- package/dist/src/presentation/web/components/features/features-canvas/canvas-toolbar.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/canvas-toolbar.js +3 -3
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/manage-workspace-dialog.d.ts +15 -0
- package/dist/src/presentation/web/components/features/features-canvas/manage-workspace-dialog.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/features-canvas/manage-workspace-dialog.js +74 -0
- package/dist/src/presentation/web/components/features/features-canvas/workspace-name-dialog.d.ts +11 -0
- package/dist/src/presentation/web/components/features/features-canvas/workspace-name-dialog.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/features-canvas/workspace-name-dialog.js +22 -0
- package/dist/src/presentation/web/components/features/features-canvas/workspace-selector.d.ts +13 -0
- package/dist/src/presentation/web/components/features/features-canvas/workspace-selector.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/features-canvas/workspace-selector.js +21 -0
- package/dist/src/presentation/web/hooks/use-workspaces.d.ts +37 -0
- package/dist/src/presentation/web/hooks/use-workspaces.d.ts.map +1 -0
- package/dist/src/presentation/web/hooks/use-workspaces.js +219 -0
- package/dist/src/presentation/web/lib/derive-graph.d.ts +3 -1
- package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
- package/dist/translations/ar/web.json +4 -1
- package/dist/translations/de/web.json +4 -1
- package/dist/translations/en/web.json +4 -1
- package/dist/translations/es/web.json +4 -1
- package/dist/translations/fr/web.json +4 -1
- package/dist/translations/he/web.json +4 -1
- package/dist/translations/pt/web.json +4 -1
- package/dist/translations/ru/web.json +4 -1
- package/dist/translations/uk/web.json +3 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +2 -2
- package/web/.next/required-server-files.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +73 -58
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +75 -60
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +91 -76
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +91 -76
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/chat/page.js +1 -2
- package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +75 -60
- package/web/.next/server/app/(dashboard)/create/page.js +1 -2
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +91 -76
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +91 -76
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/page.js +1 -2
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -2
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
- package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/features/page.js.nft.json +1 -1
- package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +13 -13
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__23b5ca2c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__46b10380._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__46b10380._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7528eb6f._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b512877._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b512877._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__990dba2d._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__990dba2d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cc9c7bbb._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cc9c7bbb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_35b56ded._.js +3 -0
- package/web/.next/server/chunks/ssr/_35b56ded._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_4cbb7f95._.js → _496c9117._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4cbb7f95._.js.map → _496c9117._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6abfa39e._.js +1 -1
- package/web/.next/server/chunks/ssr/_79a4a04a._.js +3 -0
- package/web/.next/server/chunks/ssr/_79a4a04a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_3fc2374c._.js → _a1cc5e68._.js} +2 -2
- package/web/.next/server/chunks/ssr/_a1cc5e68._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_19a779c6._.js → _a2e317b3._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_19a779c6._.js.map → _a2e317b3._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_f8c55130._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_06109d28._.js +5 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_06109d28._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_0bca70f8._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_0bca70f8._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_367cdbe0._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_367cdbe0._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_57fed7fd._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_57fed7fd._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_7f567f6d._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_7f567f6d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_972f58d5._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_972f58d5._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_a71b18a2._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_a71b18a2._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_features_feature-tree-page-client_tsx_34c5cbbf._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_app_features_feature-tree-page-client_tsx_34c5cbbf._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_bebe675e._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_bebe675e._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_c93e8bc6._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_c93e8bc6._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e729f44a._.js +5 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e729f44a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js +1 -1
- package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +590 -484
- package/web/.next/static/chunks/{b5d355eb59916926.js → 0b6c8ca8403db859.js} +2 -2
- package/web/.next/static/chunks/{eaa1b979d63d322b.js → 0ff97e3b2c05f514.js} +1 -1
- package/web/.next/static/chunks/124b79a5d2a760fb.css +1 -0
- package/web/.next/static/chunks/{829d2f8ef2715f2f.js → 27b1e99ab97bdf52.js} +3 -3
- package/web/.next/static/chunks/28ad440cbb92bebe.js +1 -0
- package/web/.next/static/chunks/{4c20d4cd4786a0c8.js → 2ce798babf8adbc5.js} +1 -1
- package/web/.next/static/chunks/{ef897f150084ef85.js → 374e00e5b4ab142e.js} +1 -1
- package/web/.next/static/chunks/4052a4971fbbac9c.js +1 -0
- package/web/.next/static/chunks/{0a706f8508eae0a8.js → 44dc686d971c7513.js} +3 -3
- package/web/.next/static/chunks/{0d0e2661bd167e0f.js → 64a765a6eec07603.js} +1 -1
- package/web/.next/static/chunks/{bb479c31b5b53bac.js → 74c37f189bc83156.js} +2 -2
- package/web/.next/static/chunks/8057357cf1f9b4ef.js +1 -0
- package/web/.next/static/chunks/{b5a916fec4cdc897.js → 8ecdaada8068211c.js} +1 -1
- package/web/.next/static/chunks/b2c52514837b4fc4.js +1 -0
- package/web/.next/static/chunks/{efd57b6ffc7cbd54.js → b567f6c06cc7013a.js} +1 -1
- package/web/.next/static/chunks/{c0e4cd44851a9293.js → bbc95353509ede89.js} +1 -1
- package/web/.next/static/chunks/{77d6506c7d1f711f.js → f2ec6318c5ff73b8.js} +1 -1
- package/web/.next/static/chunks/{18f429029d702545.js → f7741bf45b42ac62.js} +1 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_073183f4._.js +0 -3
- package/web/.next/server/chunks/ssr/_073183f4._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_3fc2374c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_57b1af27._.js +0 -3
- package/web/.next/server/chunks/ssr/_57b1af27._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js.map +0 -1
- package/web/.next/static/chunks/3fc5b2287f192799.js +0 -1
- package/web/.next/static/chunks/a20f2d6f76f469b7.css +0 -1
- package/web/.next/static/chunks/ddd34e939acc204f.js +0 -1
- package/web/.next/static/chunks/f9d948464ed409cb.js +0 -1
- package/web/.next/static/chunks/fc0232384ec2b48d.js +0 -1
- /package/web/.next/static/{UZ2czjiAnEl1RF-HTzHyA → d9JsHxuahs7UrJKwH-FGH}/_buildManifest.js +0 -0
- /package/web/.next/static/{UZ2czjiAnEl1RF-HTzHyA → d9JsHxuahs7UrJKwH-FGH}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{UZ2czjiAnEl1RF-HTzHyA → d9JsHxuahs7UrJKwH-FGH}/_ssgManifest.js +0 -0
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { useRouter, usePathname } from 'next/navigation';
|
|
5
|
-
import {
|
|
5
|
+
import { FolderPlus } from 'lucide-react';
|
|
6
6
|
import { useReactFlow } from '@xyflow/react';
|
|
7
7
|
import { FeaturesCanvas } from '../../features/features-canvas/index.js';
|
|
8
8
|
import { CanvasToolbar } from '../../features/features-canvas/canvas-toolbar.js';
|
|
9
|
+
import { WorkspaceSelector } from '../../features/features-canvas/workspace-selector.js';
|
|
10
|
+
import { ManageWorkspaceDialog } from '../../features/features-canvas/manage-workspace-dialog.js';
|
|
11
|
+
import { WorkspaceNameDialog } from '../../features/features-canvas/workspace-name-dialog.js';
|
|
12
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
|
|
13
|
+
import { useWorkspaces, DEFAULT_WORKSPACE_ID } from '../../../hooks/use-workspaces.js';
|
|
14
|
+
import { Layers, Plus } from 'lucide-react';
|
|
15
|
+
import { Button } from '../../ui/button.js';
|
|
9
16
|
import { FloatingActionButton, } from '../../common/floating-action-button/index.js';
|
|
10
17
|
import { useSidebarFeaturesContext, mapNodeStateToSidebarStatus, } from '../../../hooks/sidebar-features-context.js';
|
|
11
18
|
import { useTranslation } from 'react-i18next';
|
|
@@ -18,7 +25,11 @@ import { useViewportPersistence } from '../../../hooks/use-viewport-persistence.
|
|
|
18
25
|
import { useSidebar } from '../../ui/sidebar.js';
|
|
19
26
|
import { useFabLayout } from '../../../hooks/fab-layout-context.js';
|
|
20
27
|
import { ControlCenterEmptyState } from './control-center-empty-state.js';
|
|
28
|
+
import { NewProjectDialog } from './new-project-dialog.js';
|
|
21
29
|
import { useControlCenterState } from './use-control-center-state.js';
|
|
30
|
+
import { useCanvasEventListeners } from './use-canvas-event-listeners.js';
|
|
31
|
+
import { useWorkspaceFitView } from './use-workspace-fit-view.js';
|
|
32
|
+
import { useFabActions } from './use-fab-actions.js';
|
|
22
33
|
const AUTO_FOCUS_OPTIONS = {
|
|
23
34
|
maxZoom: 1.0,
|
|
24
35
|
padding: 0.5,
|
|
@@ -26,7 +37,6 @@ const AUTO_FOCUS_OPTIONS = {
|
|
|
26
37
|
};
|
|
27
38
|
const AUTO_FOCUS_DRAWER_DELAY_MS = 600;
|
|
28
39
|
export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
29
|
-
const { t } = useTranslation('web');
|
|
30
40
|
const router = useRouter();
|
|
31
41
|
const pathname = usePathname();
|
|
32
42
|
const selectedFeatureId = useSelectedFeatureId();
|
|
@@ -37,6 +47,21 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
37
47
|
const drawerTimerRef = useRef(null);
|
|
38
48
|
const { defaultViewport, onMoveEnd: handleViewportChange, resetViewport, } = useViewportPersistence();
|
|
39
49
|
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleArchiveFeature, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleUnarchiveFeature, handleDeleteRepository, createFeatureNode, showArchived, setShowArchived, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
|
|
50
|
+
// ── Workspaces (client-only prototype) ────────────────────────────────
|
|
51
|
+
const { workspaces, activeWorkspace, isDefaultActive, setActiveWorkspace, createWorkspace, renameWorkspace, deleteWorkspace, setWorkspaceMembers, addToActiveWorkspace, } = useWorkspaces();
|
|
52
|
+
// Tracks the set of node ids we've already seen, so we can detect new
|
|
53
|
+
// repo/feature nodes appearing on the canvas and auto-include them in the
|
|
54
|
+
// active workspace (when it isn't the default).
|
|
55
|
+
const knownNodeIdsRef = useRef(new Set());
|
|
56
|
+
const [manageWorkspaceOpen, setManageWorkspaceOpen] = useState(false);
|
|
57
|
+
const [createWorkspaceOpen, setCreateWorkspaceOpen] = useState(false);
|
|
58
|
+
const [renameWorkspaceOpen, setRenameWorkspaceOpen] = useState(false);
|
|
59
|
+
const [deleteWorkspaceOpen, setDeleteWorkspaceOpen] = useState(false);
|
|
60
|
+
// Target of the delete confirmation dialog. Allows deleting any workspace
|
|
61
|
+
// (not just the active one) directly from the workspace dropdown.
|
|
62
|
+
const [pendingDeleteWorkspaceId, setPendingDeleteWorkspaceId] = useState(null);
|
|
63
|
+
// Inline "New Project" dialog launched from the empty-workspace state.
|
|
64
|
+
const [workspaceNewProjectOpen, setWorkspaceNewProjectOpen] = useState(false);
|
|
40
65
|
// Publish sidebar features + repo state to context
|
|
41
66
|
const { setFeatures: setSidebarFeatures, setHasRepositories: setSidebarHasRepos } = useSidebarFeaturesContext();
|
|
42
67
|
const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
|
|
@@ -165,80 +190,26 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
165
190
|
focusOnNode(tempNodeId);
|
|
166
191
|
}
|
|
167
192
|
}, [handleAddRepository, focusAndOpenDrawer, focusOnNode]);
|
|
168
|
-
//
|
|
193
|
+
// All five window-level CustomEvent listeners (add-repository, feature-
|
|
194
|
+
// created, delete/archive/unarchive requests) live in this hook so the
|
|
195
|
+
// parent component stays focused on graph state + rendering.
|
|
196
|
+
useCanvasEventListeners({
|
|
197
|
+
addRepoAndFocus,
|
|
198
|
+
createFeatureNode,
|
|
199
|
+
nodes,
|
|
200
|
+
handleDeleteFeature,
|
|
201
|
+
handleArchiveFeature,
|
|
202
|
+
handleUnarchiveFeature,
|
|
203
|
+
});
|
|
204
|
+
// Cleanup the drawer timer on unmount. Used to live inside the inlined
|
|
205
|
+
// shep:add-repository listener; now standalone since the listener moved.
|
|
169
206
|
useEffect(() => {
|
|
170
|
-
const handler = (e) => {
|
|
171
|
-
const path = e.detail.path;
|
|
172
|
-
addRepoAndFocus(path);
|
|
173
|
-
};
|
|
174
|
-
window.addEventListener('shep:add-repository', handler);
|
|
175
207
|
return () => {
|
|
176
|
-
window.removeEventListener('shep:add-repository', handler);
|
|
177
208
|
if (drawerTimerRef.current != null) {
|
|
178
209
|
clearTimeout(drawerTimerRef.current);
|
|
179
210
|
}
|
|
180
211
|
};
|
|
181
|
-
}, [
|
|
182
|
-
// Listen for create events from the create drawer (with real feature ID from server)
|
|
183
|
-
useEffect(() => {
|
|
184
|
-
const handler = (e) => {
|
|
185
|
-
const detail = e.detail;
|
|
186
|
-
// When a parentId is provided, connect to the parent feature node
|
|
187
|
-
// via a dependency edge instead of the repo node.
|
|
188
|
-
if (detail.parentId) {
|
|
189
|
-
const parentNodeId = `feat-${detail.parentId}`;
|
|
190
|
-
createFeatureNode(parentNodeId, {
|
|
191
|
-
state: 'creating',
|
|
192
|
-
featureId: detail.featureId,
|
|
193
|
-
name: detail.name,
|
|
194
|
-
description: detail.description,
|
|
195
|
-
repositoryPath: detail.repositoryPath,
|
|
196
|
-
}, 'dependencyEdge');
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
// Find the repo node to connect to
|
|
200
|
-
const repoNode = nodes.find((n) => n.type === 'repositoryNode' &&
|
|
201
|
-
n.data.repositoryPath === detail.repositoryPath);
|
|
202
|
-
createFeatureNode(repoNode?.id ?? null, {
|
|
203
|
-
state: 'running',
|
|
204
|
-
featureId: detail.featureId,
|
|
205
|
-
name: detail.name,
|
|
206
|
-
description: detail.description,
|
|
207
|
-
repositoryPath: detail.repositoryPath,
|
|
208
|
-
});
|
|
209
|
-
};
|
|
210
|
-
window.addEventListener('shep:feature-created', handler);
|
|
211
|
-
return () => window.removeEventListener('shep:feature-created', handler);
|
|
212
|
-
}, [nodes, createFeatureNode]);
|
|
213
|
-
// Listen for delete requests from the feature drawer (fires when the user
|
|
214
|
-
// confirms delete inside the drawer). Delegates to handleDeleteFeature so
|
|
215
|
-
// the canvas gets optimistic state, mutation guard, and node removal.
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
const handler = (e) => {
|
|
218
|
-
const { featureId, cleanup, cascadeDelete, closePr } = e.detail;
|
|
219
|
-
handleDeleteFeature(featureId, cleanup, cascadeDelete, closePr);
|
|
220
|
-
};
|
|
221
|
-
window.addEventListener('shep:feature-delete-requested', handler);
|
|
222
|
-
return () => window.removeEventListener('shep:feature-delete-requested', handler);
|
|
223
|
-
}, [handleDeleteFeature]);
|
|
224
|
-
// Listen for archive requests from the feature drawer.
|
|
225
|
-
useEffect(() => {
|
|
226
|
-
const handler = (e) => {
|
|
227
|
-
const { featureId } = e.detail;
|
|
228
|
-
handleArchiveFeature(featureId);
|
|
229
|
-
};
|
|
230
|
-
window.addEventListener('shep:feature-archive-requested', handler);
|
|
231
|
-
return () => window.removeEventListener('shep:feature-archive-requested', handler);
|
|
232
|
-
}, [handleArchiveFeature]);
|
|
233
|
-
// Listen for unarchive requests from the feature drawer.
|
|
234
|
-
useEffect(() => {
|
|
235
|
-
const handler = (e) => {
|
|
236
|
-
const { featureId } = e.detail;
|
|
237
|
-
handleUnarchiveFeature(featureId);
|
|
238
|
-
};
|
|
239
|
-
window.addEventListener('shep:feature-unarchive-requested', handler);
|
|
240
|
-
return () => window.removeEventListener('shep:feature-unarchive-requested', handler);
|
|
241
|
-
}, [handleUnarchiveFeature]);
|
|
212
|
+
}, []);
|
|
242
213
|
// Wire callbacks into derived node data (via ref — no re-render).
|
|
243
214
|
useEffect(() => {
|
|
244
215
|
setCallbacks({
|
|
@@ -302,72 +273,111 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
302
273
|
clearTimeout(latchTimerRef.current);
|
|
303
274
|
};
|
|
304
275
|
}, [hasRepositories, showCanvas, resetViewport]);
|
|
276
|
+
// Auto-include any newly-appearing repo/feature nodes in the active
|
|
277
|
+
// workspace (skipped when default is active — that workspace shows
|
|
278
|
+
// everything anyway). We diff the current node id list against the set
|
|
279
|
+
// we've already seen so we only add the deltas.
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
const seen = knownNodeIdsRef.current;
|
|
282
|
+
const newRepoIds = [];
|
|
283
|
+
const newFeatureIds = [];
|
|
284
|
+
for (const n of nodes) {
|
|
285
|
+
if (seen.has(n.id))
|
|
286
|
+
continue;
|
|
287
|
+
seen.add(n.id);
|
|
288
|
+
if (n.type === 'repositoryNode')
|
|
289
|
+
newRepoIds.push(n.id);
|
|
290
|
+
else if (n.type === 'featureNode')
|
|
291
|
+
newFeatureIds.push(n.id);
|
|
292
|
+
}
|
|
293
|
+
if (isDefaultActive)
|
|
294
|
+
return;
|
|
295
|
+
if (newRepoIds.length === 0 && newFeatureIds.length === 0)
|
|
296
|
+
return;
|
|
297
|
+
addToActiveWorkspace({ repoIds: newRepoIds, featureIds: newFeatureIds });
|
|
298
|
+
}, [nodes, isDefaultActive, addToActiveWorkspace]);
|
|
299
|
+
// Filter nodes by the active workspace (default workspace = no filter).
|
|
300
|
+
// We always filter from the full `nodes` list so `displayNodes` already
|
|
301
|
+
// reflects workspace membership before pulse-add decoration runs.
|
|
302
|
+
const workspaceFilteredNodes = useMemo(() => {
|
|
303
|
+
if (isDefaultActive)
|
|
304
|
+
return nodes;
|
|
305
|
+
const allowedRepos = new Set(activeWorkspace.repoIds);
|
|
306
|
+
const allowedFeatures = new Set(activeWorkspace.featureIds);
|
|
307
|
+
return nodes.filter((n) => {
|
|
308
|
+
if (n.type === 'repositoryNode')
|
|
309
|
+
return allowedRepos.has(n.id);
|
|
310
|
+
if (n.type === 'featureNode')
|
|
311
|
+
return allowedFeatures.has(n.id);
|
|
312
|
+
return true;
|
|
313
|
+
});
|
|
314
|
+
}, [nodes, isDefaultActive, activeWorkspace]);
|
|
315
|
+
// Drop edges whose endpoints were filtered out.
|
|
316
|
+
const workspaceFilteredEdges = useMemo(() => {
|
|
317
|
+
if (isDefaultActive)
|
|
318
|
+
return edges;
|
|
319
|
+
const visibleIds = new Set(workspaceFilteredNodes.map((n) => n.id));
|
|
320
|
+
return edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target));
|
|
321
|
+
}, [edges, isDefaultActive, workspaceFilteredNodes]);
|
|
305
322
|
// Pulse the "+" button when there's a single repo with no features and the
|
|
306
323
|
// create-feature drawer is not open — draws attention to the next action.
|
|
307
324
|
const isCreateDrawerOpen = pathname.startsWith('/create');
|
|
308
325
|
const displayNodes = useMemo(() => {
|
|
309
|
-
const
|
|
310
|
-
const
|
|
326
|
+
const source = workspaceFilteredNodes;
|
|
327
|
+
const repoNodes = source.filter((n) => n.type === 'repositoryNode');
|
|
328
|
+
const hasFeatures = source.some((n) => n.type === 'featureNode');
|
|
311
329
|
const shouldPulse = repoNodes.length === 1 && !hasFeatures && !isCreateDrawerOpen;
|
|
312
330
|
if (!shouldPulse)
|
|
313
|
-
return
|
|
314
|
-
return
|
|
315
|
-
}, [
|
|
331
|
+
return source;
|
|
332
|
+
return source.map((n) => n.type === 'repositoryNode' ? { ...n, data: { ...n.data, pulseAdd: true } } : n);
|
|
333
|
+
}, [workspaceFilteredNodes, isCreateDrawerOpen]);
|
|
316
334
|
const handlePickFolder = useCallback(() => {
|
|
317
335
|
window.dispatchEvent(new CustomEvent('shep:pick-folder'));
|
|
318
336
|
}, []);
|
|
337
|
+
// Re-fit the viewport when the active workspace's visible node set changes.
|
|
338
|
+
// See use-workspace-fit-view.ts for the scoping rules.
|
|
339
|
+
useWorkspaceFitView({
|
|
340
|
+
activeWorkspace,
|
|
341
|
+
isDefaultActive,
|
|
342
|
+
workspaceFilteredNodes,
|
|
343
|
+
fitView,
|
|
344
|
+
});
|
|
345
|
+
// When the active (non-default) workspace has no members but real repos
|
|
346
|
+
// exist on the canvas, show a workspace-aware empty state instead of the
|
|
347
|
+
// welcome wizard. The wizard would imply "no repos at all", which is wrong
|
|
348
|
+
// here — and crucially, leaves the workspace selector visible via the
|
|
349
|
+
// toolbar so users can switch back to the default workspace.
|
|
350
|
+
const workspaceFilteredEmpty = hasRepositories && !isDefaultActive && workspaceFilteredNodes.length === 0;
|
|
351
|
+
const emptyStateNode = workspaceFilteredEmpty ? (_jsxs("div", { className: "pointer-events-auto flex h-full w-full flex-col items-center justify-center px-8", children: [_jsx("div", { className: "bg-primary/10 text-primary mb-5 flex h-12 w-12 items-center justify-center rounded-2xl", children: _jsx(Layers, { className: "h-6 w-6" }) }), _jsx("h2", { className: "text-foreground/90 text-center text-2xl font-light tracking-tight", children: "This workspace is empty" }), _jsx("p", { className: "text-muted-foreground mt-2 max-w-sm text-center text-sm leading-relaxed", children: "Add repositories or features from the canvas, or switch back to the default workspace to see everything." }), _jsxs("div", { className: "mt-6 flex items-center gap-2", children: [_jsxs(Button, { size: "sm", onClick: () => setWorkspaceNewProjectOpen(true), className: "bg-blue-500 text-white hover:bg-blue-600", children: [_jsx(FolderPlus, { className: "me-1.5 h-3.5 w-3.5" }), "New project"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setManageWorkspaceOpen(true), children: [_jsx(Plus, { className: "me-1.5 h-3.5 w-3.5" }), "Manage items"] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setActiveWorkspace(DEFAULT_WORKSPACE_ID), children: "Switch to Default" })] })] })) : (_jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }));
|
|
319
352
|
const featureFlags = useFeatureFlags();
|
|
320
|
-
// (+) FAB actions — only visible on control center
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
id: 'new-feature',
|
|
325
|
-
label: t('fab.newFeature'),
|
|
326
|
-
icon: _jsx(Sparkles, { className: "h-4 w-4" }),
|
|
327
|
-
onClick: () => {
|
|
328
|
-
clickSound.play();
|
|
329
|
-
guardedNavigate(() => router.push('/create'));
|
|
330
|
-
},
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
id: 'add-local-repo',
|
|
334
|
-
label: t('fab.localFolder'),
|
|
335
|
-
icon: _jsx(FolderPlus, { className: "h-4 w-4" }),
|
|
336
|
-
onClick: handlePickFolder,
|
|
337
|
-
},
|
|
338
|
-
];
|
|
339
|
-
if (featureFlags.adoptBranch) {
|
|
340
|
-
actions.push({
|
|
341
|
-
id: 'adopt-branch',
|
|
342
|
-
label: t('fab.adoptBranch'),
|
|
343
|
-
icon: _jsx(GitBranch, { className: "h-4 w-4" }),
|
|
344
|
-
onClick: () => {
|
|
345
|
-
guardedNavigate(() => router.push('/adopt'));
|
|
346
|
-
},
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
if (featureFlags.githubImport) {
|
|
350
|
-
actions.push({
|
|
351
|
-
id: 'add-github-repo',
|
|
352
|
-
label: t('fab.fromGithub'),
|
|
353
|
-
icon: _jsx(Github, { className: "h-4 w-4" }),
|
|
354
|
-
onClick: () => {
|
|
355
|
-
window.dispatchEvent(new CustomEvent('shep:open-github-import'));
|
|
356
|
-
},
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
return actions;
|
|
360
|
-
}, [
|
|
361
|
-
t,
|
|
353
|
+
// (+) FAB actions — only visible on control center. Action list lives in
|
|
354
|
+
// its own hook so this component stays focused on graph state + rendering.
|
|
355
|
+
const fabActions = useFabActions({
|
|
356
|
+
router,
|
|
362
357
|
clickSound,
|
|
363
358
|
guardedNavigate,
|
|
364
|
-
router,
|
|
365
359
|
handlePickFolder,
|
|
366
|
-
|
|
367
|
-
featureFlags
|
|
368
|
-
|
|
369
|
-
const canvasToolbar = (_jsx(CanvasToolbar, { showArchived: showArchived, onToggleArchived: () => setShowArchived(!showArchived), onResetViewport: resetViewport
|
|
370
|
-
|
|
360
|
+
onNewProject: () => setWorkspaceNewProjectOpen(true),
|
|
361
|
+
featureFlags,
|
|
362
|
+
});
|
|
363
|
+
const canvasToolbar = (_jsx(CanvasToolbar, { showArchived: showArchived, onToggleArchived: () => setShowArchived(!showArchived), onResetViewport: resetViewport, startSlot: _jsx(WorkspaceSelector, { workspaces: workspaces, activeWorkspace: activeWorkspace, onSelect: setActiveWorkspace, onRequestCreate: () => setCreateWorkspaceOpen(true), onRequestRename: () => setRenameWorkspaceOpen(true), onRequestDelete: (id) => {
|
|
364
|
+
setPendingDeleteWorkspaceId(id);
|
|
365
|
+
setDeleteWorkspaceOpen(true);
|
|
366
|
+
}, onManage: () => setManageWorkspaceOpen(true) }) }));
|
|
367
|
+
return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? workspaceFilteredEdges : [], selectedFeatureId: selectedFeatureId, selectedRepository: selectedRepository, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, toolbar: canvasToolbar, emptyState: emptyStateNode }), showCanvas ? _jsx(CreateFab, { actions: fabActions }) : null, _jsx(NewProjectDialog, { open: workspaceNewProjectOpen, onOpenChange: setWorkspaceNewProjectOpen, onCreated: (path) => addRepoAndFocus(path) }), _jsx(ManageWorkspaceDialog, { open: manageWorkspaceOpen, onOpenChange: setManageWorkspaceOpen, workspace: activeWorkspace, allNodes: nodes, onSave: (members) => setWorkspaceMembers(activeWorkspace.id, members) }), _jsx(WorkspaceNameDialog, { open: createWorkspaceOpen, onOpenChange: setCreateWorkspaceOpen, title: "New workspace", description: "Create a workspace to filter the canvas to a specific set of repositories and features.", confirmLabel: "Create", onConfirm: (name) => {
|
|
368
|
+
createWorkspace(name);
|
|
369
|
+
setManageWorkspaceOpen(true);
|
|
370
|
+
} }), _jsx(WorkspaceNameDialog, { open: renameWorkspaceOpen, onOpenChange: setRenameWorkspaceOpen, title: "Rename workspace", initialValue: activeWorkspace.name, confirmLabel: "Rename", onConfirm: (name) => renameWorkspace(activeWorkspace.id, name) }), _jsx(AlertDialog, { open: deleteWorkspaceOpen, onOpenChange: (open) => {
|
|
371
|
+
setDeleteWorkspaceOpen(open);
|
|
372
|
+
if (!open)
|
|
373
|
+
setPendingDeleteWorkspaceId(null);
|
|
374
|
+
}, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete workspace?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently remove the workspace \u201C", workspaces.find((w) => w.id === pendingDeleteWorkspaceId)?.name ??
|
|
375
|
+
activeWorkspace.name, "\u201D. The repositories and features themselves are not affected."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", onClick: () => {
|
|
376
|
+
if (pendingDeleteWorkspaceId) {
|
|
377
|
+
deleteWorkspace(pendingDeleteWorkspaceId);
|
|
378
|
+
setPendingDeleteWorkspaceId(null);
|
|
379
|
+
}
|
|
380
|
+
}, children: "Delete" })] })] }) })] }));
|
|
371
381
|
}
|
|
372
382
|
/** (+) FAB that tracks sidebar width via CSS var + transition.
|
|
373
383
|
* When fabLayout.swapPosition is true, moves to the end side (right in LTR). */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface NewProjectDialogProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onOpenChange: (open: boolean) => void;
|
|
4
|
+
/** Called with the absolute path of the newly-created project folder. */
|
|
5
|
+
onCreated: (path: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function NewProjectDialog({ open, onOpenChange, onCreated }: NewProjectDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=new-project-dialog.d.ts.map
|
package/dist/src/presentation/web/components/features/control-center/new-project-dialog.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-project-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/new-project-dialog.tsx"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,yEAAyE;IACzE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,qBAAqB,2CAsFxF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Loader2 } from 'lucide-react';
|
|
5
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
|
|
6
|
+
import { Input } from '../../ui/input.js';
|
|
7
|
+
import { Button } from '../../ui/button.js';
|
|
8
|
+
import { createProjectFolder } from '../../../app/actions/create-project-folder.js';
|
|
9
|
+
export function NewProjectDialog({ open, onOpenChange, onCreated }) {
|
|
10
|
+
const [name, setName] = useState('');
|
|
11
|
+
const [busy, setBusy] = useState(false);
|
|
12
|
+
const [error, setError] = useState(null);
|
|
13
|
+
// Reset state every time the dialog opens.
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (open) {
|
|
16
|
+
setName('');
|
|
17
|
+
setBusy(false);
|
|
18
|
+
setError(null);
|
|
19
|
+
}
|
|
20
|
+
}, [open]);
|
|
21
|
+
const handleSubmit = async (e) => {
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
const trimmed = name.trim();
|
|
24
|
+
if (!trimmed || busy)
|
|
25
|
+
return;
|
|
26
|
+
setBusy(true);
|
|
27
|
+
setError(null);
|
|
28
|
+
const result = await createProjectFolder(trimmed);
|
|
29
|
+
if (!result.ok || !result.path) {
|
|
30
|
+
setError(result.error ?? 'Failed to create project.');
|
|
31
|
+
setBusy(false);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Hand the new path off to the empty state's existing add-repo flow.
|
|
35
|
+
onCreated(result.path);
|
|
36
|
+
onOpenChange(false);
|
|
37
|
+
};
|
|
38
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsx(DialogContent, { className: "max-w-sm", children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "New project" }), _jsx(DialogDescription, { children: "Create an empty project folder inside your Shep home directory. Git will be initialised automatically when the project is added." })] }), _jsxs("div", { className: "py-4", children: [_jsx(Input, { autoFocus: true, value: name, onChange: (e) => {
|
|
39
|
+
setName(e.target.value);
|
|
40
|
+
if (error)
|
|
41
|
+
setError(null);
|
|
42
|
+
}, placeholder: "my-prototype", disabled: busy, "data-testid": "new-project-name-input" }), error ? (_jsx("p", { className: "text-destructive mt-2 text-xs", role: "alert", children: error })) : null] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), disabled: busy, children: "Cancel" }), _jsx(Button, { type: "submit", disabled: !name.trim() || busy, children: busy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Creating\u2026"] })) : ('Create project') })] })] }) }) }));
|
|
43
|
+
}
|
package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire global window events used by the control center canvas to the
|
|
3
|
+
* appropriate handlers. The canvas listens for cross-component requests
|
|
4
|
+
* dispatched as CustomEvents:
|
|
5
|
+
*
|
|
6
|
+
* - shep:add-repository → addRepoAndFocus(path)
|
|
7
|
+
* - shep:feature-created → createFeatureNode(...)
|
|
8
|
+
* - shep:feature-delete-requested → handleDeleteFeature(...)
|
|
9
|
+
* - shep:feature-archive-requested → handleArchiveFeature(...)
|
|
10
|
+
* - shep:feature-unarchive-requested → handleUnarchiveFeature(...)
|
|
11
|
+
*
|
|
12
|
+
* Extracted from control-center-inner.tsx so the parent component stays
|
|
13
|
+
* focused on graph state + rendering, not event-bus plumbing.
|
|
14
|
+
*/
|
|
15
|
+
import type { CanvasNodeType } from '../../features/features-canvas/index.js';
|
|
16
|
+
import type { FeatureNodeData } from '../../common/feature-node/index.js';
|
|
17
|
+
export type CreateFeatureNodeFn = (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData>, edgeType?: string) => string;
|
|
18
|
+
export interface CanvasEventListenerHandlers {
|
|
19
|
+
addRepoAndFocus: (path: string) => void;
|
|
20
|
+
createFeatureNode: CreateFeatureNodeFn;
|
|
21
|
+
nodes: CanvasNodeType[];
|
|
22
|
+
handleDeleteFeature: (featureId: string, cleanup?: boolean, cascadeDelete?: boolean, closePr?: boolean) => void;
|
|
23
|
+
handleArchiveFeature: (featureId: string) => void;
|
|
24
|
+
handleUnarchiveFeature: (featureId: string) => void;
|
|
25
|
+
}
|
|
26
|
+
export declare function useCanvasEventListeners(handlers: CanvasEventListenerHandlers): void;
|
|
27
|
+
//# sourceMappingURL=use-canvas-event-listeners.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-canvas-event-listeners.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-canvas-event-listeners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG,CAChC,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;AAEZ,MAAM,WAAW,2BAA2B;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,IAAI,CAyGnF"}
|
package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire global window events used by the control center canvas to the
|
|
3
|
+
* appropriate handlers. The canvas listens for cross-component requests
|
|
4
|
+
* dispatched as CustomEvents:
|
|
5
|
+
*
|
|
6
|
+
* - shep:add-repository → addRepoAndFocus(path)
|
|
7
|
+
* - shep:feature-created → createFeatureNode(...)
|
|
8
|
+
* - shep:feature-delete-requested → handleDeleteFeature(...)
|
|
9
|
+
* - shep:feature-archive-requested → handleArchiveFeature(...)
|
|
10
|
+
* - shep:feature-unarchive-requested → handleUnarchiveFeature(...)
|
|
11
|
+
*
|
|
12
|
+
* Extracted from control-center-inner.tsx so the parent component stays
|
|
13
|
+
* focused on graph state + rendering, not event-bus plumbing.
|
|
14
|
+
*/
|
|
15
|
+
import { useEffect } from 'react';
|
|
16
|
+
export function useCanvasEventListeners(handlers) {
|
|
17
|
+
const { addRepoAndFocus, createFeatureNode, nodes, handleDeleteFeature, handleArchiveFeature, handleUnarchiveFeature, } = handlers;
|
|
18
|
+
// shep:add-repository — top-bar "add folder" button
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const handler = (e) => {
|
|
21
|
+
const path = e.detail.path;
|
|
22
|
+
addRepoAndFocus(path);
|
|
23
|
+
};
|
|
24
|
+
window.addEventListener('shep:add-repository', handler);
|
|
25
|
+
return () => window.removeEventListener('shep:add-repository', handler);
|
|
26
|
+
}, [addRepoAndFocus]);
|
|
27
|
+
// shep:feature-created — fired by the create drawer with the real server feature ID
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const handler = (e) => {
|
|
30
|
+
const detail = e.detail;
|
|
31
|
+
// When parentId is provided, attach to the parent feature node via a
|
|
32
|
+
// dependency edge instead of the repo node.
|
|
33
|
+
if (detail.parentId) {
|
|
34
|
+
const parentNodeId = `feat-${detail.parentId}`;
|
|
35
|
+
createFeatureNode(parentNodeId, {
|
|
36
|
+
state: 'creating',
|
|
37
|
+
featureId: detail.featureId,
|
|
38
|
+
name: detail.name,
|
|
39
|
+
description: detail.description,
|
|
40
|
+
repositoryPath: detail.repositoryPath,
|
|
41
|
+
}, 'dependencyEdge');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const repoNode = nodes.find((n) => n.type === 'repositoryNode' &&
|
|
45
|
+
n.data.repositoryPath === detail.repositoryPath);
|
|
46
|
+
createFeatureNode(repoNode?.id ?? null, {
|
|
47
|
+
state: 'running',
|
|
48
|
+
featureId: detail.featureId,
|
|
49
|
+
name: detail.name,
|
|
50
|
+
description: detail.description,
|
|
51
|
+
repositoryPath: detail.repositoryPath,
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
window.addEventListener('shep:feature-created', handler);
|
|
55
|
+
return () => window.removeEventListener('shep:feature-created', handler);
|
|
56
|
+
}, [nodes, createFeatureNode]);
|
|
57
|
+
// shep:feature-delete-requested — fired from the feature drawer
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const handler = (e) => {
|
|
60
|
+
const { featureId, cleanup, cascadeDelete, closePr } = e.detail;
|
|
61
|
+
handleDeleteFeature(featureId, cleanup, cascadeDelete, closePr);
|
|
62
|
+
};
|
|
63
|
+
window.addEventListener('shep:feature-delete-requested', handler);
|
|
64
|
+
return () => window.removeEventListener('shep:feature-delete-requested', handler);
|
|
65
|
+
}, [handleDeleteFeature]);
|
|
66
|
+
// shep:feature-archive-requested — fired from the feature drawer
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const handler = (e) => {
|
|
69
|
+
const { featureId } = e.detail;
|
|
70
|
+
handleArchiveFeature(featureId);
|
|
71
|
+
};
|
|
72
|
+
window.addEventListener('shep:feature-archive-requested', handler);
|
|
73
|
+
return () => window.removeEventListener('shep:feature-archive-requested', handler);
|
|
74
|
+
}, [handleArchiveFeature]);
|
|
75
|
+
// shep:feature-unarchive-requested — fired from the feature drawer
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
const handler = (e) => {
|
|
78
|
+
const { featureId } = e.detail;
|
|
79
|
+
handleUnarchiveFeature(featureId);
|
|
80
|
+
};
|
|
81
|
+
window.addEventListener('shep:feature-unarchive-requested', handler);
|
|
82
|
+
return () => window.removeEventListener('shep:feature-unarchive-requested', handler);
|
|
83
|
+
}, [handleUnarchiveFeature]);
|
|
84
|
+
}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts
CHANGED
|
@@ -21,7 +21,9 @@ export interface ControlCenterState {
|
|
|
21
21
|
handleStartFeature: (featureId: string) => void;
|
|
22
22
|
handleStopFeature: (featureId: string) => void;
|
|
23
23
|
handleUnarchiveFeature: (featureId: string) => void;
|
|
24
|
-
handleDeleteRepository: (repositoryId: string
|
|
24
|
+
handleDeleteRepository: (repositoryId: string, options?: {
|
|
25
|
+
deleteFromDisk?: boolean;
|
|
26
|
+
}) => Promise<void>;
|
|
25
27
|
createFeatureNode: (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData>, edgeType?: string) => string;
|
|
26
28
|
/** Whether archived features are shown on the canvas. */
|
|
27
29
|
showArchived: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CACtB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,KACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAmlBpB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -388,7 +388,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
388
388
|
})
|
|
389
389
|
.finally(() => endMutation());
|
|
390
390
|
}, [router, deleteSound, updateFeature, removeFeature, beginMutation, endMutation]);
|
|
391
|
-
const handleDeleteRepository = useCallback(async (repositoryId) => {
|
|
391
|
+
const handleDeleteRepository = useCallback(async (repositoryId, options) => {
|
|
392
392
|
const repoNodeId = `repo-${repositoryId}`;
|
|
393
393
|
// Find children of this repo via edges
|
|
394
394
|
const childFeatureIds = new Set(edgesRef.current.filter((e) => e.source === repoNodeId).map((e) => e.target));
|
|
@@ -415,7 +415,9 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
415
415
|
removeFeature(childId);
|
|
416
416
|
}
|
|
417
417
|
try {
|
|
418
|
-
const result = await deleteRepository(repositoryId
|
|
418
|
+
const result = await deleteRepository(repositoryId, {
|
|
419
|
+
deleteFromDisk: options?.deleteFromDisk === true,
|
|
420
|
+
});
|
|
419
421
|
if (!result.success) {
|
|
420
422
|
toast.error(result.error ?? 'Failed to remove repository');
|
|
421
423
|
rollback();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the action list for the (+) FloatingActionButton on the control
|
|
3
|
+
* center. Extracted from control-center-inner.tsx so the parent component
|
|
4
|
+
* stays focused on graph state + rendering.
|
|
5
|
+
*/
|
|
6
|
+
import type { useRouter } from 'next/navigation';
|
|
7
|
+
import type { FloatingActionButtonAction } from '../../common/floating-action-button/index.js';
|
|
8
|
+
import type { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
|
|
9
|
+
interface UseFabActionsParams {
|
|
10
|
+
router: ReturnType<typeof useRouter>;
|
|
11
|
+
clickSound: {
|
|
12
|
+
play: () => void;
|
|
13
|
+
};
|
|
14
|
+
guardedNavigate: (fn: () => void) => void;
|
|
15
|
+
handlePickFolder: () => void;
|
|
16
|
+
onNewProject: () => void;
|
|
17
|
+
featureFlags: ReturnType<typeof useFeatureFlags>;
|
|
18
|
+
}
|
|
19
|
+
export declare function useFabActions({ router, clickSound, guardedNavigate, handlePickFolder, onNewProject, featureFlags, }: UseFabActionsParams): FloatingActionButtonAction[];
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=use-fab-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-fab-actions.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-fab-actions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;IACrC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACjC,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC1C,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,YAAY,GACb,EAAE,mBAAmB,GAAG,0BAA0B,EAAE,CA6DpD"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Build the action list for the (+) FloatingActionButton on the control
|
|
4
|
+
* center. Extracted from control-center-inner.tsx so the parent component
|
|
5
|
+
* stays focused on graph state + rendering.
|
|
6
|
+
*/
|
|
7
|
+
import { useMemo } from 'react';
|
|
8
|
+
import { FolderOpen, FolderPlus, GitBranch, Github, Sparkles } from 'lucide-react';
|
|
9
|
+
import { useTranslation } from 'react-i18next';
|
|
10
|
+
export function useFabActions({ router, clickSound, guardedNavigate, handlePickFolder, onNewProject, featureFlags, }) {
|
|
11
|
+
const { t } = useTranslation('web');
|
|
12
|
+
return useMemo(() => {
|
|
13
|
+
const actions = [
|
|
14
|
+
{
|
|
15
|
+
id: 'new-project',
|
|
16
|
+
label: 'New project',
|
|
17
|
+
icon: _jsx(FolderPlus, { className: "h-4 w-4" }),
|
|
18
|
+
onClick: () => {
|
|
19
|
+
clickSound.play();
|
|
20
|
+
onNewProject();
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'new-feature',
|
|
25
|
+
label: t('fab.newFeature'),
|
|
26
|
+
icon: _jsx(Sparkles, { className: "h-4 w-4" }),
|
|
27
|
+
onClick: () => {
|
|
28
|
+
clickSound.play();
|
|
29
|
+
guardedNavigate(() => router.push('/create'));
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 'add-local-repo',
|
|
34
|
+
label: t('fab.localFolder'),
|
|
35
|
+
icon: _jsx(FolderOpen, { className: "h-4 w-4" }),
|
|
36
|
+
onClick: handlePickFolder,
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
if (featureFlags.adoptBranch) {
|
|
40
|
+
actions.push({
|
|
41
|
+
id: 'adopt-branch',
|
|
42
|
+
label: t('fab.adoptBranch'),
|
|
43
|
+
icon: _jsx(GitBranch, { className: "h-4 w-4" }),
|
|
44
|
+
onClick: () => {
|
|
45
|
+
guardedNavigate(() => router.push('/adopt'));
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (featureFlags.githubImport) {
|
|
50
|
+
actions.push({
|
|
51
|
+
id: 'add-github-repo',
|
|
52
|
+
label: t('fab.fromGithub'),
|
|
53
|
+
icon: _jsx(Github, { className: "h-4 w-4" }),
|
|
54
|
+
onClick: () => {
|
|
55
|
+
window.dispatchEvent(new CustomEvent('shep:open-github-import'));
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return actions;
|
|
60
|
+
}, [
|
|
61
|
+
t,
|
|
62
|
+
clickSound,
|
|
63
|
+
guardedNavigate,
|
|
64
|
+
router,
|
|
65
|
+
handlePickFolder,
|
|
66
|
+
onNewProject,
|
|
67
|
+
featureFlags.adoptBranch,
|
|
68
|
+
featureFlags.githubImport,
|
|
69
|
+
]);
|
|
70
|
+
}
|