The working screens of an evening. The home screen lists the events of the working folder, asks its question, loads demos, copies, renames, imports and deletes, and shows what the trash holds. An open event frames its mode, offers Modifier, Débloquer and a confirmed lock takeover, and shows its warnings. Participants get a grid, a form and a file; an import goes through a preview and a report; tables, the default and tours have their screens; the plan draws tables, chairs, empty seats and names. Checked: 2342 node, 356 browser, 60 node-long; the Electron start check. --- FR --- [ADD] interface : liste, événement, participants, import, tables, plan Les écrans de travail d'une soirée. L'accueil liste les événements du dossier de travail, pose sa question, charge les démonstrations, copie, renomme, importe et supprime, et montre ce que tient la corbeille. Un événement ouvert encadre son mode, offre Modifier, Débloquer et une reprise de verrou confirmée, et montre ses avertissements. Les participants ont une grille, un formulaire et une fiche ; un import passe par un aperçu et un rapport ; tables, défaut et tours ont leurs écrans ; le plan dessine tables, chaises, sièges vides et noms. Vérifié : 2342 node, 356 navigateur, 60 node-long ; démarrage d'Electron. Assisted-by: Claude Opus 5.5
140 lines
4.4 KiB
Svelte
140 lines
4.4 KiB
Svelte
<!-- © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) -->
|
|
|
|
<script>
|
|
// Le dossier de travail sur la liste (§ 8.6, § 8.8), dans cet ordre : la
|
|
// question qui attend sa réponse — elle vient avant toute liste, et nomme
|
|
// le dossier, la cause et ce qu'il porte ; la proposition d'importer
|
|
// l'autre emplacement, quand le dossier retenu est neuf et vide — son
|
|
// compte, puis son chemin dans son propre nœud (data-autre-chemin) —, avec
|
|
// la phrase sur les originaux ; les avis de la détermination, non modaux ;
|
|
// puis le chemin du dossier, en entier, et la commande qui l'ouvre dans
|
|
// l'explorateur, ou, sous web, la phrase qui dit pourquoi elle manque.
|
|
//
|
|
// issue : la détermination { dossier, avis } de la façade ; racine : le
|
|
// dossier de travail de la séance, null tant qu'une question attend ;
|
|
// avis : ceux à dire, vides hors du premier accueil de la séance ;
|
|
// explorateur : { disponible, raison } de la façade ; repondre(choix) et
|
|
// importerDepuisAutre(), les gestes de l'accueil ; reponseEnCours : vrai
|
|
// pendant une réponse, qui retire les réponses offertes ; importAutre : les
|
|
// comptes du dernier import, ou null ; lignesPresentes : le dossier retenu
|
|
// porte déjà des événements, et l'import de l'autre emplacement ne se
|
|
// propose plus.
|
|
import { getContext } from 'svelte';
|
|
import Commande from '../primitives/Commande.svelte';
|
|
import { reponsesDe, surLaListe } from './modele.js';
|
|
|
|
let {
|
|
issue,
|
|
racine,
|
|
avis,
|
|
explorateur,
|
|
repondre,
|
|
reponseEnCours,
|
|
importerDepuisAutre,
|
|
importAutre,
|
|
lignesPresentes,
|
|
} = $props();
|
|
|
|
const t = getContext('t');
|
|
const facade = getContext('facade');
|
|
const uid = $props.id();
|
|
|
|
const question = $derived(issue.dossier.question);
|
|
const autre = $derived(issue.dossier.autre);
|
|
const reponses = $derived(question === null ? [] : reponsesDe(question));
|
|
</script>
|
|
|
|
<section class="dossier" data-dossier>
|
|
{#if question !== null}
|
|
<div class="question" role="group" data-question={question.code} aria-labelledby={`${uid}-question`}>
|
|
<p id={`${uid}-question`}>{t(question.code, question)}</p>
|
|
{#if !reponseEnCours}
|
|
<div class="reponses">
|
|
{#each reponses as { choix, cle } (choix)}
|
|
<Commande {cle} executer={() => repondre(choix)} />
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
|
|
{#if autre !== null && !lignesPresentes}
|
|
<div class="autre" data-autre>
|
|
<p>{t('accueil.autre.proposition', { evenements: autre.evenements })}</p>
|
|
<p class="donnee" data-autre-chemin>{autre.racine.chemin}</p>
|
|
<p>{t('accueil.autre.originaux')}</p>
|
|
<Commande cle="accueil.autre.importer" nom="importerAutre" executer={importerDepuisAutre} />
|
|
</div>
|
|
{/if}
|
|
{#if importAutre !== null}
|
|
<p class="avis" role="status" data-avertissement="accueil.autre.resultat">{t('accueil.autre.resultat', importAutre)}</p>
|
|
{/if}
|
|
|
|
{#each avis as { code, details }, rang (rang)}
|
|
<p class="avis" role="status" data-avertissement={code}>{t(code, details)}</p>
|
|
{/each}
|
|
|
|
{#if question === null && racine !== null}
|
|
<div class="chemin">
|
|
<h2 id={`${uid}-titre`}>{t('accueil.dossier.titre')}</h2>
|
|
<p data-dossier-travail>{racine.chemin}</p>
|
|
{#if explorateur.disponible}
|
|
<Commande cle="accueil.dossier.explorateur" executer={() => surLaListe(() => facade.ouvrirExplorateur())} />
|
|
{:else}
|
|
<p class="avis" data-avertissement={explorateur.raison}>{t(explorateur.raison)}</p>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</section>
|
|
|
|
<style>
|
|
.dossier {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--espace-3);
|
|
}
|
|
|
|
h2,
|
|
p {
|
|
margin: 0;
|
|
}
|
|
|
|
h2 {
|
|
font-size: var(--taille-titre);
|
|
}
|
|
|
|
.question,
|
|
.autre {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: var(--espace-2);
|
|
padding: var(--espace-3);
|
|
border: 2px solid var(--couleur-avis);
|
|
border-radius: var(--rayon-2);
|
|
}
|
|
|
|
.reponses {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--espace-2);
|
|
}
|
|
|
|
.avis {
|
|
padding: var(--espace-1) var(--espace-2);
|
|
border-left: 3px solid var(--couleur-avis);
|
|
}
|
|
|
|
.chemin {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: var(--espace-2) var(--espace-3);
|
|
}
|
|
|
|
[data-dossier-travail],
|
|
.donnee {
|
|
overflow-wrap: anywhere;
|
|
}
|
|
</style>
|