Amélioration de l'UI : meilleur affichage des images que ce soit dans la partie lore ou la partie campagne (partie campagne : visualisation scrapbooking). Possibilité de réordonner les champs dans les templates...

Passage v0.3.0
This commit is contained in:
2026-04-21 16:56:27 +02:00
parent 1e34f7f954
commit 71449bee1b
45 changed files with 1045 additions and 90 deletions

View File

@@ -2,13 +2,13 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { LucideAngularModule, Plus, Trash2, Type, Image as ImageIcon } from 'lucide-angular';
import { LucideAngularModule, Plus, Trash2, Type, Image as ImageIcon, ChevronUp, ChevronDown } from 'lucide-angular';
import { LoreService } from '../../services/lore.service';
import { TemplateService } from '../../services/template.service';
import { PageService } from '../../services/page.service';
import { LayoutService } from '../../services/layout.service';
import { LoreNode } from '../../services/lore.model';
import { FieldType, TemplateField } from '../../services/template.model';
import { FieldType, ImageLayout, TemplateField } from '../../services/template.model';
import { loadLoreSidebarData, buildLoreSidebarConfig } from '../lore-sidebar.helper';
/**
@@ -29,6 +29,8 @@ export class TemplateCreateComponent implements OnInit, OnDestroy {
readonly Trash2 = Trash2;
readonly Type = Type;
readonly ImageIcon = ImageIcon;
readonly ChevronUp = ChevronUp;
readonly ChevronDown = ChevronDown;
form: FormGroup;
loreId = '';
@@ -75,7 +77,10 @@ export class TemplateCreateComponent implements OnInit, OnDestroy {
if (!name) return;
// Unicite par nom (on ignore le type pour eviter des collisions d'affichage).
if (this.fields.some(f => f.name === name)) return;
this.fields = [...this.fields, { name, type: this.newFieldType }];
const newField: TemplateField = this.newFieldType === 'IMAGE'
? { name, type: 'IMAGE', layout: 'GALLERY' }
: { name, type: 'TEXT' };
this.fields = [...this.fields, newField];
this.newFieldName = '';
// Le type reste sur la derniere valeur choisie : pratique pour enchainer
// plusieurs champs du meme type.
@@ -85,12 +90,33 @@ export class TemplateCreateComponent implements OnInit, OnDestroy {
this.fields = this.fields.filter((_, i) => i !== index);
}
/** Deplace un champ d'un cran vers le haut ou le bas. No-op aux bords. */
moveField(index: number, direction: -1 | 1): void {
const target = index + direction;
if (target < 0 || target >= this.fields.length) return;
const next = [...this.fields];
[next[index], next[target]] = [next[target], next[index]];
this.fields = next;
}
/** Bascule le type d'un champ existant (TEXT <-> IMAGE). */
toggleFieldType(index: number): void {
const field = this.fields[index];
if (!field) return;
const nextType: FieldType = field.type === 'TEXT' ? 'IMAGE' : 'TEXT';
this.fields = this.fields.map((f, i) => i === index ? { ...f, type: nextType } : f);
this.fields = this.fields.map((f, i) => {
if (i !== index) return f;
return nextType === 'IMAGE'
? { name: f.name, type: 'IMAGE', layout: f.layout ?? 'GALLERY' }
: { name: f.name, type: 'TEXT' };
});
}
/** Met a jour le layout d'un champ IMAGE. */
setFieldLayout(index: number, layout: ImageLayout): void {
this.fields = this.fields.map((f, i) =>
i === index && f.type === 'IMAGE' ? { ...f, layout } : f
);
}
submit(): void {