Changeset 792af53 in Klonkt for src/assets/js/guardian.js


Ignore:
Timestamp:
08/07/2026 12:47:33 PM (5 weeks ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
0475b13, a29c8c8
Parents:
0db68bd
git-author:
Robin <roboburr@…> (08/07/2026 12:47:31 PM)
git-committer:
roboburr <roboburr@…> (08/07/2026 12:47:33 PM)
Message:

Het gate-paneel: een rij per gate, met het soort en de drempel (shaer-ahy.1)

Een guardian zag twee knoppen en moest zelf uitzoeken wat er verder voor dit kind
gold. Wat niet verstelbaar is stond nergens -- terwijl dat de helft is van het
antwoord op "wat mag dit kind".

EEN BRON VAN WAARHEID. GATE_CATALOGUE in gated.js is nu de lijst van gates die
deze Klonkt kent. Wat gated wordt is een ontwerpkeuze van de implementatie: de
FEP levert het mechanisme (voorstel, tally, settle) en een paar voorbeelden, niet
de lijst. Een gate erbij is daarmee een regel data en geen nieuw stuk scherm.

HET SOORT STAAT ERBIJ, want ze werken niet hetzelfde:

setting een stand, aan of uit, terug te draaien
perRequest geen stand maar een stroom beslissingen (5.3 volgverzoeken)
handover draagt gezag OVER, onomkeerbaar zodra de ward hem gebruikt

Die derde bestaat nog niet (shaer-90v), maar de rij kan hem al dragen -- inclusief
"niet terug te draaien", zodat dat er niet later ingebouwd hoeft te worden.

Volgverzoeken staan er nu ook in, met het aantal dat wacht. Ze zijn niet te
verzetten (altijd aan voor een ward, 5.3) en juist daarom horen ze zichtbaar te
zijn.

TWEE DINGEN DIE HET PANEEL NIET VERZINT. Een onbekende stand is ONBEKEND en niet
uit: bij een ward op een andere server staat die kolom daar. En zonder bekend
aantal guardians komt er geen drempel op het scherm -- nul of een gok leest als
een feit, en dit is precies waar een guardian op afgaat voordat hij iets
voorstelt.

De trap uit shaer-ahy blijft: afspelen is pas te bewegen als linkvoorbeelden
aanstaan. Met dezelfde uitzondering als voorheen -- onbekend telt niet als dicht,
want dat kostte ooit een hele voorstelronde.

Terugval ingebouwd: serveert een oudere Klonkt de catalogus nog niet, dan
verschijnen de twee knoppen zoals ze waren in plaats van een leeg vak.

9 tests op gateRows, dat pure stuk waar de regels in zitten. nl/en/de. Suite
565/565. Niet gedekt: de weergave zelf, dat is client-JS.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/assets/js/guardian.js

    r0db68bd r792af53  
    351351  }
    352352
     353  /** Het woord dat we voor een gate gebruiken; onbekend valt terug op de naam. */
     354  function gateLabel(feature) {
     355    return T['gate_' + feature.replace('shaer:', '')] || feature.replace('shaer:', '');
     356  }
     357
     358  /**
     359   * Een rij in het gate-paneel. Toont WAT er geldt, van welk SOORT het is, welke
     360   * drempel er hoort en wat er loopt -- en pas daarna een knop, als er iets te
     361   * verzetten valt.
     362   *
     363   * Het soort staat erbij omdat de gates niet hetzelfde werken: een stand is aan
     364   * of uit, volgverzoeken zijn een stroom beslissingen, en een overdracht is
     365   * onomkeerbaar zodra het kind hem gebruikt. Vier rijen met dezelfde schakelaar
     366   * zouden dat verschil wegpoetsen.
     367   */
     368  function gateRow(w, g) {
     369    var row = el('div', 'g-gate');
     370    var head = el('div', 'g-gate-head');
     371    head.appendChild(el('span', 'g-gate-name', gateLabel(g.feature)));
     372    head.appendChild(el('span', 'g-gate-kind', T['gate_kind_' + g.kind] || g.kind));
     373    row.appendChild(head);
     374
     375    // De stand. NULL is onbekend en dat is iets anders dan uit: bij een ward op
     376    // een andere server wordt die kolom daar bijgehouden.
     377    var stand = g.value === null || g.value === undefined
     378      ? (T.gate_unknown || 'unknown')
     379      : (g.value ? (T.prop_on || 'on') : (T.prop_off || 'off'));
     380    var meta = el('div', 'g-gate-meta small');
     381    meta.appendChild(el('span', null, stand));
     382    if (g.threshold) {
     383      meta.appendChild(el('span', null, (T.gate_threshold || '{need} of {of} guardians')
     384        .replace('{need}', g.threshold.need).replace('{of}', g.threshold.of)));
     385    } else {
     386      // Geen drempel verzinnen die we niet kennen.
     387      meta.appendChild(el('span', 'g-dim', T.gate_threshold_unknown || ''));
     388    }
     389    if (!g.reversible) meta.appendChild(el('span', 'g-gate-warn', T.gate_irreversible || ''));
     390    if (g.waiting) {
     391      meta.appendChild(el('span', 'g-gate-wait', (T.gate_waiting || '{n} waiting').replace('{n}', g.waiting)));
     392    }
     393    row.appendChild(meta);
     394
     395    if (g.proposal) {
     396      row.appendChild(el('p', 'small g-prop g-prop-' + g.proposal.status,
     397        (T.prop_line || 'Proposal {what} {value}: {status}')
     398          .replace('{what}', gateLabel(g.feature))
     399          .replace('{value}', g.proposal.value ? (T.prop_on || 'on') : (T.prop_off || 'off'))
     400          .replace('{status}', T['prop_st_' + g.proposal.status] || g.proposal.status)));
     401    }
     402    if (g.blockedBy) {
     403      row.appendChild(el('p', 'small g-empty', (T.gate_blocked || 'needs {what} first')
     404        .replace('{what}', gateLabel(g.blockedBy))));
     405    }
     406    if (g.adjustable) {
     407      row.appendChild(gateButton(w, g.feature, g.value, T.gate_propose || T.embeds_propose,
     408        T.prop_on || 'on', T.prop_off || 'off'));
     409    }
     410    return row;
     411  }
     412
    353413  function wardPanel(w) {
    354414    var uri = w.other_uri;
     
    358418    var set = el('div', 'g-panel-sec');
    359419    set.appendChild(el('h3', null, T.settings_title || 'Settings'));
    360     var setRow = el('div', 'row');
    361     setRow.appendChild(gateButton(w, 'shaer:externalEmbeds', w.embeds, T.embeds_propose, T.embeds_on, T.embeds_off));
    362     // The heavier sibling (5.6): seeing that a video exists is one decision,
    363     // letting a third party's player run inside the app is another. Hidden
    364     // only when previews are known-OFF: for a ward on another server the
    365     // value is unknown, and unknown is not off. Hiding it there meant a
    366     // guardian elsewhere could never even propose playback, which is how a
    367     // whole proposal round went into the wrong gate. The ward's server
    368     // enforces play-needs-previews at serve time regardless.
    369     if (w.embeds !== false) {
    370       setRow.appendChild(gateButton(w, 'shaer:externalPlayback', w.playback, T.play_propose, T.play_on, T.play_off));
    371     }
    372     set.appendChild(setRow);
    373     // What this guardian proposed and how it stands (5.6). This used to be a
    374     // button caption that vanished on refresh, so a running decision was
    375     // invisible: you could not tell "waiting", "done" and "expired" apart.
    376     (w.proposals || []).forEach(function (p) {
    377       var what = p.feature === 'shaer:externalPlayback' ? (T.prop_play || 'playback') : (T.prop_embeds || 'link previews');
    378       var line = (T.prop_line || 'Proposal {what} {value}: {status}')
    379         .replace('{what}', what)
    380         .replace('{value}', p.value ? (T.prop_on || 'on') : (T.prop_off || 'off'))
    381         .replace('{status}', T['prop_st_' + p.status] || p.status);
    382       set.appendChild(el('p', 'small g-prop g-prop-' + p.status, line));
    383     });
     420    // Een rij per gate, uit de catalogus van de server (shaer-ahy.1). Losse
     421    // knoppen lieten een guardian zelf uitzoeken wat er allemaal geldt, en wat
     422    // niet verstelbaar is stond nergens -- terwijl dat de helft van het antwoord
     423    // is op "wat mag dit kind".
     424    (w.gates || []).forEach(function (g) { set.appendChild(gateRow(w, g)); });
     425    // Terugval voor een server die de catalogus nog niet stuurt: dan de twee
     426    // knoppen zoals ze waren, zodat een oudere Klonkt niet met een leeg vak zit.
     427    if (!(w.gates || []).length) {
     428      var setRow = el('div', 'row');
     429      setRow.appendChild(gateButton(w, 'shaer:externalEmbeds', w.embeds, T.embeds_propose, T.embeds_on, T.embeds_off));
     430      if (w.embeds !== false) {
     431        setRow.appendChild(gateButton(w, 'shaer:externalPlayback', w.playback, T.play_propose, T.play_on, T.play_off));
     432      }
     433      set.appendChild(setRow);
     434      (w.proposals || []).forEach(function (p) {
     435        var what = p.feature === 'shaer:externalPlayback' ? (T.prop_play || 'playback') : (T.prop_embeds || 'link previews');
     436        set.appendChild(el('p', 'small g-prop g-prop-' + p.status, (T.prop_line || 'Proposal {what} {value}: {status}')
     437          .replace('{what}', what).replace('{value}', p.value ? (T.prop_on || 'on') : (T.prop_off || 'off'))
     438          .replace('{status}', T['prop_st_' + p.status] || p.status)));
     439      });
     440    }
    384441    panel.appendChild(set);
    385442
Note: See TracChangeset for help on using the changeset viewer.