@rozenite/vite-plugin 1.13.0 → 2.0.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/README.md +12 -0
- package/dist/bundle-dts.d.ts.map +1 -1
- package/dist/client-plugin.d.ts.map +1 -1
- package/dist/dev-config-module.d.ts.map +1 -1
- package/dist/dev-host/assets/index-DU3zXL2c.css +1 -0
- package/dist/dev-host/assets/index-Xsb6uYhI.js +13 -0
- package/dist/dev-host/index.html +3 -3
- package/dist/dev-host/manifest.json +2 -2
- package/dist/index.cjs +24 -8
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -8
- package/dist/react-native-plugin.d.ts.map +1 -1
- package/dist/sdk-plugin.d.ts.map +1 -1
- package/dist/server-plugin.d.ts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -10
- package/src/bundle-dts.ts +7 -6
- package/src/client-plugin.ts +8 -6
- package/src/dev-config-module.ts +4 -1
- package/src/dev-host/App.tsx +219 -413
- package/src/dev-host/components/DispatchForm.tsx +108 -122
- package/src/dev-host/components/FlowList.tsx +81 -101
- package/src/dev-host/components/MessageDetailsPane.tsx +56 -83
- package/src/dev-host/components/MessageLogPane.tsx +84 -66
- package/src/dev-host/components/PanelTabs.tsx +29 -10
- package/src/dev-host/config.ts +6 -2
- package/src/dev-host/constants.ts +0 -19
- package/src/dev-host/flow-runtime.ts +33 -12
- package/src/dev-host/index.html +1 -1
- package/src/dev-host/main.tsx +1 -10
- package/src/dev-host/server.ts +9 -3
- package/src/dev-host/styles.css +162 -830
- package/src/dev-host/types.ts +5 -10
- package/src/dev-host/utils.ts +9 -6
- package/src/dev-host/vite.config.mts +2 -0
- package/src/index.ts +15 -5
- package/src/load-config.ts +4 -4
- package/src/package-json.ts +1 -1
- package/src/react-native-plugin.ts +3 -0
- package/src/sdk-plugin.ts +3 -0
- package/src/server-plugin.ts +3 -0
- package/src/utils.ts +1 -1
- package/dist/dev-host/assets/index-CkxvBMpp.css +0 -1
- package/dist/dev-host/assets/index-cNKHRwej.js +0 -11
- package/src/dev-host/components/MessagePayloadDetail.tsx +0 -32
- package/src/dev-host/components/ResizeHandle.tsx +0 -33
- package/src/dev-host/components/icons.tsx +0 -79
- package/src/dev-host/components/ui/Button.tsx +0 -91
- package/src/dev-host/components/ui/DropdownMenu.tsx +0 -84
- package/src/dev-host/components/ui/IconButton.tsx +0 -41
- package/src/dev-host/components/ui/Input.tsx +0 -73
- package/src/dev-host/components/ui/ScrollArea.tsx +0 -20
- package/src/dev-host/components/ui/Tabs.tsx +0 -166
- package/src/dev-host/components/ui/Textarea.tsx +0 -79
- package/src/dev-host/components/ui/ToggleGroup.tsx +0 -120
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
import { Button, Input, Select, Tabs, Textarea } from '@rozenite/ui';
|
|
2
|
+
import { RotateCcw, Send } from 'lucide-react';
|
|
1
3
|
import { useState, type FormEvent } from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
+
import type {
|
|
5
|
+
DevHostFlowEntry,
|
|
6
|
+
DevHostFlowRunState,
|
|
7
|
+
DevHostPresetEntry,
|
|
8
|
+
} from '../types.js';
|
|
4
9
|
import { FlowList } from './FlowList.js';
|
|
5
|
-
import { DropdownMenu, type DropdownMenuItem } from './ui/DropdownMenu.js';
|
|
6
|
-
import { IconButton } from './ui/IconButton.js';
|
|
7
|
-
import { Input } from './ui/Input.js';
|
|
8
|
-
import { ScrollArea } from './ui/ScrollArea.js';
|
|
9
|
-
import { Textarea } from './ui/Textarea.js';
|
|
10
|
-
import { ToggleGroup } from './ui/ToggleGroup.js';
|
|
11
10
|
|
|
12
11
|
type DispatchFormProps = {
|
|
13
12
|
commandType: string;
|
|
@@ -43,127 +42,114 @@ export const DispatchForm = ({
|
|
|
43
42
|
onSubmit,
|
|
44
43
|
}: DispatchFormProps) => {
|
|
45
44
|
const [activeTab, setActiveTab] = useState<'dispatch' | 'flows'>('dispatch');
|
|
46
|
-
const presetItems: DropdownMenuItem<DevHostPresetEntry>[] = presets.map((preset) => ({
|
|
47
|
-
id: preset.displayName,
|
|
48
|
-
label: preset.displayName,
|
|
49
|
-
item: preset,
|
|
50
|
-
}));
|
|
51
|
-
const presetButton = (
|
|
52
|
-
<IconButton
|
|
53
|
-
type="button"
|
|
54
|
-
variant="default"
|
|
55
|
-
aria-label={presets.length > 0 ? 'Open presets' : 'No presets available'}
|
|
56
|
-
title={presets.length > 0 ? 'Presets' : 'No presets available'}
|
|
57
|
-
disabled={presets.length === 0}
|
|
58
|
-
overrides={{
|
|
59
|
-
BaseButton: {
|
|
60
|
-
style: {
|
|
61
|
-
borderRadius: '6px',
|
|
62
|
-
backgroundColor: 'rgba(255, 255, 255, 0.04)',
|
|
63
|
-
color: 'rgba(255, 255, 255, 0.88)',
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
}}
|
|
67
|
-
>
|
|
68
|
-
<PresetsIcon />
|
|
69
|
-
</IconButton>
|
|
70
|
-
);
|
|
71
45
|
|
|
72
46
|
return (
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
</div>
|
|
47
|
+
<section className="dev-host-pane">
|
|
48
|
+
<header className="dev-host-pane-header">
|
|
49
|
+
<h2 className="dev-host-pane-title">Actions</h2>
|
|
50
|
+
</header>
|
|
78
51
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
]}
|
|
90
|
-
/>
|
|
91
|
-
|
|
92
|
-
{activeTab === 'dispatch'
|
|
93
|
-
? presets.length > 0
|
|
94
|
-
? <DropdownMenu items={presetItems} onSelect={onApplyPreset}>{presetButton}</DropdownMenu>
|
|
95
|
-
: presetButton
|
|
96
|
-
: null}
|
|
97
|
-
</div>
|
|
52
|
+
<Tabs
|
|
53
|
+
className="flex min-h-0 flex-1 flex-col"
|
|
54
|
+
value={activeTab}
|
|
55
|
+
onValueChange={(value) => setActiveTab(value as 'dispatch' | 'flows')}
|
|
56
|
+
>
|
|
57
|
+
<div className="dev-host-tabs-header">
|
|
58
|
+
<Tabs.List aria-label="Action modes">
|
|
59
|
+
<Tabs.Tab value="dispatch">Dispatch</Tabs.Tab>
|
|
60
|
+
<Tabs.Tab value="flows">Flows</Tabs.Tab>
|
|
61
|
+
</Tabs.List>
|
|
98
62
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
63
|
+
{activeTab === 'dispatch' ? (
|
|
64
|
+
<Select
|
|
65
|
+
value={null}
|
|
66
|
+
onValueChange={(value) => {
|
|
67
|
+
const preset = presets.find((item) => item.name === value);
|
|
68
|
+
if (preset) {
|
|
69
|
+
onApplyPreset(preset);
|
|
70
|
+
}
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<Select.Trigger
|
|
74
|
+
className="w-auto"
|
|
75
|
+
aria-label={
|
|
76
|
+
presets.length > 0 ? 'Open presets' : 'No presets available'
|
|
77
|
+
}
|
|
78
|
+
disabled={presets.length === 0}
|
|
79
|
+
title={presets.length > 0 ? 'Presets' : 'No presets available'}
|
|
80
|
+
>
|
|
81
|
+
<Select.Value>Presets</Select.Value>
|
|
82
|
+
</Select.Trigger>
|
|
83
|
+
<Select.Content align="end">
|
|
84
|
+
{presets.map((preset) => (
|
|
85
|
+
<Select.Item key={preset.name} value={preset.name}>
|
|
86
|
+
{preset.displayName}
|
|
87
|
+
</Select.Item>
|
|
88
|
+
))}
|
|
89
|
+
</Select.Content>
|
|
90
|
+
</Select>
|
|
91
|
+
) : null}
|
|
92
|
+
</div>
|
|
114
93
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
94
|
+
<Tabs.Panel value="dispatch" className="dev-host-tab-panel">
|
|
95
|
+
<form className="dev-host-form" onSubmit={onSubmit}>
|
|
96
|
+
<label className="dev-host-field">
|
|
97
|
+
<span className="dev-host-label">Command</span>
|
|
98
|
+
<Input
|
|
99
|
+
value={commandType}
|
|
100
|
+
onChange={(event) =>
|
|
101
|
+
onCommandTypeChange(event.currentTarget.value)
|
|
102
|
+
}
|
|
103
|
+
placeholder="get-snapshot"
|
|
104
|
+
spellCheck={false}
|
|
105
|
+
/>
|
|
106
|
+
</label>
|
|
127
107
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
108
|
+
<label className="dev-host-field">
|
|
109
|
+
<span className="dev-host-label">Payload</span>
|
|
110
|
+
<Textarea
|
|
111
|
+
value={commandPayload}
|
|
112
|
+
onChange={(event) =>
|
|
113
|
+
onCommandPayloadChange(event.currentTarget.value)
|
|
114
|
+
}
|
|
115
|
+
placeholder='{"example": true}'
|
|
116
|
+
spellCheck={false}
|
|
117
|
+
/>
|
|
118
|
+
</label>
|
|
138
119
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
120
|
+
<div className="dev-host-actions">
|
|
121
|
+
<Button
|
|
122
|
+
variant="outline"
|
|
123
|
+
size="icon"
|
|
124
|
+
onClick={onReset}
|
|
125
|
+
aria-label="Reset dispatcher"
|
|
126
|
+
title="Reset dispatcher"
|
|
127
|
+
>
|
|
128
|
+
<RotateCcw />
|
|
129
|
+
</Button>
|
|
130
|
+
<Button
|
|
131
|
+
type="submit"
|
|
132
|
+
size="icon"
|
|
133
|
+
disabled={!canDispatch}
|
|
134
|
+
aria-label="Dispatch message"
|
|
135
|
+
title="Dispatch message"
|
|
136
|
+
>
|
|
137
|
+
<Send />
|
|
138
|
+
</Button>
|
|
139
|
+
</div>
|
|
140
|
+
</form>
|
|
141
|
+
</Tabs.Panel>
|
|
152
142
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
</div>
|
|
165
|
-
</ScrollArea>
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
143
|
+
<Tabs.Panel value="flows" className="dev-host-tab-panel">
|
|
144
|
+
<FlowList
|
|
145
|
+
flows={flows}
|
|
146
|
+
flowRuns={flowRuns}
|
|
147
|
+
hasRunningFlow={hasRunningFlow}
|
|
148
|
+
onRunFlow={onRunFlow}
|
|
149
|
+
onStopFlow={onStopFlow}
|
|
150
|
+
/>
|
|
151
|
+
</Tabs.Panel>
|
|
152
|
+
</Tabs>
|
|
153
|
+
</section>
|
|
168
154
|
);
|
|
169
155
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { Badge, Button, EmptyState } from '@rozenite/ui';
|
|
2
|
+
import { Play, Square } from 'lucide-react';
|
|
1
3
|
import { formatPayloadForCommandInput } from '../utils.js';
|
|
2
4
|
import type { DevHostFlowEntry, DevHostFlowRunState } from '../types.js';
|
|
3
|
-
import { Button } from './ui/Button.js';
|
|
4
5
|
|
|
5
6
|
type FlowListProps = {
|
|
6
7
|
flows: DevHostFlowEntry[];
|
|
@@ -11,129 +12,108 @@ type FlowListProps = {
|
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const getStatusLabel = (status: DevHostFlowRunState['status']) => {
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
switch (status) {
|
|
16
|
+
case 'running':
|
|
17
|
+
return 'Running';
|
|
18
|
+
case 'succeeded':
|
|
19
|
+
return 'Completed';
|
|
20
|
+
case 'failed':
|
|
21
|
+
return 'Failed';
|
|
22
|
+
case 'aborted':
|
|
23
|
+
return 'Stopped';
|
|
16
24
|
}
|
|
17
|
-
|
|
18
|
-
if (status === 'succeeded') {
|
|
19
|
-
return 'Completed';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (status === 'failed') {
|
|
23
|
-
return 'Failed';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (status === 'aborted') {
|
|
27
|
-
return 'Stopped';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return status;
|
|
31
25
|
};
|
|
32
26
|
|
|
33
|
-
export const FlowList = ({
|
|
27
|
+
export const FlowList = ({
|
|
28
|
+
flows,
|
|
29
|
+
flowRuns,
|
|
30
|
+
hasRunningFlow,
|
|
31
|
+
onRunFlow,
|
|
32
|
+
onStopFlow,
|
|
33
|
+
}: FlowListProps) => {
|
|
34
34
|
if (flows.length === 0) {
|
|
35
|
-
return
|
|
35
|
+
return (
|
|
36
|
+
<EmptyState
|
|
37
|
+
className="h-full"
|
|
38
|
+
title="No flows configured"
|
|
39
|
+
description="Add flows to rozenite.config.ts to run them here."
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
const hasExecutionState = flowRuns.length > 0;
|
|
39
|
-
|
|
40
44
|
return (
|
|
41
|
-
<div className="
|
|
42
|
-
<div className="
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const isActive = hasRunningFlow(flow.name);
|
|
45
|
+
<div className="dev-host-flow-list">
|
|
46
|
+
<div className="dev-host-field">
|
|
47
|
+
<span className="dev-host-label">Available flows</span>
|
|
48
|
+
<div className="grid gap-2">
|
|
49
|
+
{flows.map((flow) => {
|
|
50
|
+
const isRunning = hasRunningFlow(flow.name);
|
|
48
51
|
|
|
49
52
|
return (
|
|
50
53
|
<Button
|
|
51
|
-
key={
|
|
52
|
-
|
|
54
|
+
key={flow.name}
|
|
55
|
+
variant={isRunning ? 'secondary' : 'outline'}
|
|
56
|
+
className="dev-host-flow-button"
|
|
53
57
|
onClick={() => onRunFlow(flow)}
|
|
54
|
-
|
|
55
|
-
isSelected={isActive}
|
|
56
|
-
title={`Run ${flow.displayName}`}
|
|
57
|
-
overrides={{
|
|
58
|
-
BaseButton: {
|
|
59
|
-
style: {
|
|
60
|
-
display: 'flex',
|
|
61
|
-
alignItems: 'center',
|
|
62
|
-
justifyContent: 'space-between',
|
|
63
|
-
gap: '12px',
|
|
64
|
-
width: '100%',
|
|
65
|
-
borderRadius: '8px',
|
|
66
|
-
backgroundColor: isActive ? 'rgba(130, 50, 255, 0.14)' : 'rgba(255, 255, 255, 0.03)',
|
|
67
|
-
borderColor: isActive ? 'rgba(130, 50, 255, 0.45)' : 'rgba(255, 255, 255, 0.08)',
|
|
68
|
-
color: 'rgba(255, 255, 255, 0.88)',
|
|
69
|
-
paddingTop: '10px',
|
|
70
|
-
paddingRight: '12px',
|
|
71
|
-
paddingBottom: '10px',
|
|
72
|
-
paddingLeft: '12px',
|
|
73
|
-
textAlign: 'left',
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
}}
|
|
58
|
+
aria-label={`Run ${flow.displayName}`}
|
|
77
59
|
>
|
|
78
|
-
<span className="
|
|
60
|
+
<span className="dev-host-flow-name">
|
|
61
|
+
<Play />
|
|
79
62
|
{flow.displayName}
|
|
80
|
-
{flow.autoRun ? <
|
|
63
|
+
{flow.autoRun ? <Badge variant="outline">Auto</Badge> : null}
|
|
64
|
+
</span>
|
|
65
|
+
<span className="text-xs text-muted-foreground">
|
|
66
|
+
{isRunning ? 'Running' : 'Run'}
|
|
81
67
|
</span>
|
|
82
|
-
<span className="rz-flow-list-action">{isActive ? 'Running' : 'Run'}</span>
|
|
83
68
|
</Button>
|
|
84
69
|
);
|
|
85
70
|
})}
|
|
86
71
|
</div>
|
|
87
72
|
</div>
|
|
88
73
|
|
|
89
|
-
{
|
|
90
|
-
<div className="
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
{isRunning ? (
|
|
106
|
-
<Button
|
|
107
|
-
type="button"
|
|
108
|
-
variant="pill"
|
|
109
|
-
onClick={() => onStopFlow(flowRun.id)}
|
|
110
|
-
overrides={{
|
|
111
|
-
BaseButton: {
|
|
112
|
-
style: {
|
|
113
|
-
flexShrink: 0,
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
}}
|
|
117
|
-
>
|
|
118
|
-
Stop
|
|
119
|
-
</Button>
|
|
74
|
+
{flowRuns.length > 0 ? (
|
|
75
|
+
<div className="dev-host-field">
|
|
76
|
+
<span className="dev-host-label">Flow runs</span>
|
|
77
|
+
<div className="dev-host-flow-runs">
|
|
78
|
+
{flowRuns.map((flowRun) => (
|
|
79
|
+
<div
|
|
80
|
+
key={flowRun.id}
|
|
81
|
+
className="dev-host-flow-state"
|
|
82
|
+
data-status={flowRun.status}
|
|
83
|
+
>
|
|
84
|
+
<div className="dev-host-flow-state-header">
|
|
85
|
+
<span className="dev-host-flow-title">
|
|
86
|
+
{flowRun.flowDisplayName}
|
|
87
|
+
{flowRun.autoRun ? (
|
|
88
|
+
<Badge variant="outline">Auto</Badge>
|
|
120
89
|
) : null}
|
|
121
|
-
</
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
{formatPayloadForCommandInput(flowRun.result)}
|
|
132
|
-
</pre>
|
|
90
|
+
</span>
|
|
91
|
+
{flowRun.status === 'running' ? (
|
|
92
|
+
<Button
|
|
93
|
+
variant="ghost"
|
|
94
|
+
size="compact"
|
|
95
|
+
onClick={() => onStopFlow(flowRun.id)}
|
|
96
|
+
>
|
|
97
|
+
<Square />
|
|
98
|
+
Stop
|
|
99
|
+
</Button>
|
|
133
100
|
) : null}
|
|
134
101
|
</div>
|
|
135
|
-
|
|
136
|
-
|
|
102
|
+
<span className="text-xs text-muted-foreground">
|
|
103
|
+
{getStatusLabel(flowRun.status)}
|
|
104
|
+
</span>
|
|
105
|
+
{flowRun.error ? (
|
|
106
|
+
<div className="dev-host-flow-state-error">
|
|
107
|
+
{flowRun.error}
|
|
108
|
+
</div>
|
|
109
|
+
) : null}
|
|
110
|
+
{flowRun.result != null ? (
|
|
111
|
+
<pre className="dev-host-flow-state-result">
|
|
112
|
+
{formatPayloadForCommandInput(flowRun.result)}
|
|
113
|
+
</pre>
|
|
114
|
+
) : null}
|
|
115
|
+
</div>
|
|
116
|
+
))}
|
|
137
117
|
</div>
|
|
138
118
|
</div>
|
|
139
119
|
) : null}
|
|
@@ -1,103 +1,76 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { Button, JsonInspector, ScrollArea } from '@rozenite/ui';
|
|
2
|
+
import { Send, X } from 'lucide-react';
|
|
3
|
+
import type { MessageEntry } from '../types.js';
|
|
3
4
|
import { formatMessageDate, formatPayloadForCommandInput } from '../utils.js';
|
|
4
|
-
import { MessagePayloadDetail } from './MessagePayloadDetail.js';
|
|
5
|
-
import { ResizeHandle } from './ResizeHandle.js';
|
|
6
|
-
import { ScrollArea } from './ui/ScrollArea.js';
|
|
7
|
-
import { SendIcon } from './icons.js';
|
|
8
|
-
import { IconButton } from './ui/IconButton.js';
|
|
9
5
|
|
|
10
6
|
type MessageDetailsPaneProps = {
|
|
11
|
-
selectedMessage: MessageEntry
|
|
12
|
-
isOpen: boolean;
|
|
13
|
-
isNarrowViewport: boolean;
|
|
14
|
-
activeResizeHandle: ResizeHandleId | null;
|
|
7
|
+
selectedMessage: MessageEntry;
|
|
15
8
|
onClose: () => void;
|
|
16
9
|
onUseMessage: (message: MessageEntry) => void;
|
|
17
|
-
onResizeStart: (event: ReactPointerEvent<HTMLDivElement>) => void;
|
|
18
10
|
};
|
|
19
11
|
|
|
20
12
|
export const MessageDetailsPane = ({
|
|
21
13
|
selectedMessage,
|
|
22
|
-
isOpen,
|
|
23
|
-
isNarrowViewport,
|
|
24
|
-
activeResizeHandle,
|
|
25
14
|
onClose,
|
|
26
15
|
onUseMessage,
|
|
27
|
-
onResizeStart,
|
|
28
16
|
}: MessageDetailsPaneProps) => {
|
|
29
|
-
const isHidden = !isOpen || !selectedMessage;
|
|
30
|
-
|
|
31
17
|
return (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
}}
|
|
58
|
-
>
|
|
59
|
-
<SendIcon />
|
|
60
|
-
</IconButton>
|
|
18
|
+
<section className="dev-host-pane">
|
|
19
|
+
<header className="dev-host-pane-header">
|
|
20
|
+
<h2 className="dev-host-pane-title">Message Details</h2>
|
|
21
|
+
<div className="dev-host-pane-actions">
|
|
22
|
+
<Button
|
|
23
|
+
variant="ghost"
|
|
24
|
+
size="icon"
|
|
25
|
+
onClick={() => onUseMessage(selectedMessage)}
|
|
26
|
+
aria-label="Use message in dispatcher"
|
|
27
|
+
title="Use message in dispatcher"
|
|
28
|
+
>
|
|
29
|
+
<Send />
|
|
30
|
+
</Button>
|
|
31
|
+
<Button
|
|
32
|
+
variant="ghost"
|
|
33
|
+
size="icon"
|
|
34
|
+
onClick={onClose}
|
|
35
|
+
aria-label="Close message details"
|
|
36
|
+
title="Close message details"
|
|
37
|
+
>
|
|
38
|
+
<X />
|
|
39
|
+
</Button>
|
|
40
|
+
</div>
|
|
41
|
+
</header>
|
|
61
42
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
43
|
+
<ScrollArea className="dev-host-scroll">
|
|
44
|
+
<div className="dev-host-details">
|
|
45
|
+
<div className="dev-host-detail-section">
|
|
46
|
+
<span className="dev-host-label">Date</span>
|
|
47
|
+
<div className="dev-host-detail-value">
|
|
48
|
+
{formatMessageDate(selectedMessage.date)}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div className="dev-host-detail-section">
|
|
52
|
+
<span className="dev-host-label">Type</span>
|
|
53
|
+
<div className="dev-host-detail-value">{selectedMessage.type}</div>
|
|
54
|
+
</div>
|
|
55
|
+
<div className="dev-host-detail-section">
|
|
56
|
+
<span className="dev-host-label">Payload</span>
|
|
57
|
+
<div className="dev-host-detail-payload">
|
|
58
|
+
{typeof selectedMessage.payload === 'object' &&
|
|
59
|
+
selectedMessage.payload !== null ? (
|
|
60
|
+
<JsonInspector
|
|
61
|
+
data={selectedMessage.payload}
|
|
62
|
+
defaultExpandedDepth={2}
|
|
63
|
+
/>
|
|
64
|
+
) : (
|
|
65
|
+
<pre className="m-0 whitespace-pre-wrap break-words">
|
|
66
|
+
{formatPayloadForCommandInput(selectedMessage.payload)}
|
|
67
|
+
</pre>
|
|
68
|
+
)}
|
|
69
69
|
</div>
|
|
70
70
|
</div>
|
|
71
|
-
|
|
72
|
-
<ScrollArea className="rz-sidebar-scroll">
|
|
73
|
-
{selectedMessage ? (
|
|
74
|
-
<div className="rz-message-detail">
|
|
75
|
-
<div className="rz-detail-section">
|
|
76
|
-
<div className="rz-label">Date</div>
|
|
77
|
-
<div className="rz-detail-value rz-detail-mono">
|
|
78
|
-
{formatMessageDate(selectedMessage.date)}
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
|
|
82
|
-
<div className="rz-detail-section">
|
|
83
|
-
<div className="rz-label">Type</div>
|
|
84
|
-
<div className="rz-detail-value rz-detail-mono">{selectedMessage.type}</div>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
<div className="rz-detail-section">
|
|
88
|
-
<div className="rz-label">Payload</div>
|
|
89
|
-
<div className="rz-detail-payload">
|
|
90
|
-
<MessagePayloadDetail payload={selectedMessage.payload} />
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
|
-
) : (
|
|
95
|
-
<div className="rz-empty-state">Select a message to inspect its details.</div>
|
|
96
|
-
)}
|
|
97
|
-
</ScrollArea>
|
|
98
71
|
</div>
|
|
99
|
-
</
|
|
100
|
-
|
|
72
|
+
</ScrollArea>
|
|
73
|
+
</section>
|
|
101
74
|
);
|
|
102
75
|
};
|
|
103
76
|
|