v3 : modules d'ordre et de titre — l'interface, restes mineurs (L11, C25–C27)
Chaque section du lecteur finit par l'ordre de ses articles (inertie 2) : ses articles numérotés, son vote déplié, « Proposer un autre ordre » — une liste où l'on clique un article puis sa place, ses flèches, ou le clavier. Le titre du document (inertie 4) se vote et se propose sous le titre, « traduction à revoir » quand il a changé. Les deux sont dans la liste des propositions, le panier et la chaîne Ğ1 ; un nouvel article se propose dans une section, à sa fin. La liste du groupe compte les propositions ouvertes des modules. Restes mineurs : la participation ramenée se dit en deux temps (la mesure, puis ce que le groupe demande), les lignes « habituelle » des réglages resserrées, le sélecteur d'inertie se parcourt aux flèches (le cran actuel atteignable, jamais choisi), la marque « seed a minima » porte le vrai nombre de votes. Contrôles : C25 (ordre, dont la chaîne et le téléphone), C26 (titre), C27 (participation ramenée) ; C3, C17 (41 modules), C20 mis à jour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
// marks — and each unfolds its own vote.
|
||||
import type { Snippet } from 'svelte';
|
||||
import { plain } from '$lib/markdown';
|
||||
import { inertiaBadge, relationOf, titleOf } from '$lib/labels';
|
||||
import { i18n, t, type Key } from '$lib/i18n/index.svelte';
|
||||
import { inertiaBadge, moduleName, orderNote, relationOf, sectionLabel, titleOf } from '$lib/labels';
|
||||
import { i18n, t } from '$lib/i18n/index.svelte';
|
||||
import type { Proposal, Unit } from '$lib/types';
|
||||
import { excerpts, type Article } from '$lib/versions';
|
||||
import Icon from './Icon.svelte';
|
||||
@@ -18,7 +18,9 @@
|
||||
ontoggle,
|
||||
fold,
|
||||
onsection,
|
||||
nameOf = (id) => id,
|
||||
}: {
|
||||
/** Articles and modules (ADR 0009) with open proposals, in document order. */
|
||||
articles: Article[];
|
||||
/** The version whose vote is unfolded. */
|
||||
vote: string | null;
|
||||
@@ -26,10 +28,16 @@
|
||||
fold: Snippet<[Unit, Proposal]>;
|
||||
/** Opens the basket on a section; absent when this session does not vote here. */
|
||||
onsection?: (section: string) => void;
|
||||
/** The title of an article, for the orders proposed. */
|
||||
nameOf?: (unitId: string) => string;
|
||||
} = $props();
|
||||
|
||||
const SECTIONS = ['introduction', 'fondamental', 'technique', 'conclusion', 'annexe', 'formule', 'inertie', 'ordonnancement'];
|
||||
const sectionLabel = (s: string | null) => (s && SECTIONS.includes(s) ? t(`section.${s}` as Key) : null);
|
||||
/** What a line shows of a version: the start of its text, or the order it proposes. */
|
||||
function excerptOf(p: Proposal): string {
|
||||
if (p.kind === 'text') return plain(p.body);
|
||||
if (p.kind === 'order') return (p.order?.ids ?? []).map(nameOf).join(' · ');
|
||||
return '';
|
||||
}
|
||||
|
||||
// Unfolded by hand, or because the version whose vote is unfolded is inside.
|
||||
let unfolded = $state<Record<string, boolean>>({});
|
||||
@@ -38,6 +46,7 @@
|
||||
|
||||
/** The title of the article: its best text version, or what the best proposal is. */
|
||||
function headline(a: Article): string {
|
||||
if (a.unit.kind) return moduleName(a.unit);
|
||||
const text = a.versions.find((p) => p.kind === 'text');
|
||||
const best = a.versions[0];
|
||||
return text ? text.title : best ? titleOf(best, a.unit) : a.unit.code;
|
||||
@@ -45,7 +54,7 @@
|
||||
|
||||
/** What tells a version from its siblings: its variant, its author, or its rank of arrival. */
|
||||
function labelOf(p: Proposal, a: Article): string {
|
||||
if (p.kind !== 'text') return titleOf(p, a.unit);
|
||||
if (p.kind === 'inertia' || p.kind === 'remove') return titleOf(p, a.unit);
|
||||
if (p.label) return t('deep.variant', { label: p.label });
|
||||
if (p.author?.name) return t('panel.by', { name: p.author.name });
|
||||
const arrival = a.unit.proposals.filter((x) => x.status === 'open').findIndex((x) => x.id === p.id);
|
||||
@@ -56,10 +65,18 @@
|
||||
function toldApart(a: Article): Map<string, string> {
|
||||
const textual = a.versions.filter((p) => p.kind === 'text');
|
||||
const told = excerpts(textual.map((p) => plain(p.body)));
|
||||
return new Map(textual.map((p, k) => [p.id, told[k] ?? plain(p.body)]));
|
||||
return new Map([
|
||||
...a.versions.map((p): [string, string] => [p.id, excerptOf(p)]),
|
||||
...textual.map((p, k): [string, string] => [p.id, told[k] ?? plain(p.body)]),
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet module(p: Proposal)}
|
||||
{#if p.kind === 'title'}<span class="faint">{t('module.title.name')}</span>{/if}
|
||||
{#each orderNote(p) as note (note)}<span class="faint">{note}</span>{/each}
|
||||
{/snippet}
|
||||
|
||||
{#snippet marks(p: Proposal)}
|
||||
{#if p.evaluation?.wellRated}<span class="tag water">{t('deep.wellrated')}</span>{/if}
|
||||
{#if p.blocked}<span class="tag ochre">{t('deep.blocked')}</span>{/if}
|
||||
@@ -86,11 +103,12 @@
|
||||
<WaterLevel tally={best.tally} evaluation={best.evaluation} blocked={best.blocked} />
|
||||
<span class="main">
|
||||
<span class="title">{titleOf(best, unit)}</span>
|
||||
{#if best.kind === 'text'}<span class="excerpt">{plain(best.body)}</span>{/if}
|
||||
{#if excerptOf(best)}<span class="excerpt">{excerptOf(best)}</span>{/if}
|
||||
<span class="meta">
|
||||
<span>{t('tally.short', { for: best.tally.for, against: best.tally.against })}</span>
|
||||
{#if relationOf(best, unit)}<span class="faint">{relationOf(best, unit)}</span>{/if}
|
||||
{#if unit.inertia !== 3}<span class="faint">{inertiaBadge(unit.inertia)}</span>{/if}
|
||||
{@render module(best)}
|
||||
{@render marks(best)}
|
||||
</span>
|
||||
</span>
|
||||
@@ -106,7 +124,7 @@
|
||||
<WaterLevel tally={best.tally} evaluation={best.evaluation} blocked={best.blocked} />
|
||||
<span class="main">
|
||||
<span class="title">{title}</span>
|
||||
{#if best.kind === 'text'}<span class="excerpt">{plain(best.body)}</span>{/if}
|
||||
{#if excerptOf(best)}<span class="excerpt">{excerptOf(best)}</span>{/if}
|
||||
<span class="meta">
|
||||
<span class="count">{i18n.plural('deep.versions', a.versions.length)}</span>
|
||||
{#if a.leads}<span>{t('deep.lead', { label: labelOf(best, a) })}</span>{/if}
|
||||
@@ -126,10 +144,11 @@
|
||||
<button type="button" class="version" class:current={vote === p.id} aria-expanded={vote === p.id} aria-controls="vote-{p.id}" onclick={() => ontoggle(unit, p)}>
|
||||
<WaterLevel tally={p.tally} evaluation={p.evaluation} blocked={p.blocked} />
|
||||
<span class="main">
|
||||
<span class="label">{labelOf(p, a)}{#if p.kind === 'text' && p.title !== title}<span class="other"> · {p.title}</span>{/if}</span>
|
||||
{#if p.kind === 'text'}<span class="excerpt">{told.get(p.id)}</span>{/if}
|
||||
<span class="label">{labelOf(p, a)}{#if (p.kind === 'text' || p.kind === 'title') && p.title !== title}<span class="other"> · {p.title}</span>{/if}</span>
|
||||
{#if told.get(p.id)}<span class="excerpt">{told.get(p.id)}</span>{/if}
|
||||
<span class="meta">
|
||||
<span>{t('tally.short', { for: p.tally.for, against: p.tally.against })}</span>
|
||||
{#each orderNote(p) as note (note)}<span class="faint">{note}</span>{/each}
|
||||
{@render marks(p)}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user