Fusion de la tête du chantier (924a40d : lots B2 et F) dans le lot D
Les deux côtés gardés partout. Aux coutures : - une objection (redit / contredit) porte sur deux articles, jamais sur un module ; un ordre ne se corrige pas, ni par son auteur ni par un autre ; une coquille du titre suit le chemin de F (l'auteur du titre, un administrateur pour le titre de départ, ou 3 jours), et documents.title suit à l'application ; - votable() couvre les modules ; leurs totaux passent par shown_tally, à l'écran et dans document.json ; - « Modules à voter » ne compte plus une version retenue par une objection (test vu rouge) ; la liste du groupe la compte toujours parmi les propositions en cours ; - le panier : une fonction pour les articles et les modules, avec les versions retenues de F ; un nouvel article se propose dans une section, à sa fin, et peut répondre à une objection ; - migrations 0007 (modules) puis 0008 (objections) ; - C25 et C26 supportent un groupe d'essai où une voix suffit (dès 16 membres). Boucle : fmt, clippy -D warnings, cargo test (227), svelte-check 0, vitest 55, build, e2e 35 / 35 (C1–C33 et M1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
// section entière, ou un article avec son titre, ou séparément »): choices
|
||||
// article by article, « tout pour » / « tout contre » for a section or the whole
|
||||
// document — never for an article whose versions compete —, then one gesture.
|
||||
// A version held back by an objection is shown, with nothing to choose.
|
||||
import { onMount } from 'svelte';
|
||||
import { clearScope, counts, fill, lines, sections, waiting, type Section, type Slot } from '$lib/basket';
|
||||
import { clearScope, counts, fill, lines, sections, votableIds, waiting, type Section, type Slot } from '$lib/basket';
|
||||
import type { DocState } from '$lib/doc.svelte';
|
||||
import { i18n, t } from '$lib/i18n/index.svelte';
|
||||
import { moduleName, relationOf, sectionLabel, titleOf } from '$lib/labels';
|
||||
@@ -35,7 +36,7 @@
|
||||
// The modules too (ADR 0009): the title first, each order at the end of its section.
|
||||
const all = $derived(sections(view?.units ?? [], view?.modules));
|
||||
const slots = $derived(all.flatMap((s) => s.slots));
|
||||
const known = $derived(new Set(slots.flatMap((s) => [...s.versions, ...s.inertia].map((p) => p.id))));
|
||||
const known = $derived(votableIds(all));
|
||||
const toSend = $derived(lines(basket.picks, known));
|
||||
const tally = $derived(counts(Object.fromEntries(Object.entries(basket.picks).filter(([id]) => known.has(id)))));
|
||||
const left = $derived(waiting(slots, basket.picks));
|
||||
@@ -50,7 +51,7 @@
|
||||
|
||||
function headline(s: Slot): string {
|
||||
if (s.unit.kind) return moduleName(s.unit);
|
||||
const text = s.versions.find((p) => p.kind === 'text');
|
||||
const text = [...s.versions, ...s.held].find((p) => p.kind === 'text');
|
||||
return text?.title ?? (s.versions[0] ? titleOf(s.versions[0], s.unit) : s.unit.code);
|
||||
}
|
||||
|
||||
@@ -125,7 +126,7 @@
|
||||
{#each s.slots as slot (slot.unit.id)}
|
||||
{@const title = headline(slot)}
|
||||
{@const several = slot.versions.length > 1}
|
||||
{@const first = slot.versions[0] ?? slot.inertia[0]}
|
||||
{@const first = slot.versions[0] ?? slot.inertia[0] ?? slot.held[0]}
|
||||
<li class="slot" class:several class:waiting={left.includes(slot)}>
|
||||
<button class="title" type="button" onclick={() => first && onread(first.id)}>{title}</button>
|
||||
{#if several}<p class="versions-note">{t('basket.versions')}</p>{/if}
|
||||
@@ -147,6 +148,15 @@
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
{#each slot.held as v (v.id)}
|
||||
<div class="version held">
|
||||
<span class="about">
|
||||
<span class="label">{labelOf(v, slot)}</span>
|
||||
<span class="faint small">{t('tally.short', { for: v.tally.for, against: v.tally.against })}</span>
|
||||
</span>
|
||||
<span class="held-note">{t('basket.held')}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
@@ -161,9 +171,11 @@
|
||||
<button class="btn primary" type="button" disabled={!open || !toSend.length || busy} onclick={send}>
|
||||
{access?.way === 'chain' ? t('basket.send.chain', { n: toSend.length }) : t('basket.send.server', { n: toSend.length })}
|
||||
</button>
|
||||
<p class="faint small note-send">
|
||||
{#if access?.way === 'chain' && access.chain}{t('basket.note.chain', { amount: g1Amount(access.chain.amount) })}{:else}{t('basket.note.server')}{/if}
|
||||
</p>
|
||||
{#if open}
|
||||
<p class="faint small note-send">
|
||||
{#if access?.way === 'chain' && access.chain}{t('basket.note.chain', { amount: g1Amount(access.chain.amount) })}{:else}{t('basket.note.server')}{/if}
|
||||
</p>
|
||||
{/if}
|
||||
{#if error}<p class="warn" role="alert">{error}</p>{/if}
|
||||
</footer>
|
||||
</section>
|
||||
@@ -281,6 +293,17 @@
|
||||
.small {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.version.held .label {
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.held-note {
|
||||
padding: 0.25rem 0.7rem;
|
||||
border-radius: var(--r-pill);
|
||||
background: var(--ochre-wash);
|
||||
color: var(--ochre);
|
||||
font-size: 0.8rem;
|
||||
font-weight: 750;
|
||||
}
|
||||
.send {
|
||||
position: sticky;
|
||||
bottom: -1.6rem;
|
||||
|
||||
Reference in New Issue
Block a user