fix: leerer select in node im config panel leading to white screen
This commit is contained in:
parent
9e36075f0e
commit
600e0c87dc
3 changed files with 49 additions and 13 deletions
|
|
@ -246,6 +246,7 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background: var(--canvas-bg, #fafafa);
|
||||
}
|
||||
|
||||
|
|
@ -594,7 +595,7 @@
|
|||
.canvasArea {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
min-height: 400px;
|
||||
min-height: 0;
|
||||
overflow-x: visible;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
|
@ -996,6 +997,16 @@
|
|||
cursor: copy;
|
||||
}
|
||||
|
||||
/* Shell: stretches to full canvas-area height so inner `.nodeConfigPanel` can scroll. */
|
||||
.nodeConfigPanelWrap {
|
||||
flex-shrink: 0;
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Node Config Panel
|
||||
* Fixed-width side panel. The `box-sizing: border-box` + `overflow-x: hidden`
|
||||
* pair acts as a safety net so long unbreakable strings (type names like
|
||||
|
|
@ -1005,11 +1016,12 @@
|
|||
* a long label rather than escaping to the right.
|
||||
*/
|
||||
.nodeConfigPanel {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
padding: 1rem;
|
||||
background: var(--bg-primary, #fff);
|
||||
border-left: 1px solid var(--border-color, #e0e0e0);
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
|
|
|||
|
|
@ -957,8 +957,8 @@ export const Automation2FlowEditor: React.FC<Automation2FlowEditorProps> = ({ in
|
|||
onVerboseSchemaChange={setVerboseSchema}
|
||||
canvasEdit={canvasHeaderEdit}
|
||||
/>
|
||||
<div className={styles.canvasArea} style={{ display: 'flex', flex: 1, minWidth: 0 }}>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div className={styles.canvasArea} style={{ display: 'flex', flex: 1, minWidth: 0, alignItems: 'stretch' }}>
|
||||
<div style={{ flex: 1, minWidth: 0, minHeight: 0 }}>
|
||||
<FlowCanvas
|
||||
ref={flowCanvasRef}
|
||||
nodes={canvasNodes}
|
||||
|
|
@ -995,7 +995,7 @@ export const Automation2FlowEditor: React.FC<Automation2FlowEditorProps> = ({ in
|
|||
/>
|
||||
</div>
|
||||
{configurableSelected && selectedNode && (
|
||||
<div style={{ flexShrink: 0, display: 'flex', flexDirection: 'column' }}>
|
||||
<div className={styles.nodeConfigPanelWrap}>
|
||||
<Automation2DataFlowProvider
|
||||
node={selectedNode}
|
||||
nodes={canvasNodes}
|
||||
|
|
|
|||
|
|
@ -100,9 +100,30 @@ const DateInput: React.FC<FieldRendererProps> = ({ param, value, onChange }) =>
|
|||
</div>
|
||||
);
|
||||
|
||||
/** Backend may send `options: ["a","b"]` or `options: [{ value, label }, ...]` (e.g. context.extractContent). */
|
||||
function _normalizedSelectOptions(raw: unknown): Array<{ value: string; label: string }> {
|
||||
if (!Array.isArray(raw)) return [];
|
||||
const out: Array<{ value: string; label: string }> = [];
|
||||
for (const item of raw) {
|
||||
if (typeof item === 'string') {
|
||||
out.push({ value: item, label: item });
|
||||
continue;
|
||||
}
|
||||
if (item && typeof item === 'object' && 'value' in item) {
|
||||
const rec = item as { value?: unknown; label?: unknown };
|
||||
if (typeof rec.value === 'string') {
|
||||
const label = typeof rec.label === 'string' && rec.label.length > 0 ? rec.label : rec.value;
|
||||
out.push({ value: rec.value, label });
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const SelectInput: React.FC<FieldRendererProps> = ({ param, value, onChange }) => {
|
||||
const options: string[] =
|
||||
(param.frontendOptions?.options as string[]) || (param.options as string[]) || [];
|
||||
const options = _normalizedSelectOptions(
|
||||
param.frontendOptions?.options ?? param.options ?? []
|
||||
);
|
||||
return (
|
||||
<div style={{ marginBottom: 8 }}>
|
||||
<label style={{ display: 'block', fontSize: 12, marginBottom: 2 }}>{param.description || param.name}</label>
|
||||
|
|
@ -113,7 +134,9 @@ const SelectInput: React.FC<FieldRendererProps> = ({ param, value, onChange }) =
|
|||
>
|
||||
<option value="">—</option>
|
||||
{options.map((opt) => (
|
||||
<option key={opt} value={opt}>{opt}</option>
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -121,8 +144,9 @@ const SelectInput: React.FC<FieldRendererProps> = ({ param, value, onChange }) =
|
|||
};
|
||||
|
||||
const MultiSelectInput: React.FC<FieldRendererProps> = ({ param, value, onChange }) => {
|
||||
const options: string[] =
|
||||
(param.frontendOptions?.options as string[]) || (param.options as string[]) || [];
|
||||
const options = _normalizedSelectOptions(
|
||||
param.frontendOptions?.options ?? param.options ?? []
|
||||
);
|
||||
const selected = Array.isArray(value) ? value : [];
|
||||
const toggle = (opt: string) => {
|
||||
const next = selected.includes(opt) ? selected.filter((v: string) => v !== opt) : [...selected, opt];
|
||||
|
|
@ -133,9 +157,9 @@ const MultiSelectInput: React.FC<FieldRendererProps> = ({ param, value, onChange
|
|||
<label style={{ display: 'block', fontSize: 12, marginBottom: 2 }}>{param.description || param.name}</label>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
|
||||
{options.map((opt) => (
|
||||
<label key={opt} style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<input type="checkbox" checked={selected.includes(opt)} onChange={() => toggle(opt)} />
|
||||
{opt}
|
||||
<label key={opt.value} style={{ fontSize: 12, display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<input type="checkbox" checked={selected.includes(opt.value)} onChange={() => toggle(opt.value)} />
|
||||
{opt.label}
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue