Ajout de tableaux dans la partie templates / pages de lore : possibilité d'ajouter un tableau multiligne (par exemple pour faire des tableaux d'objets dans les boutiques) ; tableau type liste clé / valeur (pour des statistiques et ce genre de chose).
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m36s
Build & Push Images / build (core) (push) Successful in 1m53s
Build & Push Images / build-switcher (push) Successful in 25s
Build & Push Images / build (web) (push) Successful in 1m59s

Ajout de la possibilité de lié un PNJ à une page de lore
Ajout d'un graphe de liaison entre lore / PNJs
Passage en v.0.12.3-beta
This commit is contained in:
2026-06-12 13:23:46 +02:00
parent 7f519588b6
commit 14fc1c28fe
51 changed files with 1647 additions and 88 deletions

View File

@@ -3,7 +3,7 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { forkJoin } from 'rxjs';
import { LucideAngularModule, Sparkles } from 'lucide-angular';
import { LucideAngularModule, Sparkles, Plus, Trash2 } from 'lucide-angular';
import { LoreService } from '../../services/lore.service';
import { TemplateService } from '../../services/template.service';
import { PageService } from '../../services/page.service';
@@ -42,6 +42,8 @@ import { ConfirmDialogService } from '../../shared/confirm-dialog/confirm-dialog
})
export class PageEditComponent implements OnInit, OnDestroy {
readonly Sparkles = Sparkles;
readonly Plus = Plus;
readonly Trash2 = Trash2;
loreId = '';
pageId = '';
@@ -63,6 +65,10 @@ export class PageEditComponent implements OnInit, OnDestroy {
* la liste ordonnee des IDs d'images uploadees.
*/
imageValues: Record<string, string[]> = {};
/** Valeurs des champs KEY_VALUE_LIST (liste clé/valeur) : fieldName → (label → valeur). */
keyValueValues: Record<string, Record<string, string>> = {};
/** Valeurs des champs TABLE : fieldName → lignes (colonne → cellule). */
tableValues: Record<string, Array<Record<string, string>>> = {};
/** Étiquettes libres (Phase 5B). */
tags: string[] = [];
/** IDs des pages liées (Phase 5B). */
@@ -169,16 +175,27 @@ export class PageEditComponent implements OnInit, OnDestroy {
// structure `imageValues: Map<String, List<String>>` a l'etape 5).
const base: Record<string, string> = {};
const imageBase: Record<string, string[]> = {};
const kvBase: Record<string, Record<string, string>> = {};
const tableBase: Record<string, Array<Record<string, string>>> = {};
for (const f of this.template?.fields ?? []) {
if (f.type === 'TEXT') {
base[f.name] = page.values?.[f.name] ?? '';
} else if (f.type === 'IMAGE') {
// Initialise la galerie d'images pour ce champ (vide si jamais rempli).
imageBase[f.name] = [...(page.imageValues?.[f.name] ?? [])];
} else if (f.type === 'KEY_VALUE_LIST') {
// Toujours initialiser l'objet interne : le ngModel du formulaire
// bind directement keyValueValues[field.name][label].
kvBase[f.name] = { ...(page.keyValueValues?.[f.name] ?? {}) };
} else if (f.type === 'TABLE') {
// Copie profonde des lignes : chaque ligne est éditée par ngModel.
tableBase[f.name] = (page.tableValues?.[f.name] ?? []).map(row => ({ ...row }));
}
}
this.values = base;
this.imageValues = imageBase;
this.keyValueValues = kvBase;
this.tableValues = tableBase;
this.tags = [...(page.tags ?? [])];
this.relatedPageIds = [...(page.relatedPageIds ?? [])];
this.pageTitleService.set(page.title);
@@ -193,6 +210,8 @@ export class PageEditComponent implements OnInit, OnDestroy {
notes: this.notes,
values: this.values,
imageValues: this.imageValues,
keyValueValues: this.keyValueValues,
tableValues: this.tableValues,
tags: this.tags,
relatedPageIds: this.relatedPageIds
};
@@ -202,6 +221,20 @@ export class PageEditComponent implements OnInit, OnDestroy {
});
}
// --- Champs TABLE (lignes libres) ---------------------------------------
// Mutation en place des lignes : recréer le tableau à chaque frappe ferait
// perdre le focus de la cellule en cours d'édition.
addTableRow(fieldName: string, columns: string[] | null | undefined): void {
const row: Record<string, string> = {};
for (const col of columns ?? []) row[col] = '';
(this.tableValues[fieldName] ??= []).push(row);
}
removeTableRow(fieldName: string, rowIndex: number): void {
this.tableValues[fieldName]?.splice(rowIndex, 1);
}
// --- Chat IA conversationnel (Phase b5) --------------------------------
toggleChat(): void {