diff --git a/web_interface/static/v3/plugins_manager.js b/web_interface/static/v3/plugins_manager.js index b8c55568..e877ad4e 100644 --- a/web_interface/static/v3/plugins_manager.js +++ b/web_interface/static/v3/plugins_manager.js @@ -2873,21 +2873,55 @@ function generateFieldHtml(key, prop, value, prefix = '') { `; } else if (prop.type === 'array') { - // Check if this is a file upload widget - try multiple ways to access x-widget - const hasXWidget = prop.hasOwnProperty('x-widget'); - const xWidgetValue = prop['x-widget']; - const xWidgetValue2 = prop['x-widget'] || prop['x_widget'] || prop.xWidget; - - console.log(`[DEBUG] Array field ${fullKey}:`, { - type: prop.type, - hasXWidget: hasXWidget, - 'x-widget': xWidgetValue, - 'x-widget (alt)': xWidgetValue2, - 'x-upload-config': prop['x-upload-config'], - propKeys: Object.keys(prop), - propString: JSON.stringify(prop), - value: value - }); + // Check if this is an array of objects FIRST (before other checks) + if (prop.items && prop.items.type === 'object' && prop.items.properties) { + // Array of objects widget (like custom_feeds with name, url, enabled, logo) + console.log(`[DEBUG] ✅ Detected array-of-objects widget for ${fullKey}`); + const fieldId = fullKey.replace(/\./g, '_'); + const itemsSchema = prop.items; + const itemProperties = itemsSchema.properties || {}; + const maxItems = prop.maxItems || 50; + const currentItems = Array.isArray(value) ? value : []; + + html += ` +
+
+ `; + + // Render existing items + currentItems.forEach((item, index) => { + html += renderArrayObjectItem(fieldId, fullKey, itemProperties, item, index, itemsSchema); + }); + + html += ` +
+ + +
+ `; + } else { + // Check if this is a file upload widget - try multiple ways to access x-widget + const hasXWidget = prop.hasOwnProperty('x-widget'); + const xWidgetValue = prop['x-widget']; + const xWidgetValue2 = prop['x-widget'] || prop['x_widget'] || prop.xWidget; + + console.log(`[DEBUG] Array field ${fullKey}:`, { + type: prop.type, + hasItems: !!prop.items, + itemsType: prop.items?.type, + itemsHasProperties: !!prop.items?.properties, + hasXWidget: hasXWidget, + 'x-widget': xWidgetValue, + 'x-widget (alt)': xWidgetValue2, + 'x-upload-config': prop['x-upload-config'], + propKeys: Object.keys(prop), + value: value + }); // Check for file-upload widget - be more defensive if (xWidgetValue === 'file-upload' || xWidgetValue2 === 'file-upload') {