Step 2: the settings page can change things - shared draft, Review & Apply, rollback, history, undo
- settings/apply.py: the Apply pipeline (check, keep history, write, restart the watchdog, re-import pages by the marker-only rule, recolour page keys), rollback when the watchdog does not come back, the recording guard with the Emergency (LIVE) override, history entries and Go back / Undo. - settings/server.py: the write routes behind the editing code (draft PUT/DELETE with 409 on a conflict, validate, apply, restore, undo, watchdog restart/stop/start, commands to the watchdog, the switcher file upload / pick newest / discard, gear notes). - settings/ui/app.js: every screen grows inputs with Editing on; keys (checks, fixes, hold-always, members), computers, fixes, site setup (schedules, Dante devices, Spotify, ATEM), Review & Apply with live progress, History with Go back and Undo, Run this fix now. - schema.unmask, push_page.push, nav_keys.colour; tests for all of it (163 pass). - Verified live on NA Ingest: a page-only Apply, a restart Apply, Undo, history. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -644,6 +644,28 @@ def mask_secrets(obj):
|
||||
return walk(copy.deepcopy(obj), "")
|
||||
|
||||
|
||||
def unmask(draft, live):
|
||||
"""A draft that came back from the page carries masked secrets ("set (N characters)"): put the
|
||||
live values back so a masked value never overwrites a real one."""
|
||||
secret_paths = {p for p, f in F.items() if f["secret"]}
|
||||
|
||||
def walk(node, ref, path):
|
||||
if isinstance(node, dict):
|
||||
out = {}
|
||||
for k, v in node.items():
|
||||
p = "%s.%s" % (path, k) if path else k
|
||||
if (p in secret_paths or k in secret_paths) and isinstance(v, str) and (v.startswith("set (") or v == "") \
|
||||
and isinstance(ref, dict) and isinstance(ref.get(k), str) and ref.get(k):
|
||||
out[k] = ref[k] if v.startswith("set (") else ""
|
||||
else:
|
||||
out[k] = walk(v, ref.get(k) if isinstance(ref, dict) else None, p)
|
||||
return out
|
||||
if isinstance(node, list):
|
||||
return [walk(v, ref[i] if isinstance(ref, list) and i < len(ref) else None, path + "[]") for i, v in enumerate(node)]
|
||||
return node
|
||||
return walk(copy.deepcopy(draft), live, "")
|
||||
|
||||
|
||||
def phrases(cfg):
|
||||
"""The sentences the page and the logs build from the config."""
|
||||
a = cfg.get("auto_fix") or {}
|
||||
|
||||
Reference in New Issue
Block a user