Pages de lore en blocs (grille 2D libre) + bloc image recadrable, et import dd2vtt sur les scènes
All checks were successful
All checks were successful
Refonte du système de templates de lore en assemblage de blocs (façon Lore
d'Amsel), plus le support des cartes DungeonDraft (.dd2vtt) sur les scènes.
Templates de lore — éditeur de blocs en grille :
- Builder partagé `block-grid-builder` : palette de types de blocs à glisser sur
une grille 12 colonnes, placement LIBRE (x/y) et redimensionnement en largeur
ET hauteur par poignées, renommage en place. Remplace la liste + flèches de
template-create/template-edit (dédupliqués).
- Rendu : page-view (aperçu) honore largeur ET hauteur (grille à lignes fixes) ;
page-edit garde les colonnes (côte-à-côte) avec des hauteurs naturelles pour
l'édition. Repli empilé pour les templates sans mise en page.
- Modèle : `TemplateField` gagne `id` (clé stable) et `pos {x,y,w,h}`. Les valeurs
de page sont ancrées sur l'`id` (repli sur le nom) → renommer un bloc ne perd
plus son contenu. Sérialisation JSON additive, aucune migration ; correction au
passage de la non-relecture de `foundryPath` dans le converter.
Bloc image :
- Nouveau composant `image-block` (remplace la galerie pour les pages de lore) :
plusieurs images plein cadre (carrousel), déplacement (recadrage) et zoom
persistés PAR image et PAR page. Rendu `object-fit: contain` (image entière,
bordures noires) avec zoom 0,4×–4×.
- Stockage : `Page.imageFraming` (fieldKey → imageId → {x,y,scale}), colonne
`image_framing` (migration V8), DTO/mapper + passthrough export/import.
Scènes — source de carte au choix :
- Sélecteur Dungeon Alchemist (image/vidéo + .json, inchangé) / DungeonDraft
(.dd2vtt). Le .dd2vtt embarque l'image en base64 : extraction à l'upload
(→ média) + sidecar allégé (→ données) pour que l'export Foundry et le module
fonctionnent sans changement. Mode déduit à la relecture de l'extension.
Front-only, sans migration.
i18n fr/en, tests (converters back + helper front) et specs e2e mis à jour.
This commit is contained in:
@@ -1,5 +1,17 @@
|
||||
// Interfaces TypeScript pour PageDTO (Backend Java).
|
||||
|
||||
/**
|
||||
* Cadrage (pan/zoom) d'une image dans son bloc IMAGE.
|
||||
* Miroir de com.loremind.domain.lorecontext.ImageFraming.
|
||||
* - x, y : object-position en pourcentage (0..100), 50/50 = centré.
|
||||
* - scale : facteur de zoom (>= 1), 1 = plein cadre (cover).
|
||||
*/
|
||||
export interface ImageFraming {
|
||||
x: number;
|
||||
y: number;
|
||||
scale: number;
|
||||
}
|
||||
|
||||
export interface Page {
|
||||
id?: string;
|
||||
loreId: string;
|
||||
@@ -14,6 +26,11 @@ export interface Page {
|
||||
* uploadees (Shared Kernel images). Structure separee de `values`.
|
||||
*/
|
||||
imageValues?: Record<string, string[]>;
|
||||
/**
|
||||
* Cadrage (pan/zoom) des images : fieldKey → imageId → {x, y, scale}.
|
||||
* Purement présentationnel ; absence = cadrage par défaut (centré, plein cadre).
|
||||
*/
|
||||
imageFraming?: Record<string, Record<string, ImageFraming>>;
|
||||
/**
|
||||
* Pour chaque champ KEY_VALUE_LIST (tableau libelle → valeur, comme sur les
|
||||
* fiches de personnage) : fieldName → (label → valeur).
|
||||
|
||||
@@ -21,11 +21,34 @@ export type FieldType = 'TEXT' | 'IMAGE' | 'NUMBER' | 'KEY_VALUE_LIST' | 'TABLE'
|
||||
*/
|
||||
export type ImageLayout = 'GALLERY' | 'HERO' | 'MASONRY' | 'CAROUSEL' | 'EDITORIAL' | 'MAPS';
|
||||
|
||||
/**
|
||||
* Placement d'un bloc dans la grille 12 colonnes du template.
|
||||
* Miroir de com.loremind.domain.shared.template.BlockPosition.
|
||||
* Tout nullable : absence (ou coordonnees nulles) = auto-flow empile,
|
||||
* exactement le rendu historique en une seule colonne.
|
||||
*/
|
||||
export interface BlockPosition {
|
||||
/** Colonne de depart (0..11). */
|
||||
x?: number | null;
|
||||
/** Ligne de depart (0..n). */
|
||||
y?: number | null;
|
||||
/** Largeur en colonnes (1..12). */
|
||||
w?: number | null;
|
||||
/** Hauteur en lignes (1..n). */
|
||||
h?: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Champ d'un Template : nom + type discriminant.
|
||||
* Miroir de TemplateFieldDTO (backend).
|
||||
*/
|
||||
export interface TemplateField {
|
||||
/**
|
||||
* Identifiant STABLE du bloc : cle d'ancrage des valeurs de Page, survit aux
|
||||
* renommages. Retro-rempli avec le nom cote backend pour les templates
|
||||
* anterieurs (donc id == name au depart).
|
||||
*/
|
||||
id?: string;
|
||||
name: string;
|
||||
type: FieldType;
|
||||
/** Uniquement pour type='IMAGE'. Absent/null = 'GALLERY'. */
|
||||
@@ -37,6 +60,8 @@ export interface TemplateField {
|
||||
labels?: string[] | null;
|
||||
/** Chemin Foundry du champ (system.<path>) quand le template est calqué Foundry. */
|
||||
foundryPath?: string | null;
|
||||
/** Placement dans la grille 12 colonnes. Null = auto-flow empile (rendu historique). */
|
||||
pos?: BlockPosition | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user