@shepai/cli 1.48.0 → 1.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +65 -36
- package/dist/src/presentation/web/app/actions/approve-feature.d.ts +2 -1
- package/dist/src/presentation/web/app/actions/approve-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/approve-feature.js +2 -2
- package/dist/src/presentation/web/app/actions/reject-feature.d.ts +7 -0
- package/dist/src/presentation/web/app/actions/reject-feature.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/reject-feature.js +34 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts +24 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.js +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +12 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-action-bar/index.js +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.d.ts +11 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.js +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.js +18 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/drawer-revision-input/index.js +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +4 -2
- 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 +4 -15
- package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.d.ts +4 -2
- 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 +6 -15
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts +4 -0
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js +24 -3
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/index.js +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.d.ts +9 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.js +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.d.ts +3 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.js +19 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.d.ts +14 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.js +46 -0
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.d.ts +4 -2
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.js +4 -14
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts +4 -0
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.js +24 -6
- 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 +48 -33
- 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/_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_client-reference-manifest.js +1 -1
- package/web/.next/server/app/page/server-reference-manifest.json +41 -26
- package/web/.next/server/app/page.js +2 -1
- package/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.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]__2d1a8e37._.js +9 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js.map +1 -0
- 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 +42 -27
- 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/_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_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +41 -26
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +2 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +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/[root-of-the-server]__03a0dba7._.js +4 -4
- 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]__2d1a8e37._.js +9 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d8fbe735._.js +3 -0
- 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 +42 -27
- package/web/.next/standalone/src/presentation/web/app/actions/approve-feature.ts +4 -2
- package/web/.next/standalone/src/presentation/web/app/actions/reject-feature.ts +52 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar-config.ts +24 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +64 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/index.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input-config.ts +10 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/drawer-revision-input.tsx +41 -0
- package/web/.next/standalone/src/presentation/web/components/common/drawer-revision-input/index.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-config.ts +4 -2
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.stories.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +24 -53
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire-config.ts +4 -2
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx +36 -8
- package/web/.next/standalone/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.tsx +16 -47
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/index.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.ts +8 -0
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.tsx +63 -0
- package/web/.next/standalone/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.tsx +78 -0
- package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.ts +4 -2
- package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.tsx +27 -6
- package/web/.next/standalone/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx +14 -42
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +94 -49
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/191ca1529c9868dd.js +10 -0
- package/web/.next/static/chunks/59b8bd47023e0249.css +2 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +0 -9
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +0 -9
- package/web/.next/static/chunks/66378a6c055c4e67.js +0 -10
- package/web/.next/static/chunks/8668962d3e682263.css +0 -2
- /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → UT60KjU8SOYIjqeqo2WT-}/_buildManifest.js +0 -0
- /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → UT60KjU8SOYIjqeqo2WT-}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{1kZFDMQ0i-Y8dy1KkHlzv → UT60KjU8SOYIjqeqo2WT-}/_ssgManifest.js +0 -0
package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.d.ts
CHANGED
|
@@ -23,4 +23,8 @@ export declare const InDrawerWithSelections: DrawerStory;
|
|
|
23
23
|
export declare const WithDeleteButton: DrawerStory;
|
|
24
24
|
/** Drawer with delete in progress (button disabled). */
|
|
25
25
|
export declare const DeletingState: DrawerStory;
|
|
26
|
+
/** All answered with reject button visible on last step. */
|
|
27
|
+
export declare const WithRejectButton: Story;
|
|
28
|
+
/** Rejecting state — reject button disabled with spinner while reject action is in flight. */
|
|
29
|
+
export declare const RejectingState: Story;
|
|
26
30
|
//# sourceMappingURL=prd-questionnaire.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prd-questionnaire.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"prd-questionnaire.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAiKpE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAkBvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAU/C,sFAAsF;AACtF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,cAAc,EAAE,KAW5B,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,WAAW,EAAE,KAczB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,EAAE,KAStB,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,KA8BzB,CAAC;AAIF,KAAK,WAAW,GAAG,QAAQ,CAAC,OAAO,sBAAsB,CAAC,CAAC;AA0C3D,8DAA8D;AAC9D,eAAO,MAAM,QAAQ,EAAE,WAWtB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,WAepC,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,EAAE,WAW9B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,WAY3B,CAAC;AAaF,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,EAAE,KAQ9B,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAC"}
|
package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.stories.js
CHANGED
|
@@ -140,7 +140,7 @@ const mockFinalAction = {
|
|
|
140
140
|
/* ─── Interactive wrapper for stories ─── */
|
|
141
141
|
function InteractiveQuestionnaire({ selections: initialSelections = {}, ...props }) {
|
|
142
142
|
const [selections, setSelections] = useState(initialSelections);
|
|
143
|
-
return (_jsx(PrdQuestionnaire, { ...props, selections: selections, onSelect: (qId, optId) => setSelections((prev) => ({ ...prev, [qId]: optId })),
|
|
143
|
+
return (_jsx(PrdQuestionnaire, { ...props, selections: selections, onSelect: (qId, optId) => setSelections((prev) => ({ ...prev, [qId]: optId })), onApprove: fn().mockName('onApprove') }));
|
|
144
144
|
}
|
|
145
145
|
/* ─── Standalone PrdQuestionnaire ─── */
|
|
146
146
|
const meta = {
|
|
@@ -152,7 +152,6 @@ const meta = {
|
|
|
152
152
|
},
|
|
153
153
|
argTypes: {
|
|
154
154
|
onSelect: { action: 'onSelect' },
|
|
155
|
-
onRefine: { action: 'onRefine' },
|
|
156
155
|
onApprove: { action: 'onApprove' },
|
|
157
156
|
},
|
|
158
157
|
decorators: [
|
|
@@ -239,7 +238,7 @@ const drawerMeta = {
|
|
|
239
238
|
function DrawerTemplate({ selections: initialSelections = {}, ...props }) {
|
|
240
239
|
const [open, setOpen] = useState(true);
|
|
241
240
|
const [selections, setSelections] = useState(initialSelections);
|
|
242
|
-
return (_jsxs("div", { style: { height: '100vh', background: '#f8fafc', padding: '2rem' }, children: [_jsx("button", { type: "button", onClick: () => setOpen(true), style: { padding: '8px 16px', border: '1px solid #ccc', borderRadius: '6px' }, children: "Open Drawer" }), _jsx(PrdQuestionnaireDrawer, { ...props, open: open, onClose: () => setOpen(false), selections: selections, onSelect: (qId, optId) => setSelections((prev) => ({ ...prev, [qId]: optId })),
|
|
241
|
+
return (_jsxs("div", { style: { height: '100vh', background: '#f8fafc', padding: '2rem' }, children: [_jsx("button", { type: "button", onClick: () => setOpen(true), style: { padding: '8px 16px', border: '1px solid #ccc', borderRadius: '6px' }, children: "Open Drawer" }), _jsx(PrdQuestionnaireDrawer, { ...props, open: open, onClose: () => setOpen(false), selections: selections, onSelect: (qId, optId) => setSelections((prev) => ({ ...prev, [qId]: optId })), onApprove: fn().mockName('onApprove') })] }));
|
|
243
242
|
}
|
|
244
243
|
/** Drawer with stepper — navigate questions one at a time. */
|
|
245
244
|
export const InDrawer = {
|
|
@@ -265,3 +264,25 @@ export const DeletingState = {
|
|
|
265
264
|
...drawerMeta,
|
|
266
265
|
render: () => (_jsx(DrawerTemplate, { featureName: "User Authentication Flow", featureId: "FEAT-042", lifecycleLabel: "Requirements", data: mockData, onDelete: fn().mockName('onDelete'), isDeleting: true })),
|
|
267
266
|
};
|
|
267
|
+
/* ─── Reject Variants ─── */
|
|
268
|
+
const allAnsweredSelections = {
|
|
269
|
+
problem: 'user_pain',
|
|
270
|
+
priority: 'p1',
|
|
271
|
+
success: 'adoption',
|
|
272
|
+
timeline: 'sprint',
|
|
273
|
+
scope: 'mvp',
|
|
274
|
+
stakeholders: 'end_users',
|
|
275
|
+
};
|
|
276
|
+
/** All answered with reject button visible on last step. */
|
|
277
|
+
export const WithRejectButton = {
|
|
278
|
+
render: () => (_jsx(InteractiveQuestionnaire, { data: mockData, selections: allAnsweredSelections, onReject: fn().mockName('onReject') })),
|
|
279
|
+
};
|
|
280
|
+
/** Rejecting state — reject button disabled with spinner while reject action is in flight. */
|
|
281
|
+
export const RejectingState = {
|
|
282
|
+
args: {
|
|
283
|
+
data: mockData,
|
|
284
|
+
selections: allAnsweredSelections,
|
|
285
|
+
onReject: fn().mockName('onReject'),
|
|
286
|
+
isRejecting: true,
|
|
287
|
+
},
|
|
288
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/reject-feedback-dialog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,YAAY,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RejectFeedbackDialog } from './reject-feedback-dialog.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface RejectFeedbackDialogProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
onOpenChange: (open: boolean) => void;
|
|
4
|
+
onConfirm: (feedback: string) => void;
|
|
5
|
+
isSubmitting: boolean;
|
|
6
|
+
title?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=reject-feedback-dialog-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reject-feedback-dialog-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RejectFeedbackDialogProps } from './reject-feedback-dialog-config.js';
|
|
2
|
+
export declare function RejectFeedbackDialog({ open, onOpenChange, onConfirm, isSubmitting, title, description, }: RejectFeedbackDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
//# sourceMappingURL=reject-feedback-dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reject-feedback-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAMjF,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,KAAqB,EACrB,WAAiC,GAClC,EAAE,yBAAyB,2CAiD3B"}
|
package/dist/src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Loader2 } from 'lucide-react';
|
|
5
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
|
|
6
|
+
import { Textarea } from '../../ui/textarea.js';
|
|
7
|
+
const DEFAULT_TITLE = 'Reject Requirements';
|
|
8
|
+
const DEFAULT_DESCRIPTION = 'Provide feedback for the agent to address in the next iteration. Feedback is required.';
|
|
9
|
+
export function RejectFeedbackDialog({ open, onOpenChange, onConfirm, isSubmitting, title = DEFAULT_TITLE, description = DEFAULT_DESCRIPTION, }) {
|
|
10
|
+
const [feedback, setFeedback] = useState('');
|
|
11
|
+
// Reset feedback when dialog opens
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (open) {
|
|
14
|
+
setFeedback('');
|
|
15
|
+
}
|
|
16
|
+
}, [open]);
|
|
17
|
+
const isFeedbackEmpty = feedback.trim().length === 0;
|
|
18
|
+
return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: title }), _jsx(AlertDialogDescription, { children: description })] }), _jsx(Textarea, { "aria-label": "Rejection feedback", placeholder: "Describe what needs to change...", value: feedback, onChange: (e) => setFeedback(e.target.value), disabled: isSubmitting, rows: 4 }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isSubmitting, onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isFeedbackEmpty || isSubmitting, onClick: () => onConfirm(feedback.trim()), children: isSubmitting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Rejecting\u2026"] })) : ('Confirm Reject') })] })] }) }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { RejectFeedbackDialog } from './reject-feedback-dialog.js';
|
|
3
|
+
declare const meta: Meta<typeof RejectFeedbackDialog>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof RejectFeedbackDialog>;
|
|
6
|
+
/** Default — dialog open with empty feedback; confirm button disabled. */
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
/** With feedback entered — confirm button enabled. */
|
|
9
|
+
export declare const WithFeedback: Story;
|
|
10
|
+
/** Submitting state — spinner shown, buttons disabled. */
|
|
11
|
+
export declare const Submitting: Story;
|
|
12
|
+
/** Custom title and description for tech decisions context. */
|
|
13
|
+
export declare const CustomTitle: Story;
|
|
14
|
+
//# sourceMappingURL=reject-feedback-dialog.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reject-feedback-dialog.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/reject-feedback-dialog/reject-feedback-dialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,oBAAoB,CAa3C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEnD,0EAA0E;AAC1E,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,sDAAsD;AACtD,eAAO,MAAM,YAAY,EAAE,KAoB1B,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,KAMzB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { fn } from '@storybook/test';
|
|
2
|
+
import { RejectFeedbackDialog } from './reject-feedback-dialog.js';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Composed/RejectFeedbackDialog',
|
|
5
|
+
component: RejectFeedbackDialog,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
open: true,
|
|
12
|
+
onOpenChange: fn().mockName('onOpenChange'),
|
|
13
|
+
onConfirm: fn().mockName('onConfirm'),
|
|
14
|
+
isSubmitting: false,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export default meta;
|
|
18
|
+
/** Default — dialog open with empty feedback; confirm button disabled. */
|
|
19
|
+
export const Default = {};
|
|
20
|
+
/** With feedback entered — confirm button enabled. */
|
|
21
|
+
export const WithFeedback = {
|
|
22
|
+
play: async ({ canvasElement }) => {
|
|
23
|
+
// Type feedback into the textarea to show enabled state
|
|
24
|
+
const textarea = canvasElement.ownerDocument.querySelector('textarea[aria-label="Rejection feedback"]');
|
|
25
|
+
if (textarea) {
|
|
26
|
+
// Simulate React-compatible input
|
|
27
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value')?.set;
|
|
28
|
+
nativeInputValueSetter?.call(textarea, 'The requirements are missing error handling for edge cases. Please add validation for empty inputs.');
|
|
29
|
+
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
30
|
+
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
/** Submitting state — spinner shown, buttons disabled. */
|
|
35
|
+
export const Submitting = {
|
|
36
|
+
args: {
|
|
37
|
+
isSubmitting: true,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
/** Custom title and description for tech decisions context. */
|
|
41
|
+
export const CustomTitle = {
|
|
42
|
+
args: {
|
|
43
|
+
title: 'Reject Plan',
|
|
44
|
+
description: 'Provide feedback on the technical plan for the agent to revise. Be specific about which decisions need changes.',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -9,12 +9,14 @@ export interface TechDecisionsReviewData {
|
|
|
9
9
|
export interface TechDecisionsReviewProps {
|
|
10
10
|
/** Tech decisions data from the research artifact */
|
|
11
11
|
data: TechDecisionsReviewData;
|
|
12
|
-
/** Chat refinement callback — sends user feedback to the agent */
|
|
13
|
-
onRefine: (text: string) => void;
|
|
14
12
|
/** Approve plan callback */
|
|
15
13
|
onApprove: () => void;
|
|
14
|
+
/** Reject plan callback — opens feedback dialog when provided; also used for inline text rejection */
|
|
15
|
+
onReject?: (feedback: string) => void;
|
|
16
16
|
/** Controls disabled state during loading */
|
|
17
17
|
isProcessing?: boolean;
|
|
18
|
+
/** Whether a reject operation is in flight */
|
|
19
|
+
isRejecting?: boolean;
|
|
18
20
|
}
|
|
19
21
|
export interface TechDecisionsDrawerProps extends TechDecisionsReviewProps {
|
|
20
22
|
/** Whether the drawer is open */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tech-decisions-review-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEzE,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,qDAAqD;IACrD,IAAI,EAAE,uBAAuB,CAAC;IAC9B,
|
|
1
|
+
{"version":3,"file":"tech-decisions-review-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/tech-decisions-review/tech-decisions-review-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEzE,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,qDAAqD;IACrD,IAAI,EAAE,uBAAuB,CAAC;IAC9B,4BAA4B;IAC5B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,sGAAsG;IACtG,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,6CAA6C;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,wBAAyB,SAAQ,wBAAwB;IACxE,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
|
package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { TechDecisionsReviewProps } from './tech-decisions-review-config.js';
|
|
2
|
-
export declare function TechDecisionsReview({ data,
|
|
2
|
+
export declare function TechDecisionsReview({ data, onApprove, onReject, isProcessing, isRejecting, }: TechDecisionsReviewProps): import("react/jsx-runtime").JSX.Element | null;
|
|
3
3
|
//# sourceMappingURL=tech-decisions-review.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tech-decisions-review.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tech-decisions-review.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,wBAAwB,EAAgB,MAAM,gCAAgC,CAAC;AAoG7F,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,YAAoB,EACpB,WAAmB,GACpB,EAAE,wBAAwB,kDA6C1B"}
|
package/dist/src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import Markdown from 'react-markdown';
|
|
5
|
-
import { Check, ChevronRight, GitCompareArrows, Layers
|
|
5
|
+
import { Check, ChevronRight, GitCompareArrows, Layers } from 'lucide-react';
|
|
6
6
|
import { Badge } from '../../ui/badge.js';
|
|
7
|
-
import {
|
|
8
|
-
import { Input } from '../../ui/input.js';
|
|
7
|
+
import { DrawerActionBar } from '../../common/drawer-action-bar/index.js';
|
|
9
8
|
const markdownComponents = {
|
|
10
9
|
p: ({ children }) => (_jsx("p", { className: "text-muted-foreground mb-2 text-xs leading-relaxed last:mb-0", children: children })),
|
|
11
10
|
strong: ({ children }) => _jsx("strong", { className: "text-foreground font-semibold", children: children }),
|
|
@@ -22,18 +21,9 @@ function DecisionCard({ decision, index }) {
|
|
|
22
21
|
return (_jsxs("div", { className: "border-border rounded-lg border", children: [_jsxs("div", { className: "space-y-3 px-4 py-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("span", { className: "bg-primary text-primary-foreground flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-bold", children: index + 1 }), _jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "text-foreground text-sm leading-tight font-semibold", children: decision.title }), _jsx("p", { className: "text-muted-foreground mt-0.5 text-xs", children: decision.chosen })] })] }), 'decisionName' in decision &&
|
|
23
22
|
decision.decisionName ? (_jsx(Badge, { variant: "secondary", className: "bg-primary/10 text-primary shrink-0", children: decision.decisionName })) : null] }), decision.rationale ? (_jsx(Markdown, { components: markdownComponents, children: decision.rationale })) : null] }), decision.rejected.length > 0 ? (_jsxs("div", { className: "border-border border-t", children: [_jsxs("button", { type: "button", onClick: () => setAlternativesOpen((prev) => !prev), className: "text-muted-foreground hover:bg-muted/50 flex w-full items-center gap-1.5 px-4 py-3 text-xs font-medium transition-colors", children: [_jsx(ChevronRight, { className: `h-3.5 w-3.5 transition-transform ${alternativesOpen ? 'rotate-90' : ''}` }), _jsx(Layers, { className: "h-3.5 w-3.5" }), "Other Options Considered (", decision.rejected.length, ")"] }), alternativesOpen ? (_jsx("div", { className: "space-y-1.5 px-4 pb-3", children: decision.rejected.map((alt) => (_jsx("div", { className: "bg-primary/5 rounded-md px-3 py-2", children: _jsx("span", { className: "text-foreground text-xs", children: alt }) }, alt))) })) : null] })) : null] }));
|
|
24
23
|
}
|
|
25
|
-
export function TechDecisionsReview({ data,
|
|
24
|
+
export function TechDecisionsReview({ data, onApprove, onReject, isProcessing = false, isRejecting = false, }) {
|
|
26
25
|
const { summary, decisions } = data;
|
|
27
|
-
const [chatInput, setChatInput] = useState('');
|
|
28
|
-
function handleSubmit(e) {
|
|
29
|
-
e.preventDefault();
|
|
30
|
-
const text = chatInput.trim();
|
|
31
|
-
if (!text)
|
|
32
|
-
return;
|
|
33
|
-
onRefine(text);
|
|
34
|
-
setChatInput('');
|
|
35
|
-
}
|
|
36
26
|
if (decisions.length === 0)
|
|
37
27
|
return null;
|
|
38
|
-
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-foreground text-sm font-bold", children: "Technical Implementation Plan Review" }), summary ? (_jsx("p", { className: "text-muted-foreground mt-1 text-xs leading-relaxed", children: summary })) : null] })] }), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx(GitCompareArrows, { className: "text-primary h-4 w-4" }), _jsx("h3", { className: "text-foreground text-sm font-bold", children: "Technical Decisions" })] }), decisions.map((decision, i) => (_jsx(DecisionCard, { decision: decision, index: i }, decision.title)))] }),
|
|
28
|
+
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-foreground text-sm font-bold", children: "Technical Implementation Plan Review" }), summary ? (_jsx("p", { className: "text-muted-foreground mt-1 text-xs leading-relaxed", children: summary })) : null] })] }), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsx(GitCompareArrows, { className: "text-primary h-4 w-4" }), _jsx("h3", { className: "text-foreground text-sm font-bold", children: "Technical Decisions" })] }), decisions.map((decision, i) => (_jsx(DecisionCard, { decision: decision, index: i }, decision.title)))] }), _jsx(DrawerActionBar, { onReject: onReject, onApprove: onApprove, approveLabel: "Approve Plan", approveIcon: _jsx(Check, { className: "mr-1.5 h-4 w-4" }), revisionPlaceholder: "Ask AI to revise the plan...", rejectDialogTitle: "Reject Plan", isProcessing: isProcessing, isRejecting: isRejecting })] }));
|
|
39
29
|
}
|
|
@@ -19,4 +19,8 @@ export declare const InDrawer: DrawerStory;
|
|
|
19
19
|
export declare const WithDeleteButton: DrawerStory;
|
|
20
20
|
/** Drawer with delete in progress (button disabled). */
|
|
21
21
|
export declare const DeletingState: DrawerStory;
|
|
22
|
+
/** With reject button visible next to approve. */
|
|
23
|
+
export declare const WithRejectButton: Story;
|
|
24
|
+
/** Rejecting state — reject button disabled while reject action is in flight. */
|
|
25
|
+
export declare const RejectingState: Story;
|
|
22
26
|
//# sourceMappingURL=tech-decisions-review.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tech-decisions-review.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AA0C9D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAc1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElD,oDAAoD;AACpD,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,uBAAuB;AACvB,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAEF,8BAA8B;AAC9B,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAIF,KAAK,WAAW,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA8BxD,uCAAuC;AACvC,eAAO,MAAM,QAAQ,EAAE,WAWtB,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,EAAE,WAY9B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,WAa3B,CAAC"}
|
|
1
|
+
{"version":3,"file":"tech-decisions-review.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/tech-decisions-review/tech-decisions-review.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AA0C9D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAc1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElD,oDAAoD;AACpD,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,uBAAuB;AACvB,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAEF,8BAA8B;AAC9B,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAIF,KAAK,WAAW,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA8BxD,uCAAuC;AACvC,eAAO,MAAM,QAAQ,EAAE,WAWtB,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,EAAE,WAY9B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,WAa3B,CAAC;AAIF,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,EAAE,KAM9B,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,cAAc,EAAE,KAO5B,CAAC"}
|
|
@@ -51,7 +51,7 @@ export default meta;
|
|
|
51
51
|
export const Default = {
|
|
52
52
|
args: {
|
|
53
53
|
data: mockData,
|
|
54
|
-
|
|
54
|
+
onReject: fn().mockName('onReject'),
|
|
55
55
|
onApprove: fn().mockName('onApprove'),
|
|
56
56
|
},
|
|
57
57
|
};
|
|
@@ -67,7 +67,7 @@ export const Processing = {
|
|
|
67
67
|
export const SingleDecision = {
|
|
68
68
|
args: {
|
|
69
69
|
data: { ...mockData, decisions: [mockData.decisions[0]] },
|
|
70
|
-
|
|
70
|
+
onReject: fn().mockName('onReject'),
|
|
71
71
|
onApprove: fn().mockName('onApprove'),
|
|
72
72
|
},
|
|
73
73
|
};
|
|
@@ -75,7 +75,7 @@ export const SingleDecision = {
|
|
|
75
75
|
export const NoTechnologies = {
|
|
76
76
|
args: {
|
|
77
77
|
data: { ...mockData, technologies: [] },
|
|
78
|
-
|
|
78
|
+
onReject: fn().mockName('onReject'),
|
|
79
79
|
onApprove: fn().mockName('onApprove'),
|
|
80
80
|
},
|
|
81
81
|
};
|
|
@@ -94,15 +94,33 @@ function DrawerTemplate(props) {
|
|
|
94
94
|
/** Drawer with tech decisions list. */
|
|
95
95
|
export const InDrawer = {
|
|
96
96
|
...drawerMeta,
|
|
97
|
-
render: () => (_jsx(DrawerTemplate, { featureName: "Agent Executor Abstraction", featureId: "FEAT-099", data: mockData,
|
|
97
|
+
render: () => (_jsx(DrawerTemplate, { featureName: "Agent Executor Abstraction", featureId: "FEAT-099", data: mockData, onApprove: fn().mockName('onApprove'), onReject: fn().mockName('onReject') })),
|
|
98
98
|
};
|
|
99
99
|
/** Drawer with delete button visible. */
|
|
100
100
|
export const WithDeleteButton = {
|
|
101
101
|
...drawerMeta,
|
|
102
|
-
render: () => (_jsx(DrawerTemplate, { featureName: "Agent Executor Abstraction", featureId: "FEAT-099", data: mockData,
|
|
102
|
+
render: () => (_jsx(DrawerTemplate, { featureName: "Agent Executor Abstraction", featureId: "FEAT-099", data: mockData, onApprove: fn().mockName('onApprove'), onReject: fn().mockName('onReject'), onDelete: fn().mockName('onDelete') })),
|
|
103
103
|
};
|
|
104
104
|
/** Drawer with delete in progress (button disabled). */
|
|
105
105
|
export const DeletingState = {
|
|
106
106
|
...drawerMeta,
|
|
107
|
-
render: () => (_jsx(DrawerTemplate, { featureName: "Agent Executor Abstraction", featureId: "FEAT-099", data: mockData,
|
|
107
|
+
render: () => (_jsx(DrawerTemplate, { featureName: "Agent Executor Abstraction", featureId: "FEAT-099", data: mockData, onApprove: fn().mockName('onApprove'), onReject: fn().mockName('onReject'), onDelete: fn().mockName('onDelete'), isDeleting: true })),
|
|
108
|
+
};
|
|
109
|
+
/* ─── Reject Variants ─── */
|
|
110
|
+
/** With reject button visible next to approve. */
|
|
111
|
+
export const WithRejectButton = {
|
|
112
|
+
args: {
|
|
113
|
+
data: mockData,
|
|
114
|
+
onApprove: fn().mockName('onApprove'),
|
|
115
|
+
onReject: fn().mockName('onReject'),
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
/** Rejecting state — reject button disabled while reject action is in flight. */
|
|
119
|
+
export const RejectingState = {
|
|
120
|
+
args: {
|
|
121
|
+
data: mockData,
|
|
122
|
+
onApprove: fn().mockName('onApprove'),
|
|
123
|
+
onReject: fn().mockName('onReject'),
|
|
124
|
+
isRejecting: true,
|
|
125
|
+
},
|
|
108
126
|
};
|
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":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,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":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgB1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAU5E,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,2CAiYzF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { useCallback, useEffect, useState } from 'react';
|
|
4
4
|
import { toast } from 'sonner';
|
|
5
5
|
import { approveFeature } from '../../../app/actions/approve-feature.js';
|
|
6
|
+
import { rejectFeature } from '../../../app/actions/reject-feature.js';
|
|
6
7
|
import { getFeatureArtifact } from '../../../app/actions/get-feature-artifact.js';
|
|
7
8
|
import { getResearchArtifact } from '../../../app/actions/get-research-artifact.js';
|
|
8
9
|
import { getWorkflowDefaults } from '../../../app/actions/get-workflow-defaults.js';
|
|
@@ -28,9 +29,10 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
28
29
|
}, []);
|
|
29
30
|
// PRD questionnaire drawer state
|
|
30
31
|
const [prdSelections, setPrdSelections] = useState({});
|
|
31
|
-
const [isPrdProcessing, setIsPrdProcessing] = useState(false);
|
|
32
32
|
const [questionnaireData, setQuestionnaireData] = useState(null);
|
|
33
33
|
const [isLoadingQuestionnaire, setIsLoadingQuestionnaire] = useState(false);
|
|
34
|
+
// Reject state (shared by both drawers)
|
|
35
|
+
const [isRejecting, setIsRejecting] = useState(false);
|
|
34
36
|
// Tech decisions drawer state
|
|
35
37
|
const [techDecisionsData, setTechDecisionsData] = useState(null);
|
|
36
38
|
const [isLoadingTechDecisions, setIsLoadingTechDecisions] = useState(false);
|
|
@@ -43,18 +45,26 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
43
45
|
const handlePrdSelect = useCallback((questionId, optionId) => {
|
|
44
46
|
setPrdSelections((prev) => ({ ...prev, [questionId]: optionId }));
|
|
45
47
|
}, []);
|
|
46
|
-
const handlePrdRefine = useCallback(async (_text) => {
|
|
47
|
-
setIsPrdProcessing(true);
|
|
48
|
-
// TODO: Call API to refine requirements
|
|
49
|
-
// For now simulate a delay
|
|
50
|
-
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
51
|
-
setIsPrdProcessing(false);
|
|
52
|
-
}, []);
|
|
53
48
|
const handlePrdApprove = useCallback(async (_actionId) => {
|
|
54
49
|
const featureId = selectedNode?.featureId;
|
|
55
50
|
if (!featureId)
|
|
56
51
|
return;
|
|
57
|
-
|
|
52
|
+
let payload;
|
|
53
|
+
if (questionnaireData) {
|
|
54
|
+
const changedSelections = [];
|
|
55
|
+
for (const [questionId, optionId] of Object.entries(prdSelections)) {
|
|
56
|
+
const question = questionnaireData.questions.find((q) => q.id === questionId);
|
|
57
|
+
const option = question?.options.find((o) => o.id === optionId);
|
|
58
|
+
if (question && option) {
|
|
59
|
+
changedSelections.push({
|
|
60
|
+
questionId: question.question,
|
|
61
|
+
selectedOption: option.label,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
payload = { approved: true, changedSelections };
|
|
66
|
+
}
|
|
67
|
+
const result = await approveFeature(featureId, payload);
|
|
58
68
|
if (!result.approved) {
|
|
59
69
|
toast.error(result.error ?? 'Failed to approve requirements');
|
|
60
70
|
return;
|
|
@@ -62,43 +72,48 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
62
72
|
toast.success('Requirements approved — agent resuming');
|
|
63
73
|
clearSelection();
|
|
64
74
|
setPrdSelections({});
|
|
65
|
-
}, [selectedNode?.featureId, clearSelection]);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// TODO: Call API to refine tech decisions
|
|
69
|
-
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
70
|
-
setIsLoadingTechDecisions(false);
|
|
71
|
-
}, []);
|
|
72
|
-
const handleTechDecisionsApprove = useCallback(async () => {
|
|
75
|
+
}, [selectedNode?.featureId, clearSelection, questionnaireData, prdSelections]);
|
|
76
|
+
// Shared reject handler — all drawers use the same rejectFeature flow
|
|
77
|
+
const handleReject = useCallback(async (feedback, label, onDone) => {
|
|
73
78
|
const featureId = selectedNode?.featureId;
|
|
74
79
|
if (!featureId)
|
|
75
80
|
return;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
setIsRejecting(true);
|
|
82
|
+
try {
|
|
83
|
+
const result = await rejectFeature(featureId, feedback);
|
|
84
|
+
if (!result.rejected) {
|
|
85
|
+
toast.error(result.error ?? `Failed to reject ${label.toLowerCase()}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
toast.success(`${label} rejected — agent re-iterating (iteration ${result.iteration})`);
|
|
89
|
+
if (result.iterationWarning) {
|
|
90
|
+
toast.warning(`Iteration ${result.iteration} — consider approving or adjusting feedback to avoid excessive iterations`);
|
|
91
|
+
}
|
|
92
|
+
clearSelection();
|
|
93
|
+
onDone?.();
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
setIsRejecting(false);
|
|
80
97
|
}
|
|
81
|
-
toast.success('Plan approved — agent resuming');
|
|
82
|
-
clearSelection();
|
|
83
98
|
}, [selectedNode?.featureId, clearSelection]);
|
|
84
|
-
const
|
|
99
|
+
const handlePrdReject = useCallback((feedback) => handleReject(feedback, 'Requirements', () => setPrdSelections({})), [handleReject]);
|
|
100
|
+
const handleTechDecisionsReject = useCallback((feedback) => handleReject(feedback, 'Plan'), [handleReject]);
|
|
101
|
+
const handleMergeReject = useCallback((feedback) => handleReject(feedback, 'Merge'), [handleReject]);
|
|
102
|
+
// Shared approve handler — tech decisions and merge use identical approve flows
|
|
103
|
+
const handleSimpleApprove = useCallback(async (label) => {
|
|
85
104
|
const featureId = selectedNode?.featureId;
|
|
86
105
|
if (!featureId)
|
|
87
106
|
return;
|
|
88
107
|
const result = await approveFeature(featureId);
|
|
89
108
|
if (!result.approved) {
|
|
90
|
-
toast.error(result.error ??
|
|
109
|
+
toast.error(result.error ?? `Failed to approve ${label.toLowerCase()}`);
|
|
91
110
|
return;
|
|
92
111
|
}
|
|
93
|
-
toast.success(
|
|
112
|
+
toast.success(`${label} approved — agent resuming`);
|
|
94
113
|
clearSelection();
|
|
95
114
|
}, [selectedNode?.featureId, clearSelection]);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
// TODO: Call API to refine merge
|
|
99
|
-
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
100
|
-
setIsLoadingMergeReview(false);
|
|
101
|
-
}, []);
|
|
115
|
+
const handleTechDecisionsApprove = useCallback(() => handleSimpleApprove('Plan'), [handleSimpleApprove]);
|
|
116
|
+
const handleMergeApprove = useCallback(() => handleSimpleApprove('Merge'), [handleSimpleApprove]);
|
|
102
117
|
// Fetch questionnaire data and reset selections when a different feature is selected
|
|
103
118
|
const prdFeatureId = showPrdDrawer ? selectedNode?.featureId : null;
|
|
104
119
|
useEffect(() => {
|
|
@@ -212,5 +227,5 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
212
227
|
if (!hasRepositories) {
|
|
213
228
|
return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }), _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, repositoryPath: pendingRepositoryPath, workflowDefaults: workflowDefaults })] }));
|
|
214
229
|
}
|
|
215
|
-
return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: clearSelection, onRepositoryAdd: handleAddFeatureToRepo, onRepositoryDelete: handleDeleteRepository, onRepositorySelect: handleAddRepository, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: showPrdDrawer || showTechDecisionsDrawer || showMergeReviewDrawer ? null : selectedNode, onClose: clearSelection, onDelete: handleDeleteFeature, isDeleting: isDeleting }), questionnaireData ? (_jsx(PrdQuestionnaireDrawer, { open: showPrdDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureDescription: selectedNode?.description, featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: questionnaireData, selections: prdSelections, onSelect: handlePrdSelect,
|
|
230
|
+
return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: clearSelection, onRepositoryAdd: handleAddFeatureToRepo, onRepositoryDelete: handleDeleteRepository, onRepositorySelect: handleAddRepository, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: showPrdDrawer || showTechDecisionsDrawer || showMergeReviewDrawer ? null : selectedNode, onClose: clearSelection, onDelete: handleDeleteFeature, isDeleting: isDeleting }), questionnaireData ? (_jsx(PrdQuestionnaireDrawer, { open: showPrdDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureDescription: selectedNode?.description, featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: questionnaireData, selections: prdSelections, onSelect: handlePrdSelect, onApprove: handlePrdApprove, onReject: handlePrdReject, isRejecting: isRejecting, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingQuestionnaire })) : null, techDecisionsData ? (_jsx(TechDecisionsDrawer, { open: showTechDecisionsDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: techDecisionsData, onApprove: handleTechDecisionsApprove, onReject: handleTechDecisionsReject, isRejecting: isRejecting, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingTechDecisions })) : null, mergeReviewData ? (_jsx(MergeReviewDrawer, { open: showMergeReviewDrawer, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: mergeReviewData, onApprove: handleMergeApprove, onReject: handleMergeReject, isRejecting: isRejecting, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingMergeReview })) : null, _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, repositoryPath: pendingRepositoryPath, workflowDefaults: workflowDefaults })] }));
|
|
216
231
|
}
|