mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-06-26 05:58:38 +00:00
fix(web): repair news ticker custom-feeds save for JSON path
The JS dotToNested() helper converts indexed form fields like
feeds.custom_feeds.0.name into a dict {'0': {name:...}} rather than a
proper array. The form-data path already had fix_array_structures() to
convert those dicts back to arrays before schema validation, but the
JSON path (used by all web-UI saves) never ran that fix, so saving any
custom feed produced a schema validation error: "Expected type array,
got object".
Add _fix_json_arrays() immediately after schema loading on the JSON
path, mirroring the existing fix_array_structures() logic.
Also fix custom-feeds.js getValue() to omit the logo key entirely when
no logo is present instead of returning logo:null, which would fail
schema validation (logo expects type object).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4463,6 +4463,42 @@ def save_plugin_config():
|
||||
if 'application/json' in content_type:
|
||||
schema = schema_mgr.load_schema(plugin_id, use_cache=False)
|
||||
|
||||
# JSON path: fix numeric-keyed dicts that should be arrays.
|
||||
# JS dotToNested() converts feeds.custom_feeds.0.name → {'0': {name:...}}
|
||||
# instead of [{name:...}]. The form-data path has fix_array_structures for this;
|
||||
# mirror that logic here for JSON submissions.
|
||||
if 'application/json' in content_type and schema and 'properties' in schema:
|
||||
def _fix_json_arrays(cfg, props):
|
||||
for k, ps in props.items():
|
||||
if not isinstance(cfg, dict) or k not in cfg:
|
||||
continue
|
||||
pt = ps.get('type')
|
||||
val = cfg[k]
|
||||
if pt == 'array' and isinstance(val, dict):
|
||||
keys = list(val.keys())
|
||||
if keys and all(str(x).isdigit() for x in keys):
|
||||
sorted_keys = sorted(keys, key=lambda x: int(str(x)))
|
||||
items_schema = ps.get('items', {})
|
||||
item_type = items_schema.get('type')
|
||||
arr = [val[sk] for sk in sorted_keys]
|
||||
if item_type in ('integer', 'number'):
|
||||
converted = []
|
||||
for v in arr:
|
||||
if isinstance(v, str):
|
||||
try:
|
||||
converted.append(int(v) if item_type == 'integer' else float(v))
|
||||
except (ValueError, TypeError):
|
||||
converted.append(v)
|
||||
else:
|
||||
converted.append(v)
|
||||
arr = converted
|
||||
cfg[k] = arr
|
||||
elif not keys:
|
||||
cfg[k] = []
|
||||
elif pt == 'object' and 'properties' in ps and isinstance(val, dict):
|
||||
_fix_json_arrays(val, ps['properties'])
|
||||
_fix_json_arrays(plugin_config, schema['properties'])
|
||||
|
||||
# PRE-PROCESSING: Preserve 'enabled' state if not in request
|
||||
# This prevents overwriting the enabled state when saving config from a form that doesn't include the toggle
|
||||
if 'enabled' not in plugin_config:
|
||||
|
||||
@@ -54,15 +54,18 @@
|
||||
const logoIdInput = row.querySelector('input[name*=".logo.id"]');
|
||||
|
||||
if (nameInput && urlInput) {
|
||||
feeds.push({
|
||||
const feedObj = {
|
||||
name: nameInput.value,
|
||||
url: urlInput.value,
|
||||
enabled: enabledInput ? enabledInput.checked : true,
|
||||
logo: logoPathInput || logoIdInput ? {
|
||||
enabled: enabledInput ? enabledInput.checked : true
|
||||
};
|
||||
if (logoPathInput || logoIdInput) {
|
||||
feedObj.logo = {
|
||||
path: logoPathInput ? logoPathInput.value : '',
|
||||
id: logoIdInput ? logoIdInput.value : ''
|
||||
} : null
|
||||
});
|
||||
};
|
||||
}
|
||||
feeds.push(feedObj);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user