diff --git a/final-WL-0MNX4D4G8009XZNJ-estimate.json b/final-WL-0MNX4D4G8009XZNJ-estimate.json new file mode 100644 index 0000000..88fddd3 --- /dev/null +++ b/final-WL-0MNX4D4G8009XZNJ-estimate.json @@ -0,0 +1,26 @@ +{ + "issue": "WL-0MNX4D4G8009XZNJ", + "items": [ + {"id": "WL-0MO5NZL99006LFPH", "title": "Private dialog widget helpers", "o": 1, "m": 2, "p": 4, "probability": 2, "impact": 2}, + {"id": "WL-0MO5NZQLW0090TKN", "title": "Replace inline widget constructions", "o": 4, "m": 8, "p": 12, "probability": 3, "impact": 3}, + {"id": "WL-0MO5NZVFF000P7JP", "title": "Dialog integration parity tests", "o": 1, "m": 2, "p": 3, "probability": 2, "impact": 2}, + {"id": "WL-0MO5O00UN001OD9J", "title": "Manual smoke-run & PR checklist", "o": 0.5, "m": 1, "p": 2, "probability": 1, "impact": 1}, + {"id": "WL-0MO5O06K10079BS7", "title": "Extract dialog helpers to shared module", "o": 0.5, "m": 1, "p": 2, "probability": 2, "impact": 2}, + {"id": "WL-0MO5O0ACM0069GGF", "title": "Destroy & lifecycle cleanup", "o": 1, "m": 2, "p": 3, "probability": 2, "impact": 2} + ], + "o": 8, + "m": 16, + "p": 26, + "expected_effort_without_overheads": 16.333333333333332, + "overheads": {"coordination": 2, "review": 2, "testing": 2, "risk_buffer": 2}, + "expected_effort_with_overheads": 24.333333333333332, + "range_with_overheads": {"min": 21.333333333333332, "max": 27.333333333333332}, + "tshirt": "Medium", + "parent_risk": {"probability": 2, "impact": 2, "score": 4, "level": "Low"}, + "top_risk_drivers": ["Replace inline widget constructions (complexity of maintaining visual parity)", "Inadequate test coverage for layout behavior"], + "mitigations": ["Keep changes small and iterative", "Add/adjust integration smoke tests", "Manual smoke-run and PR checklist for reviewers"], + "confidence_pct": 70, + "assumptions": ["No major API changes to blessed or TUI controller", "Modal base design (WL-0MNU782BD004HO2W) does not introduce breaking constraints before extraction"], + "unknowns": ["Any hidden terminal-dependent layout edge-cases", "Potential blessed behavior differences across terminals"], + "generatedAt": "2026-04-19T11:13:00Z" +} diff --git a/src/tui/components/dialogs.ts b/src/tui/components/dialogs.ts index a0b34a9..3033de4 100644 --- a/src/tui/components/dialogs.ts +++ b/src/tui/components/dialogs.ts @@ -99,17 +99,12 @@ export class DialogsComponent { tags: false, }); - this.closeDialogOptions = this.blessedImpl.list({ + this.closeDialogOptions = this.createList({ parent: this.closeDialog, top: 4, left: 2, width: '100%-4', height: 4, - keys: true, - mouse: true, - style: { - selected: { bg: 'blue' }, - }, items: ['Close (in_review)', 'Close (done)', 'Close (deleted)', 'Cancel'], }); @@ -203,17 +198,12 @@ export class DialogsComponent { items: [], }); - const priorityList = this.blessedImpl.list({ + const priorityList = this.createList({ parent: this.updateDialog, top: updateDialogListTop, left: '66%+1', width: updateDialogColumnWidth, height: updateDialogListHeight, - keys: true, - mouse: true, - style: { - selected: { bg: 'blue' }, - }, items: ['critical', 'high', 'medium', 'low'], }); @@ -431,15 +421,12 @@ export class DialogsComponent { style: { fg: 'cyan', bold: true }, }); - this.createDialogPriorityOptions = this.blessedImpl.list({ + this.createDialogPriorityOptions = this.createList({ parent: this.createDialog, top: 17, left: '35%', width: '30%', height: 5, - keys: true, - mouse: true, - style: { selected: { bg: 'blue' } }, items: ['critical', 'high', 'medium', 'low'], }); @@ -504,6 +491,54 @@ export class DialogsComponent { } catch (_) {} } + /** + * Create a configured Blessed List with sensible defaults for dialogs. + * @param opts Partial blessed list options; parent/position/items may be provided. + */ + private createList(opts: any): BlessedList { + const defaults = { + keys: true, + mouse: true, + style: { selected: { bg: 'blue' } }, + items: [], + } as any; + return this.blessedImpl.list(Object.assign({}, defaults, opts)) as BlessedList; + } + + /** + * Create a configured Blessed Textarea with sensible defaults. + * @param opts Partial blessed textarea options. + */ + private createTextarea(opts: any): BlessedTextarea { + const defaults = { + input: true, + inputOnFocus: true, + vi: true, + wrap: true, + keys: true, + mouse: true, + scrollable: true, + alwaysScroll: true, + border: { type: 'line' }, + style: { fg: theme.tui.colors.lightText, bg: 'black', border: { fg: 'gray' } }, + scrollbar: { ch: ' ', inverse: true }, + } as any; + return this.blessedImpl.textarea(Object.assign({}, defaults, opts)) as BlessedTextarea; + } + + /** + * Create a label box used as a section header inside dialogs. + * @param opts Partial blessed box options. + */ + private createLabel(opts: any): BlessedBox { + const defaults = { + height: 1, + tags: false, + style: { fg: 'cyan', bold: true }, + } as any; + return this.blessedImpl.box(Object.assign({}, defaults, opts)) as BlessedBox; + } + create(): this { return this; }