update checklist component
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s

This commit is contained in:
Shinuwa 2026-07-24 13:38:17 +02:00
parent 772b9951de
commit d9d22683dc
13 changed files with 709 additions and 65 deletions

View file

@ -25,7 +25,7 @@ import {
const APP_STORAGE_WARNING_RATIO = 0.85;
const APP_STORAGE_SOFT_LIMIT_BYTES = 250 * 1024 * 1024;
const DRAWER_WIDTH_SETTING = "drawerWidth";
const ID_PREFIXES = { tbx: "t", mod: "m", item: "i", shot: "s", link: "l", counter: "c", calc: "r", marker: "k" };
const ID_PREFIXES = { tbx: "t", mod: "m", item: "i", section: "g", shot: "s", link: "l", counter: "c", calc: "r", marker: "k" };
const ID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
const TOOLBOX_ICON_BASE = "/static/img/toolbox-icons/";
const TOOLBOX_ICON_FILES = [
@ -127,10 +127,16 @@ const DEFAULT_SITE_CONTENT = {
notepad: { placeholder: "Notes rapides..." },
checklist: {
itemPlaceholder: "Nouvel item",
sectionPlaceholder: "Catégorie",
quantityLabel: "Quantité cible",
addButton: "Ajouter",
importPlaceholder: "Importer plusieurs items...\nPotion:10\nMéga potion:5",
importPlaceholder: "Importer plusieurs items...\n# Potions\nPotion:10\nMéga potion:5",
importOpenButton: "Importer du texte",
importModalTitle: "Importer une checklist",
importButton: "Importer le texte",
hideCompletedSectionsTitle: "Masquer les catégories terminées",
showCompletedSectionTitle: "Afficher cette catégorie terminée",
hideCompletedSectionTitle: "Masquer cette catégorie terminée",
decrementLabel: "Retirer une quantité",
incrementLabel: "Ajouter une quantité",
currentQuantityLabel: "Quantité actuelle",
@ -152,6 +158,8 @@ const DEFAULT_SITE_CONTENT = {
urlPlaceholder: "https://...",
addButton: "Ajouter",
importPlaceholder: "Importer plusieurs liens...\nBuild:https://example.com/build?class=rogue\nMap:https://example.com/map",
importOpenButton: "Importer du texte",
importModalTitle: "Importer des liens",
importButton: "Importer le texte",
copyTitle: "Copier",
copiedTitle: "Copié",
@ -251,6 +259,7 @@ function normalizeToolboxModule(module) {
const title = String(module.title || "").trim();
const normalized = { id: module.id || uid("mod"), type: module.type };
if (title && title !== getDefaultModuleTitle(module.type)) normalized.title = title;
if (module.scrollable === true) normalized.scrollable = true;
return normalized;
}
@ -314,10 +323,26 @@ function normalizeChecklistItem(item) {
};
}
function normalizeChecklistData(data) {
return {
items: (data?.items || []).map(normalizeChecklistItem).filter((item) => item.label)
function normalizeChecklistSection(section, fallbackTitle = "") {
const normalized = {
id: section?.id || uid("section"),
title: String(section?.title ?? fallbackTitle).trim(),
items: (section?.items || []).map(normalizeChecklistItem).filter((item) => item.label)
};
if (typeof section?.hideWhenComplete === "boolean") normalized.hideWhenComplete = section.hideWhenComplete;
if (section?.collapsed === true) normalized.collapsed = true;
return normalized;
}
function normalizeChecklistData(data) {
const hideCompletedSections = Boolean(data?.hideCompletedSections);
const sections = Array.isArray(data?.sections)
? data.sections.map((section) => normalizeChecklistSection(section)).filter((section) => section.items.length || section.title)
: [];
const legacyItems = (data?.items || []).map(normalizeChecklistItem).filter((item) => item.label);
if (!sections.length && legacyItems.length) return { hideCompletedSections, sections: [{ id: uid("section"), title: "", items: legacyItems }], items: legacyItems };
const items = sections.flatMap((section) => section.items);
return { hideCompletedSections, sections, items };
}
function normalizeUrl(value) {
@ -420,14 +445,30 @@ function compactChecklistItemForStorage(item) {
return compact;
}
function compactChecklistSectionForStorage(section) {
const normalized = normalizeChecklistSection(section);
const compact = {
id: normalized.id,
items: normalized.items.map(compactChecklistItemForStorage)
};
if (normalized.title) compact.title = normalized.title;
if (typeof normalized.hideWhenComplete === "boolean") compact.hideWhenComplete = normalized.hideWhenComplete;
if (normalized.collapsed === true) compact.collapsed = true;
return compact;
}
function compactModuleDataForStorage(type, value) {
if (type === "notepad") {
const text = String(value?.text || "");
return text ? { text } : null;
}
if (type === "checklist") {
const items = normalizeChecklistData(value).items.map(compactChecklistItemForStorage);
return items.length ? { items } : null;
const normalized = normalizeChecklistData(value);
const sections = normalized.sections.map(compactChecklistSectionForStorage).filter((section) => section.items.length || section.title);
if (!sections.length) return null;
const settings = normalized.hideCompletedSections ? { hideCompletedSections: true } : {};
if (sections.length === 1 && !sections[0].title && typeof sections[0].hideWhenComplete !== "boolean") return { ...settings, items: sections[0].items };
return { ...settings, sections };
}
if (type === "screenshots") {
const shots = (Array.isArray(value?.shots) ? value.shots : [])
@ -500,6 +541,15 @@ function remapModuleDataForExport(type, data, nextId) {
const compact = compactModuleDataForStorage(type, data);
if (!compact) return null;
if (type === "checklist") {
if (compact.sections) {
return {
sections: compact.sections.map((section) => ({
...section,
id: nextId("section"),
items: section.items.map((item) => ({ ...item, id: nextId("item") }))
}))
};
}
return { items: compact.items.map((item) => ({ ...item, id: nextId("item") })) };
}
if (type === "screenshots") {
@ -1568,6 +1618,7 @@ function ToolboxView({ siteContent, toolbox, toolboxGame, embedded, actions, sto
moduleColumns={moduleColumns}
context={moduleContext}
onRename={(moduleId, title) => updateToolbox({ ...toolbox, modules: toolbox.modules.map((module) => module.id === moduleId ? { ...module, title } : module) })}
onUpdateModule={(moduleId, updater) => updateToolbox({ ...toolbox, modules: toolbox.modules.map((module) => module.id === moduleId ? updater(module) : module) })}
onDelete={(moduleId) => actions.setConfirmModal({
title: "Retirer l'outil",
message: "Retirer cet outil de la toolbox ?",