fix: leerer select in node im config panel leading to white screen

This commit is contained in:
Ida 2026-05-13 15:48:30 +02:00
parent 9e36075f0e
commit 600e0c87dc
3 changed files with 49 additions and 13 deletions

View file

@ -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;

View file

@ -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}

View file

@ -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>