|
1 | | -import { Select, Spinner, StatusMessage } from '@inkjs/ui'; |
| 1 | +import { Select } from '@inkjs/ui'; |
| 2 | +import { PlanResponseData } from 'codify-schemas'; |
2 | 3 | import { Box, Static, Text } from 'ink'; |
3 | 4 | import { EventEmitter } from 'node:events'; |
4 | 5 | import React, { useEffect, useState } from 'react'; |
5 | 6 |
|
6 | | -import { ProcessState, ProcessStatus } from '../reporters/default-reporter.js'; |
7 | | -import { PlanResponseData } from 'codify-schemas'; |
| 7 | +import { RenderEvent, RenderState } from '../reporters/reporter.js'; |
8 | 8 | import { PlanComponent } from './plan/plan.js'; |
| 9 | +import { ProgressDisplay, ProgressState } from './progress/progress-display.js'; |
9 | 10 |
|
10 | 11 | export function DefaultComponent(props: { |
11 | 12 | emitter: EventEmitter |
12 | 13 | }) { |
13 | 14 | const { emitter } = props; |
14 | 15 |
|
15 | | - const [staticOutput, setStaticOutput] = useState([] as Array<string>); |
16 | | - const [processState, setProcessState] = useState({ |
17 | | - process: [], |
18 | | - } as ProcessState); |
19 | | - const [planState, setPlanState] = useState(null as PlanResponseData[] | null); |
20 | | - const [showConfirm, setShowConfirm] = useState(false); |
| 16 | + const [state, setState] = useState(RenderState.GENERATING_PLAN); |
| 17 | + const [staticOutput, setStaticOutput] = useState([] as Array<Record<string, unknown> | string>); |
| 18 | + const [progressState, setProgressState] = useState(null as ProgressState | null); |
| 19 | + const [plan, setPlan] = useState(null as PlanResponseData[] | null); |
21 | 20 | const [confirmValue, setConfirmValue] = useState(null as boolean | null) |
22 | 21 |
|
23 | 22 | useEffect(() => { |
24 | | - emitter.on('static_output', (newValue: any) => { |
25 | | - setStaticOutput([...newValue]); |
26 | | - }); |
| 23 | + emitter.on(RenderEvent.STATE_TRANSITION, (obj) => { |
| 24 | + switch (obj.nextState) { |
| 25 | + case RenderState.GENERATING_PLAN: { |
| 26 | + setProgressState(obj.progressState); |
| 27 | + setState(obj.nextState); |
| 28 | + break; |
| 29 | + } |
| 30 | + |
| 31 | + case RenderState.DISPLAY_PLAN: { |
| 32 | + setPlan(obj.plan); |
| 33 | + setState(obj.nextState); |
| 34 | + break; |
| 35 | + } |
| 36 | + |
| 37 | + case RenderState.ASK_CONFIRMATION: { |
| 38 | + setState(obj.nextState); |
| 39 | + break; |
| 40 | + } |
| 41 | + |
| 42 | + case RenderState.APPLYING: { |
| 43 | + break; |
| 44 | + } |
| 45 | + } |
| 46 | + }) |
27 | 47 |
|
28 | | - emitter.on('process', (state: ProcessState) => { |
29 | | - setProcessState(structuredClone(state)); |
| 48 | + emitter.once(RenderEvent.LOG, (newValue: string) => { |
| 49 | + setStaticOutput([...newValue]); |
30 | 50 | }); |
31 | 51 |
|
32 | | - emitter.on('plan', (plan: PlanResponseData[]) => { |
33 | | - setPlanState(plan); |
| 52 | + emitter.on(RenderEvent.PROCESS_UPDATE, (state: ProgressState) => { |
| 53 | + setProgressState(structuredClone(state)); |
34 | 54 | }); |
35 | | - emitter.on('promptConfirmation', () => { |
36 | | - setShowConfirm(true); |
37 | | - }) |
38 | 55 | }, []); |
39 | 56 |
|
40 | 57 | return <Box flexDirection="column"> |
41 | 58 | <Static items={staticOutput}> |
42 | 59 | { |
43 | | - (text, idx) => <Text color="cyan" key={idx}>{text}</Text> |
| 60 | + (text, idx) => <Text color="cyan" key={idx}>{text.toString()}</Text> |
44 | 61 | } |
45 | 62 | </Static> |
46 | 63 | { |
47 | | - processState.process?.map((item, i) => |
48 | | - <Box flexDirection="column" key={i}> |
49 | | - { |
50 | | - item.status === ProcessStatus.IN_PROGRESS |
51 | | - ? <Spinner label={item.name}/> |
52 | | - : <StatusMessage variant="success">{item.name}</StatusMessage> |
53 | | - } |
54 | | - <Box flexDirection="column" marginLeft={2}> |
55 | | - { |
56 | | - item.subprocess?.map((subItem, i) => |
57 | | - subItem.status === ProcessStatus.IN_PROGRESS |
58 | | - ? <Spinner key={i} label={subItem.name}/> |
59 | | - : <StatusMessage key={i} variant="success">{subItem.name}</StatusMessage> |
60 | | - ) ?? [] |
61 | | - } |
62 | | - </Box> |
63 | | - </Box> |
64 | | - ) ?? [] |
| 64 | + state >= RenderState.DISPLAY_PLAN && plan && <Static items={[plan]}>{ |
| 65 | + (plan, idx) => <PlanComponent key={idx} plan={plan}/> |
| 66 | + }</Static> |
65 | 67 | } |
66 | 68 | { |
67 | | - planState |
68 | | - ? <Static items={[planState]}>{ |
69 | | - (plan, idx) => <PlanComponent key={idx} plan={plan}/> |
70 | | - }</Static> |
71 | | - : <></> |
| 69 | + (state === RenderState.GENERATING_PLAN || state === RenderState.APPLYING) && progressState && |
| 70 | + <ProgressDisplay progress={progressState}/> |
72 | 71 | } |
73 | 72 | { |
74 | | - showConfirm && ( |
| 73 | + state === RenderState.ASK_CONFIRMATION && ( |
75 | 74 | confirmValue === null |
76 | 75 | ? <Box flexDirection="column"> |
77 | 76 | <Text>Do you want to apply the above changes?</Text> |
78 | | - <Select options={[ |
| 77 | + <Select onChange={(value) => { |
| 78 | + setConfirmValue(value === 'yes'); |
| 79 | + emitter.emit(RenderEvent.PROMPT_RESULT, value === 'yes') |
| 80 | + }} options={[ |
79 | 81 | { label: 'Yes', value: 'yes' }, |
80 | 82 | { label: 'No', value: 'no' }, |
81 | | - ]} onChange={(value) => { |
82 | | - console.log(value); |
83 | | - setConfirmValue(value === 'yes'); |
84 | | - emitter.emit('promptConfirmation_Result', value === 'yes') |
85 | | - }}/> |
| 83 | + ]}/> |
86 | 84 | </Box> |
87 | 85 | : <Box flexDirection="column"> |
88 | 86 | <Text>Do you want to apply the above changes?</Text> |
89 | | - <Select options={[ |
| 87 | + <Select highlightText={confirmValue ? 'Yes' : 'No'} isDisabled options={[ |
90 | 88 | { label: 'Yes', value: 'yes' }, |
91 | 89 | { label: 'No', value: 'no' }, |
92 | | - ]} isDisabled highlightText={confirmValue ? 'Yes' : 'No'}/> |
| 90 | + ]}/> |
93 | 91 | </Box> |
94 | 92 | ) |
95 | 93 | } |
|
0 commit comments