oficina / slides Public

Clone
git clone https://amadan.net/oficina/slides

Plain git — no account needed to clone.

Download

Download this file

1// fixtures/status.mjs — the editor's save line and its load-error line,
2// factored out of editor-entry.js so the rules are testable under plain
3// Node (status.test.mjs).
4//
5// The save line is estilo's savestatus (the template renders it with
6// every state's words from the catalog; its module, served at
7// static/estilo/save-status.<hash>.mjs, moves it between them). Its
8// four states: `saved`, `saving`, `retrying` (a save is being retried —
9// the network, or a 5xx) and `failed` (a batch was DROPPED: the server
10// refused it with a 4xx, and the person's Y.Doc now holds changes the
11// server never will). The last two are different words on purpose:
12// "Offline, retrying" on a batch nobody is retrying tells a person to
13// wait for something that will not happen.
14//
15// A slide that would not load is not a save state — savestatus has no
16// word for it — so it is its own line ([slides-load-error]), said until
17// a slide does load, and independent of whatever the save line says.
18
19/** The save queue's status word (save-queue.mjs) as a savestatus state. */
20export function queueStatusState (state) {
21 if (state === 'ok') return 'saved'
22 if (state === 'failed') return 'failed'
23 return 'retrying'
24}
25
26/**
27 * The state to show. A dropped batch outranks everything — it is the
28 * one fact the person has to act on — and stays for the session; then
29 * whatever the queue says.
30 */
31export function statusState ({ queueState = 'saved', sessionFailed = false } = {}) {
32 if (sessionFailed) return 'failed'
33 return queueState
34}
35
36/**
37 * The editor's status: setSave is savestatus's setter, errorEl the
38 * load-error line, errorText its words. Returns {save, drop,
39 * loadFailed}: save(state) records the queue's state (or re-shows the
40 * current one with no argument), drop() marks the session failed,
41 * loadFailed(bool) says or clears the load error.
42 */
43export function createEditorStatus ({ setSave, errorEl, errorText }) {
44 let queueState = 'saved'
45 let sessionFailed = false
46 function save (state) {
47 if (state) queueState = state
48 setSave(statusState({ queueState, sessionFailed }))
49 }
50 return {
51 save,
52 drop () { sessionFailed = true; save() },
53 loadFailed (failed) { if (errorEl) errorEl.textContent = failed ? (errorText || '') : '' }
54 }
55}
56
57/**
58 * Loads estilo's savestatus module (its fingerprinted URL is on the
59 * root as data-save-status-module) and mounts it on the line. A module
60 * that will not load leaves the load-error line saying so and rejects:
61 * an editor whose save line cannot move is one that would say "Saved"
62 * over changes it never saved.
63 */
64export async function mountSaveStatus (root, load = src => import(src)) {
65 const errorEl = root.querySelector('[slides-load-error]')
66 const errorText = root.dataset.textError
67 try {
68 const { mount } = await load(root.dataset.saveStatusModule)
69 return createEditorStatus({ setSave: mount(root.querySelector('[estilo-save-status]')), errorEl, errorText })
70 } catch (err) {
71 if (errorEl) errorEl.textContent = errorText || ''
72 throw err
73 }
74}
75