@shepai/cli 1.162.0 → 1.163.0-pr503.5f6f050
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/FabLayoutConfig.yaml +11 -0
- package/apis/json-schema/Settings.yaml +3 -0
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts +20 -0
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +1 -1
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/repositories/list-github-organizations.use-case.d.ts +13 -0
- package/dist/packages/core/src/application/use-cases/repositories/list-github-organizations.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/repositories/list-github-organizations.use-case.js +35 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +13 -0
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +5 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +6 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/050-add-fab-position-swapped.d.ts +15 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/050-add-fab-position-swapped.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/050-add-fab-position-swapped.js +20 -0
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.js +20 -0
- package/dist/src/presentation/cli/commands/repo/add.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/repo/add.command.js +3 -1
- package/dist/src/presentation/tui/wizards/github-import.wizard.d.ts +5 -2
- package/dist/src/presentation/tui/wizards/github-import.wizard.d.ts.map +1 -1
- package/dist/src/presentation/tui/wizards/github-import.wizard.js +38 -6
- package/dist/src/presentation/web/app/actions/list-github-organizations.d.ts +6 -0
- package/dist/src/presentation/web/app/actions/list-github-organizations.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/list-github-organizations.js +17 -0
- package/dist/src/presentation/web/app/actions/list-github-repositories.d.ts +1 -0
- package/dist/src/presentation/web/app/actions/list-github-repositories.d.ts.map +1 -1
- package/dist/src/presentation/web/app/layout.d.ts.map +1 -1
- package/dist/src/presentation/web/app/layout.js +3 -1
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.d.ts +8 -1
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.js +37 -7
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.d.ts +1 -0
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.js +35 -0
- package/dist/src/presentation/web/components/features/chat/ChatSheet.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/ChatSheet.js +22 -2
- 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 +15 -1
- package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/settings-page-client.js +9 -2
- package/dist/src/presentation/web/hooks/fab-layout-context.d.ts +18 -0
- package/dist/src/presentation/web/hooks/fab-layout-context.d.ts.map +1 -0
- package/dist/src/presentation/web/hooks/fab-layout-context.js +19 -0
- package/dist/src/presentation/web/lib/fab-layout.d.ts +11 -0
- package/dist/src/presentation/web/lib/fab-layout.d.ts.map +1 -0
- package/dist/src/presentation/web/lib/fab-layout.js +21 -0
- package/dist/translations/ar/web.json +8 -0
- package/dist/translations/de/web.json +8 -0
- package/dist/translations/en/web.json +8 -0
- package/dist/translations/es/web.json +8 -0
- package/dist/translations/fr/web.json +8 -0
- package/dist/translations/he/web.json +8 -0
- package/dist/translations/pt/web.json +8 -0
- package/dist/translations/ru/web.json +8 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -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 +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js +2 -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 +73 -58
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +2 -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 +87 -72
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +2 -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 +87 -72
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/chat/page.js +2 -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 +73 -58
- package/web/.next/server/app/(dashboard)/create/page.js +2 -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 +87 -72
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +2 -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 +87 -72
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js +2 -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 +67 -52
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +2 -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 +25 -10
- package/web/.next/server/app/_not-found/page.js +2 -2
- 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/settings/page/server-reference-manifest.json +31 -16
- package/web/.next/server/app/settings/page.js +2 -2
- 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 +35 -20
- package/web/.next/server/app/skills/page.js +2 -2
- 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 +35 -20
- package/web/.next/server/app/tools/page.js +2 -2
- 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 +25 -10
- package/web/.next/server/app/version/page.js +2 -2
- 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/[root-of-the-server]__beda892a._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +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]__1abe77bb._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1abe77bb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__563e4faf._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__563e4faf._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6eb2a2b0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7562afc6._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7562afc6._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__821a11c1._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__821a11c1._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__98740ee4._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__98740ee4._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ba9f9e11._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ba9f9e11._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5ceba65._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5ceba65._.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/{_9495d50b._.js → _0727935d._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_9495d50b._.js.map → _0727935d._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_075fae20._.js +4 -0
- package/web/.next/server/chunks/ssr/_075fae20._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_0dc06d07._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_125c55af._.js +4 -0
- package/web/.next/server/chunks/ssr/_125c55af._.js.map +1 -0
- 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/{_bcaea66b._.js → _1879404a._.js} +2 -2
- package/web/.next/server/chunks/ssr/_1879404a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_b9ba2473._.js → _1e08a336._.js} +2 -2
- package/web/.next/server/chunks/ssr/_1e08a336._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_22e00a14._.js +4 -0
- package/web/.next/server/chunks/ssr/_22e00a14._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_73e1eb5f._.js → _3de1087f._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_73e1eb5f._.js.map → _3de1087f._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_5119a3df._.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/_628621c7._.js +4 -0
- package/web/.next/server/chunks/ssr/_628621c7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_68996e5b._.js +3 -0
- package/web/.next/server/chunks/ssr/_68996e5b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_07635b7c._.js → _7731942a._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_07635b7c._.js.map → _7731942a._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_83850f88._.js +3 -0
- package/web/.next/server/chunks/ssr/_83850f88._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_9412b27f._.js +4 -0
- package/web/.next/server/chunks/ssr/_9412b27f._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_a5a5901d._.js +4 -0
- package/web/.next/server/chunks/ssr/_a5a5901d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_ac4a3873._.js +1 -1
- package/web/.next/server/chunks/ssr/_c3f595c6._.js +4 -0
- package/web/.next/server/chunks/ssr/_c3f595c6._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_1c309165._.js → _ce97386b._.js} +2 -2
- package/web/.next/server/chunks/ssr/_ce97386b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_f1ba9be6._.js +6 -0
- package/web/.next/server/chunks/ssr/_f1ba9be6._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_f33cd07e._.js +6 -0
- package/web/.next/server/chunks/ssr/_f33cd07e._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_f8b45233._.js +4 -0
- package/web/.next/server/chunks/ssr/_f8b45233._.js.map +1 -0
- 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/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
- 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_ui_select_tsx_45d6b8ae._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_select_tsx_45d6b8ae._.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 +636 -495
- package/web/.next/static/chunks/{192dd30a464572ef.js → 0805da7a199bdc0a.js} +1 -1
- package/web/.next/static/chunks/{7cd7aef397d53b94.js → 0f825451a1040a62.js} +1 -1
- package/web/.next/static/chunks/19799c09a4a77b39.js +1 -0
- package/web/.next/static/chunks/{5281c5a2011132bc.js → 22c064bd5ad1f2be.js} +2 -2
- package/web/.next/static/chunks/28ae5046faef6cec.js +1 -0
- package/web/.next/static/chunks/{2770aabb38d76609.js → 424b022838e07298.js} +1 -1
- package/web/.next/static/chunks/{a81350e847797ff8.js → 515b86b64f00d706.js} +1 -1
- package/web/.next/static/chunks/{d0613380bbaa9a8e.js → 686fc60ef05bd22c.js} +1 -1
- package/web/.next/static/chunks/{1db4dfa35a1637ed.js → 75574020d3d8f848.js} +1 -1
- package/web/.next/static/chunks/{04b3e8b2c0b2a310.js → 9147cfa8ef0e4895.js} +2 -2
- package/web/.next/static/chunks/956608a44b5ebe81.js +1 -0
- package/web/.next/static/chunks/c3a67566f78b5bc3.js +1 -0
- package/web/.next/static/chunks/d8c61f7a2e44f08a.js +7 -0
- package/web/.next/static/chunks/e779296e738a812b.css +1 -0
- package/web/.next/static/chunks/f89211075016be1f.js +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__209c9597._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__209c9597._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__27301e38._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__27301e38._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6fecf886._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6fecf886._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8d27866c._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8d27866c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9f3504c7._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9f3504c7._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__bd6ed91a._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__bd6ed91a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ee0eaaf9._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ee0eaaf9._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_1c309165._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_3a0b989f._.js +0 -6
- package/web/.next/server/chunks/ssr/_3a0b989f._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_5f69c13f._.js +0 -4
- package/web/.next/server/chunks/ssr/_5f69c13f._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_7c5b97c6._.js +0 -4
- package/web/.next/server/chunks/ssr/_7c5b97c6._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_82c57f10._.js +0 -4
- package/web/.next/server/chunks/ssr/_82c57f10._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_9c5bd84a._.js +0 -3
- package/web/.next/server/chunks/ssr/_9c5bd84a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_a0e3f7e4._.js +0 -4
- package/web/.next/server/chunks/ssr/_a0e3f7e4._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_b9ba2473._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_bcaea66b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_ca0aa7f0._.js +0 -4
- package/web/.next/server/chunks/ssr/_ca0aa7f0._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_cb5a021e._.js +0 -4
- package/web/.next/server/chunks/ssr/_cb5a021e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_d86175ae._.js +0 -4
- package/web/.next/server/chunks/ssr/_d86175ae._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_d8bedf13._.js +0 -4
- package/web/.next/server/chunks/ssr/_d8bedf13._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_d90b0a06._.js +0 -3
- package/web/.next/server/chunks/ssr/_d90b0a06._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_fa7efce3._.js +0 -6
- package/web/.next/server/chunks/ssr/_fa7efce3._.js.map +0 -1
- package/web/.next/static/chunks/1d980f961818ff68.js +0 -1
- package/web/.next/static/chunks/2c9404cf96b0a5a0.js +0 -1
- package/web/.next/static/chunks/4864ff06a738d58b.js +0 -1
- package/web/.next/static/chunks/63b4954715fc3423.js +0 -1
- package/web/.next/static/chunks/83928a921868a809.js +0 -1
- package/web/.next/static/chunks/86c476f04ff32e7b.css +0 -1
- package/web/.next/static/chunks/cb41e1da2ce3a710.js +0 -7
- /package/web/.next/static/{GXMtXdKTjklQ1IkrOohzE → cnHbfa1l1H5G2Pb5kqwsf}/_buildManifest.js +0 -0
- /package/web/.next/static/{GXMtXdKTjklQ1IkrOohzE → cnHbfa1l1H5G2Pb5kqwsf}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{GXMtXdKTjklQ1IkrOohzE → cnHbfa1l1H5G2Pb5kqwsf}/_ssgManifest.js +0 -0
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Interactive TUI wizard that guides users through importing a GitHub repository.
|
|
5
5
|
* Offers two paths: paste a GitHub URL or browse the user's repositories.
|
|
6
|
+
* Supports browsing repos from multiple organizations.
|
|
6
7
|
* Returns the selected URL/nameWithOwner and optional destination override.
|
|
7
8
|
*/
|
|
8
9
|
import { select, input } from '@inquirer/prompts';
|
|
9
10
|
import { GitHubUrlParseError } from '../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
10
11
|
import { getTuiI18n } from '../i18n.js';
|
|
11
12
|
import { shepTheme } from '../themes/shep.theme.js';
|
|
13
|
+
/** Sentinel value representing the authenticated user's personal account */
|
|
14
|
+
const PERSONAL_OWNER = '__personal__';
|
|
12
15
|
/**
|
|
13
16
|
* Format a GitHub repo for display in the select list.
|
|
14
17
|
* Shows name, visibility badge, and truncated description.
|
|
@@ -27,14 +30,15 @@ function formatRepoChoice(repo) {
|
|
|
27
30
|
* Steps:
|
|
28
31
|
* 1. Choose import method (URL input or browse repos)
|
|
29
32
|
* 2a. If URL: prompt for URL, validate with parseGitHubUrl
|
|
30
|
-
* 2b. If browse: fetch repos via listUseCase, display select list
|
|
33
|
+
* 2b. If browse: optionally select an org, then fetch repos via listUseCase, display select list
|
|
31
34
|
* 3. Optionally prompt for destination directory override
|
|
32
35
|
*
|
|
33
36
|
* @param gitHubService - Service for URL validation
|
|
34
37
|
* @param listUseCase - Use case for listing user repos
|
|
38
|
+
* @param listOrgsUseCase - Use case for listing user's organizations
|
|
35
39
|
* @returns The selected import target and optional destination
|
|
36
40
|
*/
|
|
37
|
-
export async function githubImportWizard(gitHubService, listUseCase) {
|
|
41
|
+
export async function githubImportWizard(gitHubService, listUseCase, listOrgsUseCase) {
|
|
38
42
|
// Step 1: Choose import method
|
|
39
43
|
const t = getTuiI18n().t;
|
|
40
44
|
const method = await select({
|
|
@@ -58,7 +62,7 @@ export async function githubImportWizard(gitHubService, listUseCase) {
|
|
|
58
62
|
url = await promptForUrl(gitHubService);
|
|
59
63
|
}
|
|
60
64
|
else {
|
|
61
|
-
url = await promptForBrowse(listUseCase);
|
|
65
|
+
url = await promptForBrowse(listUseCase, listOrgsUseCase);
|
|
62
66
|
}
|
|
63
67
|
// Step 3: Optional destination override
|
|
64
68
|
const dest = await promptForDestination();
|
|
@@ -97,11 +101,39 @@ async function promptForUrl(gitHubService) {
|
|
|
97
101
|
}
|
|
98
102
|
/**
|
|
99
103
|
* Prompt the user to browse and select from their GitHub repositories.
|
|
100
|
-
*
|
|
104
|
+
* If organizations are available, first prompts the user to select an owner.
|
|
101
105
|
*/
|
|
102
|
-
async function promptForBrowse(listUseCase) {
|
|
103
|
-
const repos = await listUseCase.execute({ limit: 30 });
|
|
106
|
+
async function promptForBrowse(listUseCase, listOrgsUseCase) {
|
|
104
107
|
const t = getTuiI18n().t;
|
|
108
|
+
let owner;
|
|
109
|
+
// Try to load organizations for the owner selector
|
|
110
|
+
if (listOrgsUseCase) {
|
|
111
|
+
try {
|
|
112
|
+
const orgs = await listOrgsUseCase.execute();
|
|
113
|
+
if (orgs.length > 0) {
|
|
114
|
+
const ownerChoices = [
|
|
115
|
+
{ name: 'My repositories', value: PERSONAL_OWNER },
|
|
116
|
+
...orgs.map((org) => ({
|
|
117
|
+
name: org.login,
|
|
118
|
+
value: org.login,
|
|
119
|
+
description: org.description || undefined,
|
|
120
|
+
})),
|
|
121
|
+
];
|
|
122
|
+
const selectedOwner = await select({
|
|
123
|
+
message: 'Select account',
|
|
124
|
+
choices: ownerChoices,
|
|
125
|
+
theme: shepTheme,
|
|
126
|
+
});
|
|
127
|
+
if (selectedOwner !== PERSONAL_OWNER) {
|
|
128
|
+
owner = selectedOwner;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Org listing failure is non-critical — proceed with personal repos
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const repos = await listUseCase.execute({ limit: 30, owner });
|
|
105
137
|
if (repos.length === 0) {
|
|
106
138
|
throw new Error(t('tui:wizards.githubImport.noRepos'));
|
|
107
139
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GitHubOrganization } from '../../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
2
|
+
export declare function listGitHubOrganizations(): Promise<{
|
|
3
|
+
orgs?: GitHubOrganization[];
|
|
4
|
+
error?: string;
|
|
5
|
+
}>;
|
|
6
|
+
//# sourceMappingURL=list-github-organizations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-github-organizations.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/list-github-organizations.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oFAAoF,CAAC;AAG7H,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IACvD,IAAI,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAYD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { resolve } from '../../lib/server-container.js';
|
|
3
|
+
import { GitHubAuthError } from '../../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
4
|
+
export async function listGitHubOrganizations() {
|
|
5
|
+
try {
|
|
6
|
+
const useCase = resolve('ListGitHubOrganizationsUseCase');
|
|
7
|
+
const orgs = await useCase.execute();
|
|
8
|
+
return { orgs };
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error instanceof GitHubAuthError) {
|
|
12
|
+
return { error: 'GitHub CLI is not authenticated. Run `gh auth login` to sign in.' };
|
|
13
|
+
}
|
|
14
|
+
const message = error instanceof Error ? error.message : 'Failed to list organizations';
|
|
15
|
+
return { error: message };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { GitHubRepo } from '../../../../../packages/core/src/application/po
|
|
|
2
2
|
interface ListGitHubRepositoriesInput {
|
|
3
3
|
search?: string;
|
|
4
4
|
limit?: number;
|
|
5
|
+
owner?: string;
|
|
5
6
|
}
|
|
6
7
|
export declare function listGitHubRepositories(input?: ListGitHubRepositoriesInput): Promise<{
|
|
7
8
|
repos?: GitHubRepo[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-github-repositories.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/list-github-repositories.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oFAAoF,CAAC;AAGrH,UAAU,2BAA2B;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,CAAC,EAAE,2BAA2B,GAClC,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAYnD"}
|
|
1
|
+
{"version":3,"file":"list-github-repositories.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/list-github-repositories.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oFAAoF,CAAC;AAGrH,UAAU,2BAA2B;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,CAAC,EAAE,2BAA2B,GAClC,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAYnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAErC,OAAO,6BAA6B,CAAC;AACrC,OAAO,2CAA2C,CAAC;AACnD,OAAO,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAErC,OAAO,6BAA6B,CAAC;AACrC,OAAO,2CAA2C,CAAC;AACnD,OAAO,eAAe,CAAC;AAWvB,sFAAsF;AACtF,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,eAAO,MAAM,QAAQ,EAAE,QAkBtB,CAAC;AAEF,wBAA8B,UAAU,CAAC,EACvC,QAAQ,GACT,EAAE,QAAQ,CAAC;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC,oDA6BD"}
|
|
@@ -6,7 +6,9 @@ import './globals.css';
|
|
|
6
6
|
import { AppShell } from '../components/layouts/app-shell/index.js';
|
|
7
7
|
import { Toaster } from '../components/ui/sonner.js';
|
|
8
8
|
import { getFeatureFlags } from '../lib/feature-flags.js';
|
|
9
|
+
import { getFabLayout } from '../lib/fab-layout.js';
|
|
9
10
|
import { FeatureFlagsProvider } from '../hooks/feature-flags-context.js';
|
|
11
|
+
import { FabLayoutProvider } from '../hooks/fab-layout-context.js';
|
|
10
12
|
import { QueryProvider } from '../components/providers/query-provider.js';
|
|
11
13
|
import { I18nProvider } from '../components/providers/i18n-provider.js';
|
|
12
14
|
import { getLanguagePreference } from '../lib/language.js';
|
|
@@ -36,5 +38,5 @@ export default async function RootLayout({ children, }) {
|
|
|
36
38
|
const { language, dir } = getLanguagePreference();
|
|
37
39
|
return (_jsxs("html", { lang: language, dir: dir, suppressHydrationWarning: true, children: [_jsx("head", { children: _jsx("script", { dangerouslySetInnerHTML: {
|
|
38
40
|
__html: `(function(){try{var d=document.documentElement,t=localStorage.getItem('shep-theme'),s=window.matchMedia('(prefers-color-scheme: dark)').matches;if(t==='dark'||(t==='system'&&s)||(!t&&s)){d.classList.add('dark')}}catch(e){}})();`,
|
|
39
|
-
} }) }), _jsxs("body", { className: "min-h-screen antialiased", children: [_jsx(I18nProvider, { initialLanguage: language, children: _jsx(QueryProvider, { children: _jsx(FeatureFlagsProvider, { flags: getFeatureFlags(), children: _jsx(AppShell, { sidebarOpen: sidebarOpen, children: children }) }) }) }), _jsx(Toaster, { position: "bottom-center" })] })] }));
|
|
41
|
+
} }) }), _jsxs("body", { className: "min-h-screen antialiased", children: [_jsx(I18nProvider, { initialLanguage: language, children: _jsx(QueryProvider, { children: _jsx(FeatureFlagsProvider, { flags: getFeatureFlags(), children: _jsx(FabLayoutProvider, { layout: getFabLayout(), children: _jsx(AppShell, { sidebarOpen: sidebarOpen, children: children }) }) }) }) }), _jsx(Toaster, { position: "bottom-center" })] })] }));
|
|
40
42
|
}
|
package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { GitHubRepo } from '../../../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
2
|
+
import type { GitHubOrganization } from '../../../../../../packages/core/src/application/ports/output/services/github-repository-service.interface.js';
|
|
2
3
|
export interface GitHubRepoBrowserProps {
|
|
3
4
|
onSelect: (nameWithOwner: string) => void;
|
|
4
5
|
loading?: boolean;
|
|
@@ -6,10 +7,16 @@ export interface GitHubRepoBrowserProps {
|
|
|
6
7
|
fetchRepos?: (input?: {
|
|
7
8
|
search?: string;
|
|
8
9
|
limit?: number;
|
|
10
|
+
owner?: string;
|
|
9
11
|
}) => Promise<{
|
|
10
12
|
repos?: GitHubRepo[];
|
|
11
13
|
error?: string;
|
|
12
14
|
}>;
|
|
15
|
+
/** Override the fetch function for testing/stories */
|
|
16
|
+
fetchOrgs?: () => Promise<{
|
|
17
|
+
orgs?: GitHubOrganization[];
|
|
18
|
+
error?: string;
|
|
19
|
+
}>;
|
|
13
20
|
}
|
|
14
|
-
export declare function GitHubRepoBrowser({ onSelect, loading: externalLoading, fetchRepos, }: GitHubRepoBrowserProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function GitHubRepoBrowser({ onSelect, loading: externalLoading, fetchRepos, fetchOrgs, }: GitHubRepoBrowserProps): import("react/jsx-runtime").JSX.Element;
|
|
15
22
|
//# sourceMappingURL=github-repo-browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-repo-browser.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/github-import-dialog/github-repo-browser.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"github-repo-browser.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/github-import-dialog/github-repo-browser.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oFAAoF,CAAC;AACrH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oFAAoF,CAAC;AAK7H,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,KAAK,OAAO,CAAC;QAAE,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5E;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,OAAO,EAAE,eAAuB,EAChC,UAAmC,EACnC,SAAmC,GACpC,EAAE,sBAAsB,2CA+KxB"}
|
package/dist/src/presentation/web/components/common/github-import-dialog/github-repo-browser.js
CHANGED
|
@@ -5,18 +5,44 @@ import { Lock, Globe, Loader2, Search, AlertCircle } from 'lucide-react';
|
|
|
5
5
|
import { Input } from '../../ui/input.js';
|
|
6
6
|
import { Badge } from '../../ui/badge.js';
|
|
7
7
|
import { Skeleton } from '../../ui/skeleton.js';
|
|
8
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../ui/select.js';
|
|
8
9
|
import { listGitHubRepositories } from '../../../app/actions/list-github-repositories.js';
|
|
9
|
-
|
|
10
|
+
import { listGitHubOrganizations } from '../../../app/actions/list-github-organizations.js';
|
|
11
|
+
/** Sentinel value representing the authenticated user's personal account */
|
|
12
|
+
const PERSONAL_OWNER = '__personal__';
|
|
13
|
+
export function GitHubRepoBrowser({ onSelect, loading: externalLoading = false, fetchRepos = listGitHubRepositories, fetchOrgs = listGitHubOrganizations, }) {
|
|
10
14
|
const [repos, setRepos] = useState([]);
|
|
15
|
+
const [orgs, setOrgs] = useState([]);
|
|
11
16
|
const [fetching, setFetching] = useState(true);
|
|
12
17
|
const [error, setError] = useState('');
|
|
13
18
|
const [search, setSearch] = useState('');
|
|
19
|
+
const [selectedOwner, setSelectedOwner] = useState(PERSONAL_OWNER);
|
|
14
20
|
const debounceRef = useRef(null);
|
|
15
|
-
|
|
21
|
+
// Fetch organizations on mount
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
async function loadOrgs() {
|
|
24
|
+
try {
|
|
25
|
+
const result = await fetchOrgs();
|
|
26
|
+
if (result.orgs) {
|
|
27
|
+
setOrgs(result.orgs);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Org listing failure is non-critical — user can still browse personal repos
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
loadOrgs();
|
|
35
|
+
}, [fetchOrgs]);
|
|
36
|
+
const fetchData = useCallback(async (searchTerm, owner) => {
|
|
16
37
|
setFetching(true);
|
|
17
38
|
setError('');
|
|
18
39
|
try {
|
|
19
|
-
const
|
|
40
|
+
const input = {};
|
|
41
|
+
if (searchTerm)
|
|
42
|
+
input.search = searchTerm;
|
|
43
|
+
if (owner && owner !== PERSONAL_OWNER)
|
|
44
|
+
input.owner = owner;
|
|
45
|
+
const result = await fetchRepos(Object.keys(input).length > 0 ? input : undefined);
|
|
20
46
|
if (result.error) {
|
|
21
47
|
setError(result.error);
|
|
22
48
|
setRepos([]);
|
|
@@ -34,19 +60,23 @@ export function GitHubRepoBrowser({ onSelect, loading: externalLoading = false,
|
|
|
34
60
|
}
|
|
35
61
|
}, [fetchRepos]);
|
|
36
62
|
useEffect(() => {
|
|
37
|
-
fetchData();
|
|
38
|
-
}, [fetchData]);
|
|
63
|
+
fetchData(search || undefined, selectedOwner);
|
|
64
|
+
}, [fetchData, selectedOwner]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
39
65
|
function handleSearchChange(value) {
|
|
40
66
|
setSearch(value);
|
|
41
67
|
if (debounceRef.current)
|
|
42
68
|
clearTimeout(debounceRef.current);
|
|
43
69
|
debounceRef.current = setTimeout(() => {
|
|
44
|
-
fetchData(value || undefined);
|
|
70
|
+
fetchData(value || undefined, selectedOwner);
|
|
45
71
|
}, 300);
|
|
46
72
|
}
|
|
73
|
+
function handleOwnerChange(value) {
|
|
74
|
+
setSelectedOwner(value);
|
|
75
|
+
setSearch('');
|
|
76
|
+
}
|
|
47
77
|
const disabled = externalLoading;
|
|
48
78
|
if (error && !fetching) {
|
|
49
79
|
return (_jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", "data-testid": "repo-browser-error", children: [_jsx(AlertCircle, { className: "text-destructive h-8 w-8" }), _jsx("p", { className: "text-destructive text-sm", children: error })] }));
|
|
50
80
|
}
|
|
51
|
-
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { placeholder: "Search repositories...", value: search, onChange: (e) => handleSearchChange(e.target.value), className: "ps-9", disabled: disabled, "aria-label": "Search repositories" })] }), _jsx("div", { className: "max-h-64 overflow-x-hidden overflow-y-auto rounded-md border", role: "listbox", "aria-label": "GitHub repositories", children: fetching ? (_jsx("div", { className: "flex flex-col gap-2 p-3", "data-testid": "repo-browser-loading", children: Array.from({ length: 5 }).map((_, i) => (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-48" }), _jsx(Skeleton, { className: "h-3 w-72" })] }, `skeleton-${String(i)}`))) })) : repos.length === 0 ? (_jsx("div", { className: "text-muted-foreground py-8 text-center text-sm", "data-testid": "repo-browser-empty", children: "No repositories found" })) : (repos.map((repo) => (_jsxs("button", { type: "button", role: "option", "aria-selected": false, className: "hover:bg-accent flex w-full items-start gap-2 border-b px-3 py-2.5 text-start last:border-b-0 disabled:opacity-50", onClick: () => onSelect(repo.nameWithOwner), disabled: disabled, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium", children: repo.nameWithOwner }), _jsx(Badge, { variant: repo.isPrivate ? 'secondary' : 'outline', className: "shrink-0 text-xs", children: repo.isPrivate ? (_jsxs(_Fragment, { children: [_jsx(Lock, { className: "me-1 h-3 w-3" }), "Private"] })) : (_jsxs(_Fragment, { children: [_jsx(Globe, { className: "me-1 h-3 w-3" }), "Public"] })) })] }), repo.description ? (_jsx("p", { className: "text-muted-foreground mt-0.5 truncate text-xs", children: repo.description })) : null] }), disabled ? _jsx(Loader2, { className: "mt-0.5 h-4 w-4 shrink-0 animate-spin" }) : null] }, repo.nameWithOwner)))) })] }));
|
|
81
|
+
return (_jsxs("div", { className: "flex flex-col gap-3", children: [orgs.length > 0 ? (_jsxs(Select, { value: selectedOwner, onValueChange: handleOwnerChange, disabled: disabled, children: [_jsx(SelectTrigger, { "aria-label": "Select owner", children: _jsx(SelectValue, { placeholder: "Select owner" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: PERSONAL_OWNER, children: "My repositories" }), orgs.map((org) => (_jsx(SelectItem, { value: org.login, children: org.login }, org.login)))] })] })) : null, _jsxs("div", { className: "relative", children: [_jsx(Search, { className: "text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" }), _jsx(Input, { placeholder: "Search repositories...", value: search, onChange: (e) => handleSearchChange(e.target.value), className: "ps-9", disabled: disabled, "aria-label": "Search repositories" })] }), _jsx("div", { className: "max-h-64 overflow-x-hidden overflow-y-auto rounded-md border", role: "listbox", "aria-label": "GitHub repositories", children: fetching ? (_jsx("div", { className: "flex flex-col gap-2 p-3", "data-testid": "repo-browser-loading", children: Array.from({ length: 5 }).map((_, i) => (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-48" }), _jsx(Skeleton, { className: "h-3 w-72" })] }, `skeleton-${String(i)}`))) })) : repos.length === 0 ? (_jsx("div", { className: "text-muted-foreground py-8 text-center text-sm", "data-testid": "repo-browser-empty", children: "No repositories found" })) : (repos.map((repo) => (_jsxs("button", { type: "button", role: "option", "aria-selected": false, className: "hover:bg-accent flex w-full items-start gap-2 border-b px-3 py-2.5 text-start last:border-b-0 disabled:opacity-50", onClick: () => onSelect(repo.nameWithOwner), disabled: disabled, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium", children: repo.nameWithOwner }), _jsx(Badge, { variant: repo.isPrivate ? 'secondary' : 'outline', className: "shrink-0 text-xs", children: repo.isPrivate ? (_jsxs(_Fragment, { children: [_jsx(Lock, { className: "me-1 h-3 w-3" }), "Private"] })) : (_jsxs(_Fragment, { children: [_jsx(Globe, { className: "me-1 h-3 w-3" }), "Public"] })) })] }), repo.description ? (_jsx("p", { className: "text-muted-foreground mt-0.5 truncate text-xs", children: repo.description })) : null] }), disabled ? _jsx(Loader2, { className: "mt-0.5 h-4 w-4 shrink-0 animate-spin" }) : null] }, repo.nameWithOwner)))) })] }));
|
|
52
82
|
}
|
|
@@ -4,6 +4,7 @@ declare const meta: Meta<typeof GitHubRepoBrowser>;
|
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof GitHubRepoBrowser>;
|
|
6
6
|
export declare const Default: Story;
|
|
7
|
+
export declare const WithOrganizations: Story;
|
|
7
8
|
export declare const Loading: Story;
|
|
8
9
|
export declare const Empty: Story;
|
|
9
10
|
export declare const Error: Story;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-repo-browser.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"github-repo-browser.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/github-import-dialog/github-repo-browser.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAgE1D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,iBAAiB,CAiBxC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhD,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAU/B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAKnB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAQnB,CAAC"}
|
|
@@ -38,6 +38,26 @@ const mockRepos = [
|
|
|
38
38
|
pushedAt: '2025-03-11T09:00:00Z',
|
|
39
39
|
},
|
|
40
40
|
];
|
|
41
|
+
const mockOrgRepos = [
|
|
42
|
+
{
|
|
43
|
+
name: 'platform',
|
|
44
|
+
nameWithOwner: 'acme-corp/platform',
|
|
45
|
+
description: 'Core platform monorepo',
|
|
46
|
+
isPrivate: true,
|
|
47
|
+
pushedAt: '2025-03-15T10:00:00Z',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'design-system',
|
|
51
|
+
nameWithOwner: 'acme-corp/design-system',
|
|
52
|
+
description: 'Shared design system components',
|
|
53
|
+
isPrivate: false,
|
|
54
|
+
pushedAt: '2025-03-14T08:00:00Z',
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
const mockOrgs = [
|
|
58
|
+
{ login: 'acme-corp', description: 'Acme Corporation' },
|
|
59
|
+
{ login: 'open-source-collective', description: 'Open source projects' },
|
|
60
|
+
];
|
|
41
61
|
const meta = {
|
|
42
62
|
title: 'Composed/GitHubRepoBrowser',
|
|
43
63
|
component: GitHubRepoBrowser,
|
|
@@ -56,17 +76,31 @@ export default meta;
|
|
|
56
76
|
export const Default = {
|
|
57
77
|
args: {
|
|
58
78
|
fetchRepos: () => Promise.resolve({ repos: mockRepos }),
|
|
79
|
+
fetchOrgs: () => Promise.resolve({ orgs: [] }),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
export const WithOrganizations = {
|
|
83
|
+
args: {
|
|
84
|
+
fetchRepos: (input) => {
|
|
85
|
+
if (input?.owner === 'acme-corp') {
|
|
86
|
+
return Promise.resolve({ repos: mockOrgRepos });
|
|
87
|
+
}
|
|
88
|
+
return Promise.resolve({ repos: mockRepos });
|
|
89
|
+
},
|
|
90
|
+
fetchOrgs: () => Promise.resolve({ orgs: mockOrgs }),
|
|
59
91
|
},
|
|
60
92
|
};
|
|
61
93
|
export const Loading = {
|
|
62
94
|
args: {
|
|
63
95
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
64
96
|
fetchRepos: () => new Promise(() => { }), // never resolves
|
|
97
|
+
fetchOrgs: () => Promise.resolve({ orgs: [] }),
|
|
65
98
|
},
|
|
66
99
|
};
|
|
67
100
|
export const Empty = {
|
|
68
101
|
args: {
|
|
69
102
|
fetchRepos: () => Promise.resolve({ repos: [] }),
|
|
103
|
+
fetchOrgs: () => Promise.resolve({ orgs: [] }),
|
|
70
104
|
},
|
|
71
105
|
};
|
|
72
106
|
export const Error = {
|
|
@@ -74,5 +108,6 @@ export const Error = {
|
|
|
74
108
|
fetchRepos: () => Promise.resolve({
|
|
75
109
|
error: 'GitHub CLI is not authenticated. Run `gh auth login` to sign in.',
|
|
76
110
|
}),
|
|
111
|
+
fetchOrgs: () => Promise.resolve({ orgs: [] }),
|
|
77
112
|
},
|
|
78
113
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatSheet.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/ChatSheet.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChatSheet.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/ChatSheet.tsx"],"names":[],"mappings":"AA2DA,wBAAgB,eAAe,4CAwY9B"}
|
|
@@ -8,6 +8,8 @@ import { Button } from '../../ui/button.js';
|
|
|
8
8
|
import { ChatTab } from './ChatTab.js';
|
|
9
9
|
import { ChatDotIndicator } from './ChatDotIndicator.js';
|
|
10
10
|
import { useTurnStatus } from '../../../hooks/turn-statuses-provider.js';
|
|
11
|
+
import { useFabLayout } from '../../../hooks/fab-layout-context.js';
|
|
12
|
+
import { useSidebar } from '../../ui/sidebar.js';
|
|
11
13
|
// ── Persistent global chat popup (draggable + resizable) ──────────────────
|
|
12
14
|
const DEFAULT_W = 520;
|
|
13
15
|
const DEFAULT_H_VH = 70; // percentage of viewport height
|
|
@@ -48,6 +50,8 @@ export function GlobalChatPopup() {
|
|
|
48
50
|
const [hasOpened, setHasOpened] = useState(false);
|
|
49
51
|
const [isMaximized, setIsMaximized] = useState(false);
|
|
50
52
|
const globalChatTurnStatus = useTurnStatus('global');
|
|
53
|
+
const { swapPosition } = useFabLayout();
|
|
54
|
+
const { state: sidebarState } = useSidebar();
|
|
51
55
|
// Position/size — initialized from localStorage
|
|
52
56
|
// eslint-disable-next-line react/hook-use-state -- wrapped setters below
|
|
53
57
|
const [pos, setPosRaw] = useState(() => loadPersistedState().pos);
|
|
@@ -229,7 +233,7 @@ export function GlobalChatPopup() {
|
|
|
229
233
|
};
|
|
230
234
|
return (_jsxs(_Fragment, { children: [hasOpened ? (_jsxs("div", { ref: panelRef, className: cn(isMaximized
|
|
231
235
|
? 'bg-background fixed inset-0 z-[60] flex flex-col overflow-hidden dark:bg-neutral-900'
|
|
232
|
-
: cn(!pos && 'fixed end-8 bottom-24', 'z-[60] flex flex-col overflow-hidden rounded-lg', 'border-border/60 border dark:border-white/10', 'bg-background dark:bg-neutral-900', 'shadow-[0_8px_40px_-8px_rgba(0,0,0,0.2)] dark:shadow-[0_8px_40px_-8px_rgba(0,0,0,0.6)]'), 'transition-opacity duration-300 ease-out', isOpen ? 'pointer-events-auto opacity-100' : 'pointer-events-none opacity-0'), style: panelStyle, children: [!isMaximized ? (_jsx("div", { className: "h-[2px] shrink-0 bg-gradient-to-r from-transparent via-violet-500/50 to-transparent" })) : null, !isMaximized ? (_jsx("div", { onMouseDown: onResizeStart, className: "absolute end-0 top-0 z-10 h-4 w-4 cursor-ne-resize" })) : null, _jsxs("div", { onMouseDown: isMaximized ? undefined : onDragStart, className: cn('relative flex h-11 shrink-0 items-center gap-2.5 border-b border-black/[0.06] px-3.5 dark:border-white/[0.06]', !isMaximized && 'cursor-grab active:cursor-grabbing'), children: [_jsx("div", { className: "from-foreground/[0.02] to-foreground/[0.02] pointer-events-none absolute inset-0 bg-gradient-to-r via-transparent" }), !isMaximized ? (_jsx(GripVertical, { className: "text-foreground/15 relative h-3.5 w-3.5 shrink-0" })) : null, _jsx("div", { className: "relative flex h-5 w-5 items-center justify-center", children: _jsx(Bot, { className: "text-foreground/50 h-4 w-4" }) }), _jsxs("div", { className: "relative flex items-baseline gap-2", children: [_jsx("span", { className: "text-foreground/90 text-base font-bold tracking-tight", children: "Shep" }), _jsx("span", { className: "text-foreground/30 text-xs font-medium tracking-widest uppercase", children: "global" })] }), _jsxs("div", { className: "relative ms-auto flex items-center gap-0.5", children: [_jsx("button", { type: "button", onClick: toggleMaximize, className: "text-foreground/30 hover:text-foreground/60 rounded-md p-1 transition-colors", title: isMaximized ? 'Restore (⌘⇧M)' : 'Maximize (⌘⇧M)', children: isMaximized ? (_jsx(Minimize2, { className: "h-3.5 w-3.5" })) : (_jsx(Maximize2, { className: "h-3.5 w-3.5" })) }), _jsx("button", { type: "button", onClick: handleClose, className: "text-foreground/30 hover:text-foreground/60 rounded-md p-1 transition-colors", title: "Close (\u2318\u21E7K)", children: _jsx(X, { className: "h-3.5 w-3.5" }) })] })] }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: _jsx(ChatTab, { featureId: "global" }) }), !isMaximized ? (_jsx("div", { onMouseDown: (e) => {
|
|
236
|
+
: cn(!pos && (swapPosition ? 'fixed start-8 bottom-24' : 'fixed end-8 bottom-24'), 'z-[60] flex flex-col overflow-hidden rounded-lg', 'border-border/60 border dark:border-white/10', 'bg-background dark:bg-neutral-900', 'shadow-[0_8px_40px_-8px_rgba(0,0,0,0.2)] dark:shadow-[0_8px_40px_-8px_rgba(0,0,0,0.6)]'), 'transition-opacity duration-300 ease-out', isOpen ? 'pointer-events-auto opacity-100' : 'pointer-events-none opacity-0'), style: panelStyle, children: [!isMaximized ? (_jsx("div", { className: "h-[2px] shrink-0 bg-gradient-to-r from-transparent via-violet-500/50 to-transparent" })) : null, !isMaximized ? (_jsx("div", { onMouseDown: onResizeStart, className: "absolute end-0 top-0 z-10 h-4 w-4 cursor-ne-resize" })) : null, _jsxs("div", { onMouseDown: isMaximized ? undefined : onDragStart, className: cn('relative flex h-11 shrink-0 items-center gap-2.5 border-b border-black/[0.06] px-3.5 dark:border-white/[0.06]', !isMaximized && 'cursor-grab active:cursor-grabbing'), children: [_jsx("div", { className: "from-foreground/[0.02] to-foreground/[0.02] pointer-events-none absolute inset-0 bg-gradient-to-r via-transparent" }), !isMaximized ? (_jsx(GripVertical, { className: "text-foreground/15 relative h-3.5 w-3.5 shrink-0" })) : null, _jsx("div", { className: "relative flex h-5 w-5 items-center justify-center", children: _jsx(Bot, { className: "text-foreground/50 h-4 w-4" }) }), _jsxs("div", { className: "relative flex items-baseline gap-2", children: [_jsx("span", { className: "text-foreground/90 text-base font-bold tracking-tight", children: "Shep" }), _jsx("span", { className: "text-foreground/30 text-xs font-medium tracking-widest uppercase", children: "global" })] }), _jsxs("div", { className: "relative ms-auto flex items-center gap-0.5", children: [_jsx("button", { type: "button", onClick: toggleMaximize, className: "text-foreground/30 hover:text-foreground/60 rounded-md p-1 transition-colors", title: isMaximized ? 'Restore (⌘⇧M)' : 'Maximize (⌘⇧M)', children: isMaximized ? (_jsx(Minimize2, { className: "h-3.5 w-3.5" })) : (_jsx(Maximize2, { className: "h-3.5 w-3.5" })) }), _jsx("button", { type: "button", onClick: handleClose, className: "text-foreground/30 hover:text-foreground/60 rounded-md p-1 transition-colors", title: "Close (\u2318\u21E7K)", children: _jsx(X, { className: "h-3.5 w-3.5" }) })] })] }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: _jsx(ChatTab, { featureId: "global" }) }), !isMaximized ? (_jsx("div", { onMouseDown: (e) => {
|
|
233
237
|
e.preventDefault();
|
|
234
238
|
e.stopPropagation();
|
|
235
239
|
const panel = panelRef.current;
|
|
@@ -255,7 +259,23 @@ export function GlobalChatPopup() {
|
|
|
255
259
|
};
|
|
256
260
|
document.addEventListener('mousemove', onMove);
|
|
257
261
|
document.addEventListener('mouseup', onUp);
|
|
258
|
-
}, className: "absolute end-0 bottom-0 z-10 h-4 w-4 cursor-se-resize" })) : null] })) : null, _jsxs(
|
|
262
|
+
}, className: "absolute end-0 bottom-0 z-10 h-4 w-4 cursor-se-resize" })) : null] })) : null, _jsxs(ChatFabWrapper, { swapPosition: swapPosition, sidebarState: sidebarState, isMaximized: isMaximized, children: [_jsxs(Button, { size: "icon", onClick: toggle, className: cn('relative h-14 w-14 rounded-full shadow-lg', 'transition-all duration-200 hover:scale-105 hover:shadow-xl active:scale-95', isOpen
|
|
259
263
|
? 'bg-violet-600 text-white hover:bg-violet-500'
|
|
260
264
|
: 'bg-violet-500 text-white hover:bg-violet-400 dark:bg-violet-500 dark:hover:bg-violet-400'), children: [_jsx(MessageSquare, { className: cn('absolute h-7 w-7 stroke-[2.5] transition-all duration-200', isOpen ? 'scale-0 rotate-90 opacity-0' : 'scale-100 rotate-0 opacity-100') }), _jsx(X, { className: cn('absolute h-6 w-6 stroke-[2.5] transition-all duration-200', isOpen ? 'scale-100 rotate-0 opacity-100' : 'scale-0 -rotate-90 opacity-0') }), !isOpen && _jsx(ChatDotIndicator, { status: globalChatTurnStatus, className: "end-0 top-0" })] }), _jsx("div", { className: "pointer-events-none absolute bottom-[calc(100%+8px)] left-1/2 -translate-x-1/2 translate-y-1 opacity-0 transition-all duration-200 group-hover/fab:translate-y-0 group-hover/fab:opacity-100", children: _jsxs("div", { className: "bg-foreground rounded-lg px-3 py-1.5 text-center shadow-lg", children: [_jsx("p", { className: "text-background text-xs font-medium whitespace-nowrap", children: t('chat.shepChat') }), _jsxs("p", { className: "text-background/50 mt-0.5 flex items-center justify-center gap-1 text-[10px]", children: [_jsx("kbd", { className: "bg-background/15 rounded px-1 py-px font-mono", children: "\u2318" }), _jsx("kbd", { className: "bg-background/15 rounded px-1 py-px font-mono", children: "\u21E7" }), _jsx("kbd", { className: "bg-background/15 rounded px-1 py-px font-mono", children: "K" })] })] }) })] })] }));
|
|
261
265
|
}
|
|
266
|
+
/** Wrapper for the Chat FAB that handles position swapping. */
|
|
267
|
+
function ChatFabWrapper({ swapPosition, sidebarState, isMaximized, children, }) {
|
|
268
|
+
const { i18n } = useTranslation('web');
|
|
269
|
+
const isRtl = i18n.dir() === 'rtl';
|
|
270
|
+
if (!swapPosition) {
|
|
271
|
+
return (_jsx("div", { className: cn('group/fab fixed end-8 bottom-6 z-30', isMaximized && 'hidden'), children: children }));
|
|
272
|
+
}
|
|
273
|
+
// Swapped: chat FAB moves to start side, tracking sidebar width
|
|
274
|
+
const sidebarOffset = sidebarState === 'expanded'
|
|
275
|
+
? 'calc(var(--sidebar-width) + 32px)'
|
|
276
|
+
: 'calc(var(--sidebar-width-icon) + 32px)';
|
|
277
|
+
const positionStyle = isRtl
|
|
278
|
+
? { right: sidebarOffset, transition: 'right 200ms ease-in-out' }
|
|
279
|
+
: { left: sidebarOffset, transition: 'left 200ms ease-in-out' };
|
|
280
|
+
return (_jsx("div", { className: cn('group/fab fixed bottom-6 z-30', isMaximized && 'hidden'), style: positionStyle, children: children }));
|
|
281
|
+
}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAgC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CA+czF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -16,6 +16,7 @@ import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
|
16
16
|
import { useDrawerCloseGuard } from '../../../hooks/drawer-close-guard.js';
|
|
17
17
|
import { useViewportPersistence } from '../../../hooks/use-viewport-persistence.js';
|
|
18
18
|
import { useSidebar } from '../../ui/sidebar.js';
|
|
19
|
+
import { useFabLayout } from '../../../hooks/fab-layout-context.js';
|
|
19
20
|
import { ControlCenterEmptyState } from './control-center-empty-state.js';
|
|
20
21
|
import { useControlCenterState } from './use-control-center-state.js';
|
|
21
22
|
const AUTO_FOCUS_OPTIONS = {
|
|
@@ -353,11 +354,24 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
353
354
|
const canvasToolbar = (_jsx(CanvasToolbar, { showArchived: showArchived, onToggleArchived: () => setShowArchived(!showArchived), onResetViewport: resetViewport }));
|
|
354
355
|
return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, selectedRepository: selectedRepository, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, toolbar: canvasToolbar, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }), showCanvas ? _jsx(CreateFab, { actions: fabActions }) : null] }));
|
|
355
356
|
}
|
|
356
|
-
/** (+) FAB that tracks sidebar width via CSS var + transition.
|
|
357
|
+
/** (+) FAB that tracks sidebar width via CSS var + transition.
|
|
358
|
+
* When fabLayout.swapPosition is true, moves to the end side (right in LTR). */
|
|
357
359
|
function CreateFab({ actions }) {
|
|
358
360
|
const { state } = useSidebar();
|
|
359
361
|
const { i18n } = useTranslation('web');
|
|
362
|
+
const { swapPosition } = useFabLayout();
|
|
360
363
|
const isRtl = i18n.dir() === 'rtl';
|
|
364
|
+
// Default: start side (left in LTR), tracking sidebar width
|
|
365
|
+
// Swapped: end side (right in LTR), fixed 32px from edge
|
|
366
|
+
if (swapPosition) {
|
|
367
|
+
const positionStyle = isRtl
|
|
368
|
+
? {
|
|
369
|
+
left: 'calc(var(--sidebar-width-icon) + 32px)',
|
|
370
|
+
transition: 'left 200ms ease-in-out',
|
|
371
|
+
}
|
|
372
|
+
: { right: '32px', transition: 'right 200ms ease-in-out' };
|
|
373
|
+
return (_jsx(FloatingActionButton, { actions: actions, className: "!fixed bottom-6", style: positionStyle }));
|
|
374
|
+
}
|
|
361
375
|
// Sidebar expanded = var(--sidebar-width) = 16rem, collapsed = var(--sidebar-width-icon) = 3rem
|
|
362
376
|
// Position just outside the sidebar edge with 16px gap
|
|
363
377
|
const offset = state === 'expanded'
|
package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EACV,QAAQ,EAKT,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AA8B/E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AA+QD,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,kBAAkB,GACnB,EAAE,uBAAuB,2CAi3CzB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useTransition, useRef, useEffect, useCallback } from 'react';
|
|
4
|
-
import { Check, Bot, Terminal, GitBranch, Activity, Bell, Flag, Database, Globe, Minus, Plus, ExternalLink, Settings2, Timer, MessageSquare, } from 'lucide-react';
|
|
4
|
+
import { Check, Bot, Terminal, GitBranch, Activity, Bell, Flag, Database, Globe, Minus, Plus, ExternalLink, Settings2, Timer, MessageSquare, LayoutGrid, } from 'lucide-react';
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { cn } from '../../../lib/utils.js';
|
|
@@ -36,6 +36,7 @@ const SECTIONS = [
|
|
|
36
36
|
{ id: 'notifications', labelKey: 'settings.sections.notifications', icon: Bell },
|
|
37
37
|
{ id: 'feature-flags', labelKey: 'settings.sections.flags', icon: Flag },
|
|
38
38
|
{ id: 'interactive-agent', labelKey: 'settings.sections.chat', icon: MessageSquare },
|
|
39
|
+
{ id: 'fab-layout', labelKey: 'settings.sections.layout', icon: LayoutGrid },
|
|
39
40
|
{ id: 'database', labelKey: 'settings.sections.database', icon: Database },
|
|
40
41
|
];
|
|
41
42
|
function useSaveIndicator() {
|
|
@@ -190,6 +191,9 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
190
191
|
const [interactiveEnabled, setInteractiveEnabled] = useState(interactiveAgentConfig.enabled);
|
|
191
192
|
const [interactiveTimeout, setInteractiveTimeout] = useState(String(interactiveAgentConfig.autoTimeoutMinutes));
|
|
192
193
|
const [interactiveSessions, setInteractiveSessions] = useState(String(interactiveAgentConfig.maxConcurrentSessions));
|
|
194
|
+
// FAB layout state
|
|
195
|
+
const fabLayoutConfig = settings.fabLayout ?? { swapPosition: false };
|
|
196
|
+
const [fabSwapPosition, setFabSwapPosition] = useState(fabLayoutConfig.swapPosition);
|
|
193
197
|
// Notification state
|
|
194
198
|
const [inApp, setInApp] = useState(settings.notifications.inApp.enabled);
|
|
195
199
|
const [events, setEvents] = useState({ ...settings.notifications.events });
|
|
@@ -588,7 +592,10 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
588
592
|
maxConcurrentSessions: clamped,
|
|
589
593
|
},
|
|
590
594
|
});
|
|
591
|
-
} }) })] }), _jsx(SectionHint, { children: t('settings.interactiveAgent.hint') })] }), _jsxs("div", { id: "section-
|
|
595
|
+
} }) })] }), _jsx(SectionHint, { children: t('settings.interactiveAgent.hint') })] }), _jsxs("div", { id: "section-fab-layout", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsx(SettingsSection, { icon: LayoutGrid, title: t('settings.fabLayout.title'), description: t('settings.fabLayout.description'), testId: "fab-layout-settings-section", children: _jsx(SwitchRow, { label: t('settings.fabLayout.swapPosition'), description: t('settings.fabLayout.swapPositionDescription'), id: "fab-swap-position", testId: "switch-fab-swap-position", checked: fabSwapPosition, onChange: (v) => {
|
|
596
|
+
setFabSwapPosition(v);
|
|
597
|
+
save({ fabLayout: { swapPosition: v } });
|
|
598
|
+
} }) }), _jsx(SectionHint, { children: t('settings.fabLayout.hint') })] }), _jsxs("div", { id: "section-database", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsxs(SettingsSection, { icon: Database, title: t('settings.database.title'), description: t('settings.database.sectionDescription'), testId: "database-settings-section", children: [_jsx(SettingsRow, { label: t('settings.database.location'), description: t('settings.database.locationDescription'), children: _jsx("span", { className: "text-muted-foreground max-w-50 truncate font-mono text-xs", "data-testid": "shep-home-path", children: shepHome }) }), _jsx(SettingsRow, { label: t('settings.database.size'), children: _jsx("span", { className: "text-muted-foreground text-xs", "data-testid": "db-file-size", children: dbFileSize }) })] }), _jsx(SectionHint, { links: [
|
|
592
599
|
{
|
|
593
600
|
label: t('settings.database.links.settingsService'),
|
|
594
601
|
href: 'https://github.com/shep-ai/shep/blob/main/docs/architecture/settings-service.md',
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { FabLayoutState } from '../lib/fab-layout.js';
|
|
3
|
+
interface FabLayoutProviderProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
layout: FabLayoutState;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Provides server-resolved FAB layout configuration to all client components.
|
|
9
|
+
* Initialized in the root layout with values from the DB singleton.
|
|
10
|
+
*/
|
|
11
|
+
export declare function FabLayoutProvider({ children, layout }: FabLayoutProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Read FAB layout config from context. Returns default (not swapped)
|
|
14
|
+
* when used outside a FabLayoutProvider (e.g., Storybook, tests).
|
|
15
|
+
*/
|
|
16
|
+
export declare function useFabLayout(): FabLayoutState;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=fab-layout-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fab-layout-context.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/fab-layout-context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMvD,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,sBAAsB,2CAE7E;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,cAAc,CAE7C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext } from 'react';
|
|
4
|
+
const defaultLayout = { swapPosition: false };
|
|
5
|
+
const FabLayoutContext = createContext(defaultLayout);
|
|
6
|
+
/**
|
|
7
|
+
* Provides server-resolved FAB layout configuration to all client components.
|
|
8
|
+
* Initialized in the root layout with values from the DB singleton.
|
|
9
|
+
*/
|
|
10
|
+
export function FabLayoutProvider({ children, layout }) {
|
|
11
|
+
return _jsx(FabLayoutContext.Provider, { value: layout, children: children });
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Read FAB layout config from context. Returns default (not swapped)
|
|
15
|
+
* when used outside a FabLayoutProvider (e.g., Storybook, tests).
|
|
16
|
+
*/
|
|
17
|
+
export function useFabLayout() {
|
|
18
|
+
return useContext(FabLayoutContext);
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FAB layout configuration for the web UI.
|
|
3
|
+
*
|
|
4
|
+
* Reads from Settings.fabLayout when available, defaulting to
|
|
5
|
+
* swapPosition = false (Create FAB on start side, Chat FAB on end side).
|
|
6
|
+
*/
|
|
7
|
+
export interface FabLayoutState {
|
|
8
|
+
swapPosition: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function getFabLayout(): FabLayoutState;
|
|
11
|
+
//# sourceMappingURL=fab-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fab-layout.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/lib/fab-layout.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,YAAY,IAAI,cAAc,CAa7C"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FAB layout configuration for the web UI.
|
|
3
|
+
*
|
|
4
|
+
* Reads from Settings.fabLayout when available, defaulting to
|
|
5
|
+
* swapPosition = false (Create FAB on start side, Chat FAB on end side).
|
|
6
|
+
*/
|
|
7
|
+
import { hasSettings, getSettings } from '../../../../packages/core/src/infrastructure/services/settings.service.js';
|
|
8
|
+
export function getFabLayout() {
|
|
9
|
+
try {
|
|
10
|
+
if (hasSettings()) {
|
|
11
|
+
const fabLayout = getSettings().fabLayout;
|
|
12
|
+
if (fabLayout) {
|
|
13
|
+
return { swapPosition: fabLayout.swapPosition };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// Settings not initialized (e.g., during build/SSG or client-side hydration)
|
|
19
|
+
}
|
|
20
|
+
return { swapPosition: false };
|
|
21
|
+
}
|