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:
@@ -178,6 +178,35 @@ def page_name(host, port, page):
|
||||
return r.read().decode()
|
||||
|
||||
|
||||
def push(host, port, page, file_path, expected_name):
|
||||
"""Upload a built page file and import it into `page` (the caller has checked safe_target)."""
|
||||
data = open(file_path, "rb").read()
|
||||
built = json.loads(gzip.decompress(data))
|
||||
if (built.get("page") or {}).get("name") != expected_name:
|
||||
raise ValueError("%s builds page %r, not %r" % (os.path.basename(file_path), (built.get("page") or {}).get("name"), expected_name))
|
||||
ws = WebSocket(host, port, "/trpc")
|
||||
try:
|
||||
api = Trpc(ws)
|
||||
for attempt in range(40):
|
||||
try:
|
||||
session = api.mutation("importExport.prepareImport.start", {"name": os.path.basename(file_path), "size": len(data)})
|
||||
break
|
||||
except RuntimeError as e:
|
||||
if "already exists" not in str(e) or attempt == 39:
|
||||
raise
|
||||
time.sleep(3)
|
||||
for offset in range(0, len(data), CHUNK):
|
||||
api.mutation("importExport.prepareImport.uploadChunk",
|
||||
{"sessionId": session, "offset": offset, "data": base64.b64encode(data[offset:offset + CHUNK]).decode()})
|
||||
summary = api.mutation("importExport.prepareImport.complete",
|
||||
{"sessionId": session, "expectedChecksum": hashlib.sha1(data).hexdigest(), "userData": None})
|
||||
if isinstance(summary, list) and summary and summary[0]:
|
||||
raise RuntimeError("Companion could not read the file: %s" % summary[0])
|
||||
api.mutation("importExport.importSinglePage", {"targetPage": page, "sourcePage": 1, "connectionIdRemapping": {}})
|
||||
finally:
|
||||
ws.close()
|
||||
|
||||
|
||||
def main():
|
||||
cfg = json.load(open(os.path.join(HERE, "config.json")))
|
||||
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||
|
||||
Reference in New Issue
Block a user