@shepai/cli 1.72.3 → 1.72.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.js +4 -0
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +36 -6
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts +4 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts +1 -1
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +4 -2
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +6 -5
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +5 -0
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +24 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +4 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.js +2 -2
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts +4 -0
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.d.ts +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.js +2 -2
- package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.d.ts +4 -0
- package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.d.ts +1 -1
- package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.js +2 -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 +12 -8
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +2 -1
- 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 +13 -5
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +7 -5
- package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.js +1 -1
- package/dist/src/presentation/web/components/ui/alert-dialog.stories.js +1 -1
- package/dist/src/presentation/web/hooks/drawer-close-guard.d.ts +26 -0
- package/dist/src/presentation/web/hooks/drawer-close-guard.d.ts.map +1 -0
- package/dist/src/presentation/web/hooks/drawer-close-guard.js +74 -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/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +14 -14
- 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]/page/server-reference-manifest.json +17 -17
- 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]/page/server-reference-manifest.json +12 -12
- 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)/create/page/server-reference-manifest.json +14 -14
- 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]/page/server-reference-manifest.json +17 -17
- 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 +12 -12
- 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]/page/server-reference-manifest.json +12 -12
- 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 +1 -1
- 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/skills/page/server-reference-manifest.json +6 -6
- 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 +1 -1
- 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 +1 -1
- 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/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/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8fcb9132._.js +2 -2
- package/web/.next/server/chunks/ssr/_00e6c698._.js +1 -1
- package/web/.next/server/chunks/ssr/_00e6c698._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_07c2a32a._.js +9 -0
- package/web/.next/server/chunks/ssr/_07c2a32a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_26129e04._.js +3 -0
- package/web/.next/server/chunks/ssr/_26129e04._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_37259405._.js +1 -1
- package/web/.next/server/chunks/ssr/_37259405._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_85d0351b._.js +1 -1
- package/web/.next/server/chunks/ssr/_85d0351b._.js.map +1 -1
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/_9f5276de._.js → server/chunks/ssr/_8fcb97eb._.js} +3 -9
- package/web/.next/server/chunks/ssr/_8fcb97eb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_fc3a6895._.js +1 -1
- package/web/.next/server/chunks/ssr/_fc3a6895._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.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/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +20 -20
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +17 -17
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +17 -17
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +12 -12
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__8fcb9132._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_00e6c698._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_07c2a32a._.js +9 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_26129e04._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_37259405._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_85d0351b._.js +1 -1
- package/web/.next/{server/chunks/ssr/_9f5276de._.js → standalone/src/presentation/web/.next/server/chunks/ssr/_8fcb97eb._.js} +3 -9
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_fc3a6895._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +20 -20
- package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx +1 -0
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/control-center-drawer.stories.tsx +8 -0
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx +45 -3
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts +4 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +5 -1
- package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx +32 -0
- package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +8 -6
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-config.ts +4 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +4 -0
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts +4 -0
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.tsx +4 -0
- package/web/.next/standalone/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs-config.ts +4 -0
- package/web/.next/standalone/src/presentation/web/components/common/tech-review-tabs/tech-review-tabs.tsx +4 -0
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +12 -8
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center.stories.tsx +6 -3
- package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +11 -5
- package/web/.next/standalone/src/presentation/web/components/layouts/app-shell/app-shell.tsx +11 -7
- package/web/.next/standalone/src/presentation/web/components/layouts/app-sidebar/app-sidebar.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/ui/alert-dialog.stories.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/hooks/drawer-close-guard.tsx +149 -0
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/00adfce42dbbd5ef.js +1 -0
- package/web/.next/static/chunks/06dfd668334ffb4e.js +7 -0
- package/web/.next/static/chunks/{311b817783b3ebd7.js → 0f3e1ea42efba7e8.js} +1 -1
- package/web/.next/static/chunks/{47435830535491e8.js → 3c79bca4d3f18f66.js} +1 -1
- package/web/.next/static/chunks/{e44849eb58a3335f.js → 515d5b157a7620b9.js} +1 -1
- package/web/.next/static/chunks/{7183f9b53504c911.js → 5a962b5baf7c4d1d.js} +1 -1
- package/web/.next/static/chunks/{6310c6efd3e3ff8c.js → 87db91411a520cea.js} +1 -1
- package/web/.next/static/chunks/{0274480f2b09f92e.js → 9261e2adb145d388.js} +1 -1
- package/web/.next/static/chunks/{c6a53b653c68f935.js → 92ebb1cad6f24333.js} +4 -10
- package/web/.next/static/chunks/952c8aa7247dcb3f.js +1 -0
- package/web/.next/static/chunks/d2e6361bdd7a02a5.js +1 -0
- package/web/.next/static/chunks/{8d3e12279b2aa76b.js → ebfd2ed5b143b5b6.js} +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/server/chunks/ssr/_45715073._.js +0 -3
- package/web/.next/server/chunks/ssr/_45715073._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_9f5276de._.js.map +0 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_11589942._.js +0 -3
- package/web/.next/server/chunks/ssr/node_modules__pnpm_11589942._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_45715073._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/node_modules__pnpm_11589942._.js +0 -3
- package/web/.next/static/chunks/0b99eb9664d47ca7.js +0 -1
- package/web/.next/static/chunks/3e46df89d84cae41.js +0 -1
- package/web/.next/static/chunks/c279e0294d864963.js +0 -1
- package/web/.next/static/chunks/c4b35853f5a100b6.js +0 -1
- /package/web/.next/static/{he5MpZ65Zlh6SbVlx_mbE → KbyvoLS1Q62iF5F25ZKYW}/_buildManifest.js +0 -0
- /package/web/.next/static/{he5MpZ65Zlh6SbVlx_mbE → KbyvoLS1Q62iF5F25ZKYW}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{he5MpZ65Zlh6SbVlx_mbE → KbyvoLS1Q62iF5F25ZKYW}/_ssgManifest.js +0 -0
|
@@ -16,8 +16,12 @@ export function DrawerActionBar({
|
|
|
16
16
|
isProcessing = false,
|
|
17
17
|
isRejecting = false,
|
|
18
18
|
children,
|
|
19
|
+
chatInput: controlledChatInput,
|
|
20
|
+
onChatInputChange,
|
|
19
21
|
}: DrawerActionBarProps) {
|
|
20
|
-
const [
|
|
22
|
+
const [internalChatInput, setInternalChatInput] = useState('');
|
|
23
|
+
const chatInput = controlledChatInput ?? internalChatInput;
|
|
24
|
+
const setChatInput = onChatInputChange ?? setInternalChatInput;
|
|
21
25
|
const approveSound = useSoundAction('approve');
|
|
22
26
|
const disabled = isProcessing || isRejecting;
|
|
23
27
|
|
|
@@ -5,6 +5,7 @@ import { FeatureCreateDrawer } from './feature-create-drawer';
|
|
|
5
5
|
import type { FeatureCreatePayload } from './feature-create-drawer';
|
|
6
6
|
import type { WorkflowDefaults } from '@/app/actions/get-workflow-defaults';
|
|
7
7
|
import { Button } from '@/components/ui/button';
|
|
8
|
+
import { DrawerCloseGuardProvider } from '@/hooks/drawer-close-guard';
|
|
8
9
|
|
|
9
10
|
/* ---------------------------------------------------------------------------
|
|
10
11
|
* Meta — component-level docs + interactive controls
|
|
@@ -44,6 +45,13 @@ const meta: Meta<typeof FeatureCreateDrawer> = {
|
|
|
44
45
|
title: 'Drawers/Feature/FeatureCreateDrawer',
|
|
45
46
|
component: FeatureCreateDrawer,
|
|
46
47
|
tags: ['autodocs'],
|
|
48
|
+
decorators: [
|
|
49
|
+
(Story) => (
|
|
50
|
+
<DrawerCloseGuardProvider>
|
|
51
|
+
<Story />
|
|
52
|
+
</DrawerCloseGuardProvider>
|
|
53
|
+
),
|
|
54
|
+
],
|
|
47
55
|
parameters: {
|
|
48
56
|
layout: 'fullscreen',
|
|
49
57
|
},
|
|
@@ -346,6 +354,30 @@ export const InDrawer: Story = {
|
|
|
346
354
|
render: () => <CreateDrawerShellTemplate />,
|
|
347
355
|
};
|
|
348
356
|
|
|
357
|
+
/* ---------------------------------------------------------------------------
|
|
358
|
+
* Discard confirmation stories
|
|
359
|
+
* ------------------------------------------------------------------------- */
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Discard confirmation — type text, then click Cancel to trigger the
|
|
363
|
+
* "Discard unsaved changes?" dialog. Demonstrates the dirty-form guard.
|
|
364
|
+
*/
|
|
365
|
+
export const DiscardConfirmation: Story = {
|
|
366
|
+
render: () => <CreateDrawerTrigger label="Open (Discard Confirmation)" />,
|
|
367
|
+
play: async ({ canvasElement }) => {
|
|
368
|
+
const canvas = within(canvasElement);
|
|
369
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Open (Discard Confirmation)' }));
|
|
370
|
+
|
|
371
|
+
const body = within(canvasElement.ownerDocument.body);
|
|
372
|
+
const nameInput = await body.findByPlaceholderText('e.g. GitHub OAuth Login');
|
|
373
|
+
await userEvent.type(nameInput, 'My Feature');
|
|
374
|
+
|
|
375
|
+
// Click Cancel — should show the discard confirmation dialog
|
|
376
|
+
const cancelButton = body.getByRole('button', { name: 'Cancel' });
|
|
377
|
+
await userEvent.click(cancelButton);
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
|
|
349
381
|
/* ---------------------------------------------------------------------------
|
|
350
382
|
* Interactive story — full paths shown in submitted data panel
|
|
351
383
|
* ------------------------------------------------------------------------- */
|
|
@@ -24,6 +24,7 @@ import { CheckboxGroup } from '@/components/ui/checkbox-group';
|
|
|
24
24
|
import { CheckboxGroupItem } from '@/components/ui/checkbox-group-item';
|
|
25
25
|
import { Badge } from '@/components/ui/badge';
|
|
26
26
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
|
27
|
+
import { useGuardedDrawerClose } from '@/hooks/drawer-close-guard';
|
|
27
28
|
import type { FileAttachment } from '@shepai/core/infrastructure/services/file-dialog.service';
|
|
28
29
|
import type { WorkflowDefaults } from '@/app/actions/get-workflow-defaults';
|
|
29
30
|
import { pickFiles } from './pick-files';
|
|
@@ -125,10 +126,11 @@ export function FeatureCreateDrawer({
|
|
|
125
126
|
setParentId(undefined);
|
|
126
127
|
}, [defaultGates, defaultPush, defaultOpenPr]);
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
// Track whether the form has unsaved data
|
|
130
|
+
const isDirty = name.trim() !== '' || description.trim() !== '' || attachments.length > 0;
|
|
131
|
+
|
|
132
|
+
// Shared close guard — shows confirmation when dirty, prevents navigation
|
|
133
|
+
const { attemptClose } = useGuardedDrawerClose({ open, isDirty, onClose, onReset: resetForm });
|
|
132
134
|
|
|
133
135
|
const handleSubmit = useCallback(
|
|
134
136
|
(e: React.FormEvent) => {
|
|
@@ -187,7 +189,7 @@ export function FeatureCreateDrawer({
|
|
|
187
189
|
return (
|
|
188
190
|
<BaseDrawer
|
|
189
191
|
open={open}
|
|
190
|
-
onClose={
|
|
192
|
+
onClose={attemptClose}
|
|
191
193
|
size="md"
|
|
192
194
|
modal={false}
|
|
193
195
|
data-testid="feature-create-drawer"
|
|
@@ -206,7 +208,7 @@ export function FeatureCreateDrawer({
|
|
|
206
208
|
}
|
|
207
209
|
footer={
|
|
208
210
|
<div className="flex flex-row justify-end gap-2">
|
|
209
|
-
<Button variant="outline" onClick={
|
|
211
|
+
<Button variant="outline" onClick={attemptClose} disabled={isSubmitting}>
|
|
210
212
|
Cancel
|
|
211
213
|
</Button>
|
|
212
214
|
<Button type="submit" form="create-feature-form" disabled={!name.trim() || isSubmitting}>
|
|
@@ -58,6 +58,10 @@ export interface MergeReviewProps {
|
|
|
58
58
|
isProcessing?: boolean;
|
|
59
59
|
/** Whether a reject operation is in flight */
|
|
60
60
|
isRejecting?: boolean;
|
|
61
|
+
/** Controlled chat input for the revision input. */
|
|
62
|
+
chatInput?: string;
|
|
63
|
+
/** Handler for chat input changes. */
|
|
64
|
+
onChatInputChange?: (value: string) => void;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
/** Props for the merge review drawer (shell wrapper) */
|
package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx
CHANGED
|
@@ -52,6 +52,8 @@ export function MergeReview({
|
|
|
52
52
|
onReject,
|
|
53
53
|
isProcessing = false,
|
|
54
54
|
isRejecting = false,
|
|
55
|
+
chatInput,
|
|
56
|
+
onChatInputChange,
|
|
55
57
|
}: MergeReviewProps) {
|
|
56
58
|
const { pr, diffSummary, phases, branch, warning } = data;
|
|
57
59
|
|
|
@@ -188,6 +190,8 @@ export function MergeReview({
|
|
|
188
190
|
revisionPlaceholder="Ask AI to revise before merging..."
|
|
189
191
|
isProcessing={isProcessing}
|
|
190
192
|
isRejecting={isRejecting}
|
|
193
|
+
chatInput={chatInput}
|
|
194
|
+
onChatInputChange={onChatInputChange}
|
|
191
195
|
/>
|
|
192
196
|
</div>
|
|
193
197
|
);
|
|
@@ -24,6 +24,10 @@ export interface PrdQuestionnaireProps {
|
|
|
24
24
|
isRejecting?: boolean;
|
|
25
25
|
/** Show the goal/context header (default: false) */
|
|
26
26
|
showHeader?: boolean;
|
|
27
|
+
/** Controlled chat input for the revision input. */
|
|
28
|
+
chatInput?: string;
|
|
29
|
+
/** Handler for chat input changes. */
|
|
30
|
+
onChatInputChange?: (value: string) => void;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
export interface PrdQuestionnaireDrawerProps extends Omit<PrdQuestionnaireProps, 'data'> {
|
|
@@ -18,6 +18,8 @@ export function PrdQuestionnaire({
|
|
|
18
18
|
isProcessing = false,
|
|
19
19
|
isRejecting = false,
|
|
20
20
|
showHeader = false,
|
|
21
|
+
chatInput,
|
|
22
|
+
onChatInputChange,
|
|
21
23
|
}: PrdQuestionnaireProps) {
|
|
22
24
|
const { question, context, questions, finalAction } = data;
|
|
23
25
|
const [currentStep, setCurrentStep] = useState(0);
|
|
@@ -171,6 +173,8 @@ export function PrdQuestionnaire({
|
|
|
171
173
|
revisionPlaceholder="Ask AI to refine requirements..."
|
|
172
174
|
isProcessing={isProcessing}
|
|
173
175
|
isRejecting={isRejecting}
|
|
176
|
+
chatInput={chatInput}
|
|
177
|
+
onChatInputChange={onChatInputChange}
|
|
174
178
|
>
|
|
175
179
|
<div
|
|
176
180
|
className={cn(
|
|
@@ -14,4 +14,8 @@ export interface TechReviewTabsProps {
|
|
|
14
14
|
isProcessing?: boolean;
|
|
15
15
|
/** Whether a reject operation is in flight */
|
|
16
16
|
isRejecting?: boolean;
|
|
17
|
+
/** Controlled chat input for the revision input. */
|
|
18
|
+
chatInput?: string;
|
|
19
|
+
/** Handler for chat input changes. */
|
|
20
|
+
onChatInputChange?: (value: string) => void;
|
|
17
21
|
}
|
|
@@ -14,6 +14,8 @@ export function TechReviewTabs({
|
|
|
14
14
|
onReject,
|
|
15
15
|
isProcessing = false,
|
|
16
16
|
isRejecting = false,
|
|
17
|
+
chatInput,
|
|
18
|
+
onChatInputChange,
|
|
17
19
|
}: TechReviewTabsProps) {
|
|
18
20
|
if (techData.decisions.length === 0) return null;
|
|
19
21
|
|
|
@@ -54,6 +56,8 @@ export function TechReviewTabs({
|
|
|
54
56
|
revisionPlaceholder="Ask AI to revise the plan..."
|
|
55
57
|
isProcessing={isProcessing}
|
|
56
58
|
isRejecting={isRejecting}
|
|
59
|
+
chatInput={chatInput}
|
|
60
|
+
onChatInputChange={onChatInputChange}
|
|
57
61
|
/>
|
|
58
62
|
</div>
|
|
59
63
|
);
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from '@/hooks/sidebar-features-context';
|
|
15
15
|
import { useSelectedFeatureId } from '@/hooks/use-selected-feature-id';
|
|
16
16
|
import { useSoundAction } from '@/hooks/use-sound-action';
|
|
17
|
+
import { useDrawerCloseGuard } from '@/hooks/drawer-close-guard';
|
|
17
18
|
import { ControlCenterEmptyState } from './control-center-empty-state';
|
|
18
19
|
import { useControlCenterState } from './use-control-center-state';
|
|
19
20
|
|
|
@@ -27,6 +28,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
27
28
|
const pathname = usePathname();
|
|
28
29
|
const selectedFeatureId = useSelectedFeatureId();
|
|
29
30
|
const clickSound = useSoundAction('click');
|
|
31
|
+
const { guardedNavigate, getIsDirty } = useDrawerCloseGuard();
|
|
30
32
|
|
|
31
33
|
const {
|
|
32
34
|
nodes,
|
|
@@ -37,7 +39,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
37
39
|
handleDeleteFeature,
|
|
38
40
|
handleDeleteRepository,
|
|
39
41
|
createFeatureNode,
|
|
40
|
-
} = useControlCenterState(initialNodes, initialEdges);
|
|
42
|
+
} = useControlCenterState(initialNodes, initialEdges, getIsDirty);
|
|
41
43
|
|
|
42
44
|
// Publish sidebar features to context whenever feature node data changes
|
|
43
45
|
const { setFeatures: setSidebarFeatures } = useSidebarFeaturesContext();
|
|
@@ -86,11 +88,13 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
86
88
|
if (node.type === 'featureNode') {
|
|
87
89
|
const data = node.data as FeatureNodeData;
|
|
88
90
|
if (data.state === 'creating') return;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
guardedNavigate(() => {
|
|
92
|
+
clickSound.play();
|
|
93
|
+
router.push(`/feature/${data.featureId}`);
|
|
94
|
+
});
|
|
91
95
|
}
|
|
92
96
|
},
|
|
93
|
-
[router, clickSound]
|
|
97
|
+
[router, clickSound, guardedNavigate]
|
|
94
98
|
);
|
|
95
99
|
|
|
96
100
|
const handleAddFeature = useCallback(() => {
|
|
@@ -135,19 +139,19 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
135
139
|
if (node?.type === 'repositoryNode') {
|
|
136
140
|
const data = node.data as RepositoryNodeData;
|
|
137
141
|
if (data.id) {
|
|
138
|
-
router.push(`/repository/${data.id}`);
|
|
142
|
+
guardedNavigate(() => router.push(`/repository/${data.id}`));
|
|
139
143
|
}
|
|
140
144
|
}
|
|
141
145
|
},
|
|
142
|
-
[nodes, router]
|
|
146
|
+
[nodes, router, guardedNavigate]
|
|
143
147
|
);
|
|
144
148
|
|
|
145
149
|
// Close all drawers — navigate back to root
|
|
146
150
|
const handleClearDrawers = useCallback(() => {
|
|
147
151
|
if (pathname !== '/') {
|
|
148
|
-
router.push('/');
|
|
152
|
+
guardedNavigate(() => router.push('/'));
|
|
149
153
|
}
|
|
150
|
-
}, [router, pathname]);
|
|
154
|
+
}, [router, pathname, guardedNavigate]);
|
|
151
155
|
|
|
152
156
|
// Listen for global "add repository" events from the top bar button
|
|
153
157
|
useEffect(() => {
|
|
@@ -7,6 +7,7 @@ import type { RepositoryNodeType } from '@/components/common/repository-node';
|
|
|
7
7
|
import type { AddRepositoryNodeType } from '@/components/common/add-repository-node';
|
|
8
8
|
import { layoutWithDagre } from '@/lib/layout-with-dagre';
|
|
9
9
|
import { AgentEventsProvider } from '@/hooks/agent-events-provider';
|
|
10
|
+
import { DrawerCloseGuardProvider } from '@/hooks/drawer-close-guard';
|
|
10
11
|
|
|
11
12
|
const meta: Meta<typeof ControlCenter> = {
|
|
12
13
|
title: 'Features/ControlCenter',
|
|
@@ -18,9 +19,11 @@ const meta: Meta<typeof ControlCenter> = {
|
|
|
18
19
|
decorators: [
|
|
19
20
|
(Story) => (
|
|
20
21
|
<AgentEventsProvider>
|
|
21
|
-
<
|
|
22
|
-
<
|
|
23
|
-
|
|
22
|
+
<DrawerCloseGuardProvider>
|
|
23
|
+
<div style={{ height: '100vh' }}>
|
|
24
|
+
<Story />
|
|
25
|
+
</div>
|
|
26
|
+
</DrawerCloseGuardProvider>
|
|
24
27
|
</AgentEventsProvider>
|
|
25
28
|
),
|
|
26
29
|
],
|
|
@@ -37,7 +37,9 @@ let nextFeatureId = 0;
|
|
|
37
37
|
|
|
38
38
|
export function useControlCenterState(
|
|
39
39
|
initialNodes: CanvasNodeType[],
|
|
40
|
-
initialEdges: Edge[]
|
|
40
|
+
initialEdges: Edge[],
|
|
41
|
+
/** When true, background router.refresh() calls (polling / SSE debounce) are suppressed. */
|
|
42
|
+
isRefreshBlocked?: () => boolean
|
|
41
43
|
): ControlCenterState {
|
|
42
44
|
const router = useRouter();
|
|
43
45
|
const [nodes, setNodes] = useState<CanvasNodeType[]>(initialNodes);
|
|
@@ -202,8 +204,10 @@ export function useControlCenterState(
|
|
|
202
204
|
|
|
203
205
|
// Debounced background reconciliation (3s after last SSE event)
|
|
204
206
|
clearTimeout(reconcileTimerRef.current);
|
|
205
|
-
reconcileTimerRef.current = setTimeout(() =>
|
|
206
|
-
|
|
207
|
+
reconcileTimerRef.current = setTimeout(() => {
|
|
208
|
+
if (!isRefreshBlocked?.()) router.refresh();
|
|
209
|
+
}, 3000);
|
|
210
|
+
}, [events, router, isRefreshBlocked]);
|
|
207
211
|
|
|
208
212
|
// Periodic polling fallback: refresh server data every 5s when any feature
|
|
209
213
|
// is in an active state (running/action-required). This ensures the UI stays
|
|
@@ -219,9 +223,11 @@ export function useControlCenterState(
|
|
|
219
223
|
|
|
220
224
|
if (!hasActiveFeature) return;
|
|
221
225
|
|
|
222
|
-
const interval = setInterval(() =>
|
|
226
|
+
const interval = setInterval(() => {
|
|
227
|
+
if (!isRefreshBlocked?.()) router.refresh();
|
|
228
|
+
}, 5_000);
|
|
223
229
|
return () => clearInterval(interval);
|
|
224
|
-
}, [nodes, router]);
|
|
230
|
+
}, [nodes, router, isRefreshBlocked]);
|
|
225
231
|
|
|
226
232
|
const onNodesChange = useCallback((changes: NodeChange<CanvasNodeType>[]) => {
|
|
227
233
|
setNodes((ns) => applyNodeChanges(changes, ns));
|
package/web/.next/standalone/src/presentation/web/components/layouts/app-shell/app-shell.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { AddRepositoryButton } from '@/components/common/add-repository-node';
|
|
|
8
8
|
import { ThemeToggle } from '@/components/common/theme-toggle';
|
|
9
9
|
import { SoundToggle } from '@/components/common/sound-toggle';
|
|
10
10
|
import { AgentEventsProvider } from '@/hooks/agent-events-provider';
|
|
11
|
+
import { DrawerCloseGuardProvider, useDrawerCloseGuard } from '@/hooks/drawer-close-guard';
|
|
11
12
|
import {
|
|
12
13
|
SidebarFeaturesProvider,
|
|
13
14
|
useSidebarFeaturesContext,
|
|
@@ -21,6 +22,7 @@ interface AppShellProps {
|
|
|
21
22
|
/** Inner shell that consumes the agent-events context for notifications. */
|
|
22
23
|
function AppShellInner({ children }: AppShellProps) {
|
|
23
24
|
const router = useRouter();
|
|
25
|
+
const { guardedNavigate } = useDrawerCloseGuard();
|
|
24
26
|
|
|
25
27
|
// Subscribe to agent lifecycle events and dispatch toast/browser notifications
|
|
26
28
|
useNotifications();
|
|
@@ -28,14 +30,14 @@ function AppShellInner({ children }: AppShellProps) {
|
|
|
28
30
|
const { features } = useSidebarFeaturesContext();
|
|
29
31
|
|
|
30
32
|
const handleNewFeature = useCallback(() => {
|
|
31
|
-
router.push('/create');
|
|
32
|
-
}, [router]);
|
|
33
|
+
guardedNavigate(() => router.push('/create'));
|
|
34
|
+
}, [router, guardedNavigate]);
|
|
33
35
|
|
|
34
36
|
const handleFeatureClick = useCallback(
|
|
35
37
|
(featureId: string) => {
|
|
36
|
-
router.push(`/feature/${featureId}`);
|
|
38
|
+
guardedNavigate(() => router.push(`/feature/${featureId}`));
|
|
37
39
|
},
|
|
38
|
-
[router]
|
|
40
|
+
[router, guardedNavigate]
|
|
39
41
|
);
|
|
40
42
|
|
|
41
43
|
const handleRepositorySelect = useCallback((path: string) => {
|
|
@@ -66,9 +68,11 @@ function AppShellInner({ children }: AppShellProps) {
|
|
|
66
68
|
export function AppShell({ children }: AppShellProps) {
|
|
67
69
|
return (
|
|
68
70
|
<AgentEventsProvider>
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
|
|
71
|
+
<DrawerCloseGuardProvider>
|
|
72
|
+
<SidebarFeaturesProvider>
|
|
73
|
+
<AppShellInner>{children}</AppShellInner>
|
|
74
|
+
</SidebarFeaturesProvider>
|
|
75
|
+
</DrawerCloseGuardProvider>
|
|
72
76
|
</AgentEventsProvider>
|
|
73
77
|
);
|
|
74
78
|
}
|
|
@@ -84,8 +84,8 @@ export const WithDescription: Story = {
|
|
|
84
84
|
</AlertDialogDescription>
|
|
85
85
|
</AlertDialogHeader>
|
|
86
86
|
<AlertDialogFooter>
|
|
87
|
-
<AlertDialogCancel>Keep Editing</AlertDialogCancel>
|
|
88
87
|
<AlertDialogAction variant="destructive">Discard</AlertDialogAction>
|
|
88
|
+
<AlertDialogCancel>Keep Editing</AlertDialogCancel>
|
|
89
89
|
</AlertDialogFooter>
|
|
90
90
|
</AlertDialogContent>
|
|
91
91
|
</AlertDialog>
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useState,
|
|
7
|
+
useCallback,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import {
|
|
13
|
+
AlertDialog,
|
|
14
|
+
AlertDialogAction,
|
|
15
|
+
AlertDialogCancel,
|
|
16
|
+
AlertDialogContent,
|
|
17
|
+
AlertDialogDescription,
|
|
18
|
+
AlertDialogFooter,
|
|
19
|
+
AlertDialogHeader,
|
|
20
|
+
AlertDialogTitle,
|
|
21
|
+
} from '@/components/ui/alert-dialog';
|
|
22
|
+
|
|
23
|
+
/* ---------------------------------------------------------------------------
|
|
24
|
+
* Context
|
|
25
|
+
* ------------------------------------------------------------------------- */
|
|
26
|
+
|
|
27
|
+
interface DrawerCloseGuardContextValue {
|
|
28
|
+
/** Register a drawer's dirty state and reset callback. Pass `null` to unregister. */
|
|
29
|
+
setGuard: (guard: { isDirty: boolean; onReset: () => void } | null) => void;
|
|
30
|
+
/** Navigate only if no dirty drawer is registered; otherwise show confirmation. */
|
|
31
|
+
guardedNavigate: (navigate: () => void) => void;
|
|
32
|
+
/** Returns true when any drawer has unsaved changes. Safe to call from effects/intervals. */
|
|
33
|
+
getIsDirty: () => boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DrawerCloseGuardContext = createContext<DrawerCloseGuardContextValue | null>(null);
|
|
37
|
+
|
|
38
|
+
/* ---------------------------------------------------------------------------
|
|
39
|
+
* Provider — renders the shared confirmation dialog
|
|
40
|
+
* ------------------------------------------------------------------------- */
|
|
41
|
+
|
|
42
|
+
export function DrawerCloseGuardProvider({ children }: { children: ReactNode }) {
|
|
43
|
+
// Use a ref so guard updates (on every keystroke) don't re-render the provider tree.
|
|
44
|
+
const guardRef = useRef<{ isDirty: boolean; onReset: () => void } | null>(null);
|
|
45
|
+
const pendingNavigateRef = useRef<(() => void) | null>(null);
|
|
46
|
+
const [showConfirmation, setShowConfirmation] = useState(false);
|
|
47
|
+
|
|
48
|
+
const setGuard = useCallback((guard: { isDirty: boolean; onReset: () => void } | null) => {
|
|
49
|
+
guardRef.current = guard;
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const guardedNavigate = useCallback((navigate: () => void) => {
|
|
53
|
+
if (guardRef.current?.isDirty) {
|
|
54
|
+
pendingNavigateRef.current = navigate;
|
|
55
|
+
setShowConfirmation(true);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
navigate();
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
const confirmDiscard = useCallback(() => {
|
|
62
|
+
setShowConfirmation(false);
|
|
63
|
+
guardRef.current?.onReset();
|
|
64
|
+
guardRef.current = null;
|
|
65
|
+
pendingNavigateRef.current?.();
|
|
66
|
+
pendingNavigateRef.current = null;
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
const cancelDiscard = useCallback(() => {
|
|
70
|
+
setShowConfirmation(false);
|
|
71
|
+
pendingNavigateRef.current = null;
|
|
72
|
+
}, []);
|
|
73
|
+
|
|
74
|
+
const getIsDirty = useCallback(() => guardRef.current?.isDirty ?? false, []);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<DrawerCloseGuardContext value={{ setGuard, guardedNavigate, getIsDirty }}>
|
|
78
|
+
{children}
|
|
79
|
+
|
|
80
|
+
<AlertDialog open={showConfirmation}>
|
|
81
|
+
<AlertDialogContent>
|
|
82
|
+
<AlertDialogHeader>
|
|
83
|
+
<AlertDialogTitle>Discard unsaved changes?</AlertDialogTitle>
|
|
84
|
+
<AlertDialogDescription>
|
|
85
|
+
You have unsaved changes. Are you sure you want to discard them?
|
|
86
|
+
</AlertDialogDescription>
|
|
87
|
+
</AlertDialogHeader>
|
|
88
|
+
<AlertDialogFooter>
|
|
89
|
+
<AlertDialogAction variant="destructive" onClick={confirmDiscard}>
|
|
90
|
+
Discard
|
|
91
|
+
</AlertDialogAction>
|
|
92
|
+
<AlertDialogCancel onClick={cancelDiscard}>Keep editing</AlertDialogCancel>
|
|
93
|
+
</AlertDialogFooter>
|
|
94
|
+
</AlertDialogContent>
|
|
95
|
+
</AlertDialog>
|
|
96
|
+
</DrawerCloseGuardContext>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* ---------------------------------------------------------------------------
|
|
101
|
+
* Hook — access the guard from any child component
|
|
102
|
+
* ------------------------------------------------------------------------- */
|
|
103
|
+
|
|
104
|
+
export function useDrawerCloseGuard() {
|
|
105
|
+
const ctx = useContext(DrawerCloseGuardContext);
|
|
106
|
+
if (!ctx) throw new Error('useDrawerCloseGuard must be used within DrawerCloseGuardProvider');
|
|
107
|
+
return ctx;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* ---------------------------------------------------------------------------
|
|
111
|
+
* Convenience hook for drawer components
|
|
112
|
+
*
|
|
113
|
+
* Registers dirty state + reset callback with the guard, and returns an
|
|
114
|
+
* `attemptClose` function that goes through the guard before closing.
|
|
115
|
+
* ------------------------------------------------------------------------- */
|
|
116
|
+
|
|
117
|
+
export function useGuardedDrawerClose({
|
|
118
|
+
open,
|
|
119
|
+
isDirty,
|
|
120
|
+
onClose,
|
|
121
|
+
onReset,
|
|
122
|
+
}: {
|
|
123
|
+
open: boolean;
|
|
124
|
+
isDirty: boolean;
|
|
125
|
+
onClose: () => void;
|
|
126
|
+
onReset: () => void;
|
|
127
|
+
}) {
|
|
128
|
+
const { setGuard, guardedNavigate } = useDrawerCloseGuard();
|
|
129
|
+
|
|
130
|
+
// Keep the guard in sync with dirty state. Because setGuard writes to a ref,
|
|
131
|
+
// this doesn't trigger re-renders in the provider.
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (open) {
|
|
134
|
+
setGuard({ isDirty, onReset });
|
|
135
|
+
} else {
|
|
136
|
+
setGuard(null);
|
|
137
|
+
}
|
|
138
|
+
return () => setGuard(null);
|
|
139
|
+
}, [open, isDirty, onReset, setGuard]);
|
|
140
|
+
|
|
141
|
+
const attemptClose = useCallback(() => {
|
|
142
|
+
guardedNavigate(() => {
|
|
143
|
+
onReset();
|
|
144
|
+
onClose();
|
|
145
|
+
});
|
|
146
|
+
}, [guardedNavigate, onClose, onReset]);
|
|
147
|
+
|
|
148
|
+
return { attemptClose };
|
|
149
|
+
}
|
|
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
|
|
|
15
15
|
const hostname = process.env.HOSTNAME || '0.0.0.0'
|
|
16
16
|
|
|
17
17
|
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
|
|
18
|
-
const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.72.
|
|
18
|
+
const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.72.4","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
|
|
19
19
|
|
|
20
20
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
21
21
|
|