From b3e0e0883b86d5d8b49cf037cbd13531c54b60f1 Mon Sep 17 00:00:00 2001 From: "IETM_FIXE\\ietm6" Date: Sun, 19 Apr 2026 12:08:16 +0200 Subject: [PATCH] Initial commit - LoreMind project --- core/pom.xml | 83 + .../com/loremind/LoreMindApplication.java | 16 + .../campaigncontext/ArcService.java | 76 + .../campaigncontext/CampaignService.java | 84 + .../campaigncontext/ChapterService.java | 73 + .../campaigncontext/SceneService.java | 78 + .../lorecontext/LoreNodeService.java | 78 + .../application/lorecontext/LoreService.java | 93 + .../application/lorecontext/PageService.java | 95 + .../lorecontext/TemplateService.java | 84 + .../loremind/domain/campaigncontext/Arc.java | 60 + .../domain/campaigncontext/Campaign.java | 59 + .../domain/campaigncontext/Chapter.java | 54 + .../domain/campaigncontext/Scene.java | 67 + .../campaigncontext/ports/ArcRepository.java | 24 + .../ports/CampaignRepository.java | 24 + .../ports/ChapterRepository.java | 24 + .../ports/SceneRepository.java | 24 + .../com/loremind/domain/lorecontext/Lore.java | 48 + .../loremind/domain/lorecontext/LoreNode.java | 42 + .../com/loremind/domain/lorecontext/Page.java | 82 + .../loremind/domain/lorecontext/Template.java | 61 + .../lorecontext/ports/LoreNodeRepository.java | 30 + .../lorecontext/ports/LoreRepository.java | 25 + .../lorecontext/ports/PageRepository.java | 32 + .../lorecontext/ports/TemplateRepository.java | 27 + .../converter/MapJsonConverter.java | 44 + .../converter/StringListJsonConverter.java | 46 + .../converter/StringMapJsonConverter.java | 44 + .../persistence/entity/ArcJpaEntity.java | 81 + .../persistence/entity/CampaignJpaEntity.java | 58 + .../persistence/entity/ChapterJpaEntity.java | 71 + .../persistence/entity/LoreJpaEntity.java | 54 + .../persistence/entity/LoreNodeJpaEntity.java | 55 + .../persistence/entity/PageJpaEntity.java | 76 + .../persistence/entity/SceneJpaEntity.java | 92 + .../persistence/entity/TemplateJpaEntity.java | 63 + .../persistence/jpa/ArcJpaRepository.java | 16 + .../jpa/CampaignJpaRepository.java | 19 + .../persistence/jpa/ChapterJpaRepository.java | 16 + .../persistence/jpa/LoreJpaRepository.java | 17 + .../jpa/LoreNodeJpaRepository.java | 22 + .../persistence/jpa/PageJpaRepository.java | 24 + .../persistence/jpa/SceneJpaRepository.java | 16 + .../jpa/TemplateJpaRepository.java | 18 + .../postgres/PostgresArcRepository.java | 108 + .../postgres/PostgresCampaignRepository.java | 89 + .../postgres/PostgresChapterRepository.java | 103 + .../postgres/PostgresLoreNodeRepository.java | 118 + .../postgres/PostgresLoreRepository.java | 92 + .../postgres/PostgresPageRepository.java | 130 + .../postgres/PostgresSceneRepository.java | 113 + .../postgres/PostgresTemplateRepository.java | 97 + .../infrastructure/web/config/CorsConfig.java | 29 + .../web/controller/ArcController.java | 71 + .../web/controller/CampaignController.java | 77 + .../web/controller/ChapterController.java | 71 + .../web/controller/LoreController.java | 72 + .../web/controller/LoreNodeController.java | 100 + .../web/controller/PageController.java | 89 + .../web/controller/SceneController.java | 71 + .../web/controller/TemplateController.java | 82 + .../web/dto/campaigncontext/ArcDTO.java | 29 + .../web/dto/campaigncontext/CampaignDTO.java | 18 + .../web/dto/campaigncontext/ChapterDTO.java | 27 + .../web/dto/campaigncontext/SceneDTO.java | 32 + .../web/dto/lorecontext/LoreDTO.java | 18 + .../web/dto/lorecontext/LoreNodeDTO.java | 17 + .../web/dto/lorecontext/PageDTO.java | 24 + .../web/dto/lorecontext/TemplateDTO.java | 22 + .../infrastructure/web/mapper/ArcMapper.java | 58 + .../web/mapper/CampaignMapper.java | 40 + .../web/mapper/ChapterMapper.java | 54 + .../infrastructure/web/mapper/LoreMapper.java | 41 + .../web/mapper/LoreNodeMapper.java | 40 + .../infrastructure/web/mapper/PageMapper.java | 49 + .../web/mapper/SceneMapper.java | 64 + .../web/mapper/TemplateMapper.java | 47 + .../src/main/resources/application.properties | 20 + .../postgres/PostgresLoreRepositoryTest.java | 103 + .../src/test/resources/application.properties | 10 + docs/Documentation_projet.docx | Bin 0 -> 20398 bytes docs/loremind-contexte.md | 33 + .../campagne/Accueil partie campagne.png | Bin 0 -> 70874 bytes docs/maquettes/campagne/Assistance IA.png | Bin 0 -> 114853 bytes .../campagne/Création d'un nouvel arc.png | Bin 0 -> 68740 bytes .../campagne/Création de chapitre.png | Bin 0 -> 72401 bytes docs/maquettes/campagne/Création de scène.png | Bin 0 -> 75390 bytes .../Ecran de création de campagne.png | Bin 0 -> 53701 bytes .../maquettes/campagne/Modification d'arc.png | Bin 0 -> 79780 bytes .../campagne/Modification d'un chapitre.png | Bin 0 -> 82233 bytes .../campagne/Modification de scène.png | Bin 0 -> 87232 bytes .../campagne/Sauvegarde de la campagne.png | Bin 0 -> 102829 bytes .../détail/Modification arc détail 2.png | Bin 0 -> 101572 bytes .../détail/Modification arc détail 3.png | Bin 0 -> 96754 bytes .../détail/Modification chapitre détail 2.png | Bin 0 -> 96226 bytes .../détail/Modification chapitre détail 3.png | Bin 0 -> 96932 bytes .../détail/Modification de scène détail 2.png | Bin 0 -> 105200 bytes .../détail/Modification de scène détail 3.png | Bin 0 -> 100912 bytes .../détail/Modification de scène détail 4.png | Bin 0 -> 101683 bytes docs/maquettes/général/Accueil.png | Bin 0 -> 39462 bytes docs/maquettes/général/Ecran de recherche.png | Bin 0 -> 115377 bytes docs/maquettes/lore/Accueil Lore.png | Bin 0 -> 62967 bytes .../lore/Assistance IA dans une page.png | Bin 0 -> 114904 bytes docs/maquettes/lore/Création d'un Lore.png | Bin 0 -> 55187 bytes docs/maquettes/lore/Création de noeud.png | Bin 0 -> 104878 bytes docs/maquettes/lore/Création de template.png | Bin 0 -> 86320 bytes .../lore/Modification d'une page.png | Bin 0 -> 78772 bytes .../lore/Modification de template.png | Bin 0 -> 77387 bytes docs/maquettes/lore/création de page.png | Bin 0 -> 83688 bytes docs/plan.md | 407 + web/angular.json | 42 + web/package-lock.json | 12174 ++++++++++++++++ web/package.json | 33 + web/src/app/app.component.html | 18 + web/src/app/app.component.scss | 10 + web/src/app/app.component.ts | 33 + web/src/app/app.routes.ts | 23 + .../arc-create/arc-create.component.html | 37 + .../arc-create/arc-create.component.scss | 18 + .../arc-create/arc-create.component.ts | 95 + .../arc-edit/arc-edit.component.html | 110 + .../arc-edit/arc-edit.component.scss | 21 + .../campaigns/arc-edit/arc-edit.component.ts | 168 + .../campaign-create.component.html | 69 + .../campaign-create.component.scss | 123 + .../campaign-create.component.ts | 69 + .../campaign-detail.component.html | 93 + .../campaign-detail.component.scss | 203 + .../campaign-detail.component.ts | 194 + web/src/app/campaigns/campaign-tree.helper.ts | 95 + .../app/campaigns/campaigns.component.html | 42 + .../app/campaigns/campaigns.component.scss | 99 + web/src/app/campaigns/campaigns.component.ts | 60 + .../chapter-create.component.html | 38 + .../chapter-create.component.scss | 21 + .../chapter-create.component.ts | 97 + .../chapter-edit/chapter-edit.component.html | 92 + .../chapter-edit/chapter-edit.component.scss | 18 + .../chapter-edit/chapter-edit.component.ts | 157 + .../scene-create/scene-create.component.html | 38 + .../scene-create/scene-create.component.scss | 18 + .../scene-create/scene-create.component.ts | 99 + .../scene-edit/scene-edit.component.html | 137 + .../scene-edit/scene-edit.component.scss | 18 + .../scene-edit/scene-edit.component.ts | 179 + .../lore-create/lore-create.component.html | 54 + .../lore-create/lore-create.component.scss | 123 + .../lore/lore-create/lore-create.component.ts | 37 + .../lore-detail/lore-detail.component.html | 70 + .../lore-detail/lore-detail.component.scss | 160 + .../lore/lore-detail/lore-detail.component.ts | 137 + web/src/app/lore/lore-icons.ts | 53 + .../lore-node-create.component.html | 71 + .../lore-node-create.component.scss | 116 + .../lore-node-create.component.ts | 104 + .../lore-node-edit.component.html | 67 + .../lore-node-edit.component.scss | 141 + .../lore-node-edit.component.ts | 163 + web/src/app/lore/lore-sidebar.helper.ts | 162 + web/src/app/lore/lore.component.html | 42 + web/src/app/lore/lore.component.scss | 102 + web/src/app/lore/lore.component.ts | 72 + .../page-create/page-create.component.html | 66 + .../page-create/page-create.component.scss | 159 + .../lore/page-create/page-create.component.ts | 112 + .../lore/page-edit/page-edit.component.html | 90 + .../lore/page-edit/page-edit.component.scss | 122 + .../app/lore/page-edit/page-edit.component.ts | 184 + .../template-create.component.html | 72 + .../template-create.component.scss | 180 + .../template-create.component.ts | 95 + .../template-edit.component.html | 72 + .../template-edit.component.scss | 205 + .../template-edit/template-edit.component.ts | 119 + web/src/app/services/campaign.model.ts | 120 + web/src/app/services/campaign.service.ts | 105 + web/src/app/services/global-search.service.ts | 16 + web/src/app/services/layout.service.ts | 101 + web/src/app/services/lore.model.ts | 37 + web/src/app/services/lore.service.ts | 69 + web/src/app/services/page-title.service.ts | 25 + web/src/app/services/page.model.ts | 21 + web/src/app/services/page.service.ts | 48 + web/src/app/services/template.model.ts | 20 + web/src/app/services/template.service.ts | 42 + .../breadcrumb/breadcrumb.component.html | 12 + .../breadcrumb/breadcrumb.component.scss | 50 + .../shared/breadcrumb/breadcrumb.component.ts | 35 + .../chips-input/chips-input.component.html | 15 + .../chips-input/chips-input.component.scss | 53 + .../chips-input/chips-input.component.ts | 68 + .../expandable-section.component.html | 15 + .../expandable-section.component.scss | 49 + .../expandable-section.component.ts | 39 + .../global-search.component.html | 51 + .../global-search.component.scss | 118 + .../global-search/global-search.component.ts | 216 + .../lore-link-picker.component.html | 42 + .../lore-link-picker.component.scss | 114 + .../lore-link-picker.component.ts | 96 + .../secondary-sidebar.component.html | 82 + .../secondary-sidebar.component.scss | 217 + .../secondary-sidebar.component.ts | 115 + web/src/app/sidebar/sidebar.component.html | 66 + web/src/app/sidebar/sidebar.component.scss | 186 + web/src/app/sidebar/sidebar.component.ts | 46 + web/src/index.html | 13 + web/src/main.ts | 9 + web/src/styles.scss | 20 + web/src/styles/_buttons.scss | 75 + web/src/styles/_forms.scss | 89 + web/tsconfig.json | 32 + 213 files changed, 25358 insertions(+) create mode 100644 core/pom.xml create mode 100644 core/src/main/java/com/loremind/LoreMindApplication.java create mode 100644 core/src/main/java/com/loremind/application/campaigncontext/ArcService.java create mode 100644 core/src/main/java/com/loremind/application/campaigncontext/CampaignService.java create mode 100644 core/src/main/java/com/loremind/application/campaigncontext/ChapterService.java create mode 100644 core/src/main/java/com/loremind/application/campaigncontext/SceneService.java create mode 100644 core/src/main/java/com/loremind/application/lorecontext/LoreNodeService.java create mode 100644 core/src/main/java/com/loremind/application/lorecontext/LoreService.java create mode 100644 core/src/main/java/com/loremind/application/lorecontext/PageService.java create mode 100644 core/src/main/java/com/loremind/application/lorecontext/TemplateService.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/Arc.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/Campaign.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/Chapter.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/Scene.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/ports/ArcRepository.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/ports/CampaignRepository.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/ports/ChapterRepository.java create mode 100644 core/src/main/java/com/loremind/domain/campaigncontext/ports/SceneRepository.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/Lore.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/LoreNode.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/Page.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/Template.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/ports/LoreNodeRepository.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/ports/LoreRepository.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/ports/PageRepository.java create mode 100644 core/src/main/java/com/loremind/domain/lorecontext/ports/TemplateRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/converter/MapJsonConverter.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/converter/StringListJsonConverter.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/converter/StringMapJsonConverter.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/ArcJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/CampaignJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/ChapterJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/LoreJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/LoreNodeJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/PageJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/SceneJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/entity/TemplateJpaEntity.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/ArcJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/CampaignJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/ChapterJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/LoreJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/LoreNodeJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/PageJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/SceneJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/jpa/TemplateJpaRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresArcRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresCampaignRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresChapterRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresLoreNodeRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresLoreRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresPageRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresSceneRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/persistence/postgres/PostgresTemplateRepository.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/config/CorsConfig.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/ArcController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/CampaignController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/ChapterController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/LoreController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/LoreNodeController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/PageController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/SceneController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/controller/TemplateController.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ArcDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/CampaignDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ChapterDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/SceneDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/lorecontext/LoreDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/lorecontext/LoreNodeDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/lorecontext/PageDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/dto/lorecontext/TemplateDTO.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/ArcMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/CampaignMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/ChapterMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/LoreMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/LoreNodeMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/PageMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/SceneMapper.java create mode 100644 core/src/main/java/com/loremind/infrastructure/web/mapper/TemplateMapper.java create mode 100644 core/src/main/resources/application.properties create mode 100644 core/src/test/java/com/loremind/infrastructure/persistence/postgres/PostgresLoreRepositoryTest.java create mode 100644 core/src/test/resources/application.properties create mode 100644 docs/Documentation_projet.docx create mode 100644 docs/loremind-contexte.md create mode 100644 docs/maquettes/campagne/Accueil partie campagne.png create mode 100644 docs/maquettes/campagne/Assistance IA.png create mode 100644 docs/maquettes/campagne/Création d'un nouvel arc.png create mode 100644 docs/maquettes/campagne/Création de chapitre.png create mode 100644 docs/maquettes/campagne/Création de scène.png create mode 100644 docs/maquettes/campagne/Ecran de création de campagne.png create mode 100644 docs/maquettes/campagne/Modification d'arc.png create mode 100644 docs/maquettes/campagne/Modification d'un chapitre.png create mode 100644 docs/maquettes/campagne/Modification de scène.png create mode 100644 docs/maquettes/campagne/Sauvegarde de la campagne.png create mode 100644 docs/maquettes/campagne/détail/Modification arc détail 2.png create mode 100644 docs/maquettes/campagne/détail/Modification arc détail 3.png create mode 100644 docs/maquettes/campagne/détail/Modification chapitre détail 2.png create mode 100644 docs/maquettes/campagne/détail/Modification chapitre détail 3.png create mode 100644 docs/maquettes/campagne/détail/Modification de scène détail 2.png create mode 100644 docs/maquettes/campagne/détail/Modification de scène détail 3.png create mode 100644 docs/maquettes/campagne/détail/Modification de scène détail 4.png create mode 100644 docs/maquettes/général/Accueil.png create mode 100644 docs/maquettes/général/Ecran de recherche.png create mode 100644 docs/maquettes/lore/Accueil Lore.png create mode 100644 docs/maquettes/lore/Assistance IA dans une page.png create mode 100644 docs/maquettes/lore/Création d'un Lore.png create mode 100644 docs/maquettes/lore/Création de noeud.png create mode 100644 docs/maquettes/lore/Création de template.png create mode 100644 docs/maquettes/lore/Modification d'une page.png create mode 100644 docs/maquettes/lore/Modification de template.png create mode 100644 docs/maquettes/lore/création de page.png create mode 100644 docs/plan.md create mode 100644 web/angular.json create mode 100644 web/package-lock.json create mode 100644 web/package.json create mode 100644 web/src/app/app.component.html create mode 100644 web/src/app/app.component.scss create mode 100644 web/src/app/app.component.ts create mode 100644 web/src/app/app.routes.ts create mode 100644 web/src/app/campaigns/arc-create/arc-create.component.html create mode 100644 web/src/app/campaigns/arc-create/arc-create.component.scss create mode 100644 web/src/app/campaigns/arc-create/arc-create.component.ts create mode 100644 web/src/app/campaigns/arc-edit/arc-edit.component.html create mode 100644 web/src/app/campaigns/arc-edit/arc-edit.component.scss create mode 100644 web/src/app/campaigns/arc-edit/arc-edit.component.ts create mode 100644 web/src/app/campaigns/campaign-create/campaign-create.component.html create mode 100644 web/src/app/campaigns/campaign-create/campaign-create.component.scss create mode 100644 web/src/app/campaigns/campaign-create/campaign-create.component.ts create mode 100644 web/src/app/campaigns/campaign-detail/campaign-detail.component.html create mode 100644 web/src/app/campaigns/campaign-detail/campaign-detail.component.scss create mode 100644 web/src/app/campaigns/campaign-detail/campaign-detail.component.ts create mode 100644 web/src/app/campaigns/campaign-tree.helper.ts create mode 100644 web/src/app/campaigns/campaigns.component.html create mode 100644 web/src/app/campaigns/campaigns.component.scss create mode 100644 web/src/app/campaigns/campaigns.component.ts create mode 100644 web/src/app/campaigns/chapter-create/chapter-create.component.html create mode 100644 web/src/app/campaigns/chapter-create/chapter-create.component.scss create mode 100644 web/src/app/campaigns/chapter-create/chapter-create.component.ts create mode 100644 web/src/app/campaigns/chapter-edit/chapter-edit.component.html create mode 100644 web/src/app/campaigns/chapter-edit/chapter-edit.component.scss create mode 100644 web/src/app/campaigns/chapter-edit/chapter-edit.component.ts create mode 100644 web/src/app/campaigns/scene-create/scene-create.component.html create mode 100644 web/src/app/campaigns/scene-create/scene-create.component.scss create mode 100644 web/src/app/campaigns/scene-create/scene-create.component.ts create mode 100644 web/src/app/campaigns/scene-edit/scene-edit.component.html create mode 100644 web/src/app/campaigns/scene-edit/scene-edit.component.scss create mode 100644 web/src/app/campaigns/scene-edit/scene-edit.component.ts create mode 100644 web/src/app/lore/lore-create/lore-create.component.html create mode 100644 web/src/app/lore/lore-create/lore-create.component.scss create mode 100644 web/src/app/lore/lore-create/lore-create.component.ts create mode 100644 web/src/app/lore/lore-detail/lore-detail.component.html create mode 100644 web/src/app/lore/lore-detail/lore-detail.component.scss create mode 100644 web/src/app/lore/lore-detail/lore-detail.component.ts create mode 100644 web/src/app/lore/lore-icons.ts create mode 100644 web/src/app/lore/lore-node-create/lore-node-create.component.html create mode 100644 web/src/app/lore/lore-node-create/lore-node-create.component.scss create mode 100644 web/src/app/lore/lore-node-create/lore-node-create.component.ts create mode 100644 web/src/app/lore/lore-node-edit/lore-node-edit.component.html create mode 100644 web/src/app/lore/lore-node-edit/lore-node-edit.component.scss create mode 100644 web/src/app/lore/lore-node-edit/lore-node-edit.component.ts create mode 100644 web/src/app/lore/lore-sidebar.helper.ts create mode 100644 web/src/app/lore/lore.component.html create mode 100644 web/src/app/lore/lore.component.scss create mode 100644 web/src/app/lore/lore.component.ts create mode 100644 web/src/app/lore/page-create/page-create.component.html create mode 100644 web/src/app/lore/page-create/page-create.component.scss create mode 100644 web/src/app/lore/page-create/page-create.component.ts create mode 100644 web/src/app/lore/page-edit/page-edit.component.html create mode 100644 web/src/app/lore/page-edit/page-edit.component.scss create mode 100644 web/src/app/lore/page-edit/page-edit.component.ts create mode 100644 web/src/app/lore/template-create/template-create.component.html create mode 100644 web/src/app/lore/template-create/template-create.component.scss create mode 100644 web/src/app/lore/template-create/template-create.component.ts create mode 100644 web/src/app/lore/template-edit/template-edit.component.html create mode 100644 web/src/app/lore/template-edit/template-edit.component.scss create mode 100644 web/src/app/lore/template-edit/template-edit.component.ts create mode 100644 web/src/app/services/campaign.model.ts create mode 100644 web/src/app/services/campaign.service.ts create mode 100644 web/src/app/services/global-search.service.ts create mode 100644 web/src/app/services/layout.service.ts create mode 100644 web/src/app/services/lore.model.ts create mode 100644 web/src/app/services/lore.service.ts create mode 100644 web/src/app/services/page-title.service.ts create mode 100644 web/src/app/services/page.model.ts create mode 100644 web/src/app/services/page.service.ts create mode 100644 web/src/app/services/template.model.ts create mode 100644 web/src/app/services/template.service.ts create mode 100644 web/src/app/shared/breadcrumb/breadcrumb.component.html create mode 100644 web/src/app/shared/breadcrumb/breadcrumb.component.scss create mode 100644 web/src/app/shared/breadcrumb/breadcrumb.component.ts create mode 100644 web/src/app/shared/chips-input/chips-input.component.html create mode 100644 web/src/app/shared/chips-input/chips-input.component.scss create mode 100644 web/src/app/shared/chips-input/chips-input.component.ts create mode 100644 web/src/app/shared/expandable-section/expandable-section.component.html create mode 100644 web/src/app/shared/expandable-section/expandable-section.component.scss create mode 100644 web/src/app/shared/expandable-section/expandable-section.component.ts create mode 100644 web/src/app/shared/global-search/global-search.component.html create mode 100644 web/src/app/shared/global-search/global-search.component.scss create mode 100644 web/src/app/shared/global-search/global-search.component.ts create mode 100644 web/src/app/shared/lore-link-picker/lore-link-picker.component.html create mode 100644 web/src/app/shared/lore-link-picker/lore-link-picker.component.scss create mode 100644 web/src/app/shared/lore-link-picker/lore-link-picker.component.ts create mode 100644 web/src/app/shared/secondary-sidebar/secondary-sidebar.component.html create mode 100644 web/src/app/shared/secondary-sidebar/secondary-sidebar.component.scss create mode 100644 web/src/app/shared/secondary-sidebar/secondary-sidebar.component.ts create mode 100644 web/src/app/sidebar/sidebar.component.html create mode 100644 web/src/app/sidebar/sidebar.component.scss create mode 100644 web/src/app/sidebar/sidebar.component.ts create mode 100644 web/src/index.html create mode 100644 web/src/main.ts create mode 100644 web/src/styles.scss create mode 100644 web/src/styles/_buttons.scss create mode 100644 web/src/styles/_forms.scss create mode 100644 web/tsconfig.json diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..f697cb7 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.0 + + + + com.loremind + loremind-core + 1.0.0 + LoreMind Core + Backend Core - Architecture Hexagonale + + + 17 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + org.postgresql + postgresql + runtime + + + + + com.h2database + h2 + test + + + + + org.projectlombok + lombok + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + diff --git a/core/src/main/java/com/loremind/LoreMindApplication.java b/core/src/main/java/com/loremind/LoreMindApplication.java new file mode 100644 index 0000000..5ad7700 --- /dev/null +++ b/core/src/main/java/com/loremind/LoreMindApplication.java @@ -0,0 +1,16 @@ +package com.loremind; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Classe principale de l'application LoreMind. + * Point d'entrée Spring Boot qui démarre l'application. + */ +@SpringBootApplication +public class LoreMindApplication { + + public static void main(String[] args) { + SpringApplication.run(LoreMindApplication.class, args); + } +} diff --git a/core/src/main/java/com/loremind/application/campaigncontext/ArcService.java b/core/src/main/java/com/loremind/application/campaigncontext/ArcService.java new file mode 100644 index 0000000..691ac43 --- /dev/null +++ b/core/src/main/java/com/loremind/application/campaigncontext/ArcService.java @@ -0,0 +1,76 @@ +package com.loremind.application.campaigncontext; + +import com.loremind.domain.campaigncontext.Arc; +import com.loremind.domain.campaigncontext.ports.ArcRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte Arc. + * Orchestre la logique métier en utilisant le Port ArcRepository. + * Fait partie de la couche Application de l'Architecture Hexagonale. + */ +@Service +public class ArcService { + + private final ArcRepository arcRepository; + + public ArcService(ArcRepository arcRepository) { + this.arcRepository = arcRepository; + } + + public Arc createArc(String name, String description, String campaignId, int order) { + Arc arc = Arc.builder() + .name(name) + .description(description) + .campaignId(campaignId) + .order(order) + .build(); + return arcRepository.save(arc); + } + + public Optional getArcById(String id) { + return arcRepository.findById(id); + } + + public List getAllArcs() { + return arcRepository.findAll(); + } + + public List getArcsByCampaignId(String campaignId) { + return arcRepository.findByCampaignId(campaignId); + } + + /** + * Met à jour un Arc avec tous ses champs narratifs. + * Accepte un objet Arc pour éviter l'explosion de paramètres (Parameter Object pattern). + */ + public Arc updateArc(String id, Arc updated) { + Optional existingArc = arcRepository.findById(id); + if (existingArc.isEmpty()) { + throw new IllegalArgumentException("Arc non trouvé avec l'ID: " + id); + } + + Arc arc = existingArc.get(); + arc.setName(updated.getName()); + arc.setDescription(updated.getDescription()); + arc.setOrder(updated.getOrder()); + arc.setThemes(updated.getThemes()); + arc.setStakes(updated.getStakes()); + arc.setGmNotes(updated.getGmNotes()); + arc.setRewards(updated.getRewards()); + arc.setResolution(updated.getResolution()); + arc.setRelatedPageIds(updated.getRelatedPageIds()); + return arcRepository.save(arc); + } + + public void deleteArc(String id) { + arcRepository.deleteById(id); + } + + public boolean arcExists(String id) { + return arcRepository.existsById(id); + } +} diff --git a/core/src/main/java/com/loremind/application/campaigncontext/CampaignService.java b/core/src/main/java/com/loremind/application/campaigncontext/CampaignService.java new file mode 100644 index 0000000..48dbcac --- /dev/null +++ b/core/src/main/java/com/loremind/application/campaigncontext/CampaignService.java @@ -0,0 +1,84 @@ +package com.loremind.application.campaigncontext; + +import com.loremind.domain.campaigncontext.Campaign; +import com.loremind.domain.campaigncontext.ports.CampaignRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte Campaign. + * Orchestre la logique métier en utilisant le Port CampaignRepository. + * Fait partie de la couche Application de l'Architecture Hexagonale. + */ +@Service +public class CampaignService { + + private final CampaignRepository campaignRepository; + + public CampaignService(CampaignRepository campaignRepository) { + this.campaignRepository = campaignRepository; + } + + /** + * Parameter Object pour la création / mise à jour d'une Campaign. + * Évite une signature à rallonge et rend les évolutions futures (theme, + * coverImageUrl, etc.) sans casser les appelants. + * + *

{@code loreId} est nullable : une campagne peut exister sans univers associé.

+ */ + public record CampaignData(String name, String description, String loreId) {} + + public Campaign createCampaign(CampaignData data) { + Campaign campaign = Campaign.builder() + .name(data.name()) + .description(data.description()) + .loreId(normalizeLoreId(data.loreId())) + .arcsCount(0) + .build(); + return campaignRepository.save(campaign); + } + + public Optional getCampaignById(String id) { + return campaignRepository.findById(id); + } + + public List getAllCampaigns() { + return campaignRepository.findAll(); + } + + public Campaign updateCampaign(String id, CampaignData data) { + Optional existingCampaign = campaignRepository.findById(id); + if (existingCampaign.isEmpty()) { + throw new IllegalArgumentException("Campaign non trouvé avec l'ID: " + id); + } + + Campaign campaign = existingCampaign.get(); + campaign.setName(data.name()); + campaign.setDescription(data.description()); + campaign.setLoreId(normalizeLoreId(data.loreId())); + return campaignRepository.save(campaign); + } + + /** + * Normalise un loreId entrant : une chaîne vide/blanche est traitée comme "pas de lien". + * Utile car les payloads JSON peuvent envoyer "" au lieu de null. + */ + private String normalizeLoreId(String loreId) { + return (loreId == null || loreId.isBlank()) ? null : loreId; + } + + public void deleteCampaign(String id) { + campaignRepository.deleteById(id); + } + + public boolean campaignExists(String id) { + return campaignRepository.existsById(id); + } + + public List searchCampaigns(String query) { + if (query == null || query.isBlank()) return List.of(); + return campaignRepository.searchByName(query.trim()); + } +} diff --git a/core/src/main/java/com/loremind/application/campaigncontext/ChapterService.java b/core/src/main/java/com/loremind/application/campaigncontext/ChapterService.java new file mode 100644 index 0000000..427e960 --- /dev/null +++ b/core/src/main/java/com/loremind/application/campaigncontext/ChapterService.java @@ -0,0 +1,73 @@ +package com.loremind.application.campaigncontext; + +import com.loremind.domain.campaigncontext.Chapter; +import com.loremind.domain.campaigncontext.ports.ChapterRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte Chapter. + * Orchestre la logique métier en utilisant le Port ChapterRepository. + * Fait partie de la couche Application de l'Architecture Hexagonale. + */ +@Service +public class ChapterService { + + private final ChapterRepository chapterRepository; + + public ChapterService(ChapterRepository chapterRepository) { + this.chapterRepository = chapterRepository; + } + + public Chapter createChapter(String name, String description, String arcId, int order) { + Chapter chapter = Chapter.builder() + .name(name) + .description(description) + .arcId(arcId) + .order(order) + .build(); + return chapterRepository.save(chapter); + } + + public Optional getChapterById(String id) { + return chapterRepository.findById(id); + } + + public List getAllChapters() { + return chapterRepository.findAll(); + } + + public List getChaptersByArcId(String arcId) { + return chapterRepository.findByArcId(arcId); + } + + /** + * Met à jour un Chapter avec tous ses champs narratifs (Parameter Object pattern). + */ + public Chapter updateChapter(String id, Chapter updated) { + Optional existingChapter = chapterRepository.findById(id); + if (existingChapter.isEmpty()) { + throw new IllegalArgumentException("Chapter non trouvé avec l'ID: " + id); + } + + Chapter chapter = existingChapter.get(); + chapter.setName(updated.getName()); + chapter.setDescription(updated.getDescription()); + chapter.setOrder(updated.getOrder()); + chapter.setGmNotes(updated.getGmNotes()); + chapter.setPlayerObjectives(updated.getPlayerObjectives()); + chapter.setNarrativeStakes(updated.getNarrativeStakes()); + chapter.setRelatedPageIds(updated.getRelatedPageIds()); + return chapterRepository.save(chapter); + } + + public void deleteChapter(String id) { + chapterRepository.deleteById(id); + } + + public boolean chapterExists(String id) { + return chapterRepository.existsById(id); + } +} diff --git a/core/src/main/java/com/loremind/application/campaigncontext/SceneService.java b/core/src/main/java/com/loremind/application/campaigncontext/SceneService.java new file mode 100644 index 0000000..810a977 --- /dev/null +++ b/core/src/main/java/com/loremind/application/campaigncontext/SceneService.java @@ -0,0 +1,78 @@ +package com.loremind.application.campaigncontext; + +import com.loremind.domain.campaigncontext.Scene; +import com.loremind.domain.campaigncontext.ports.SceneRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte Scene. + * Orchestre la logique métier en utilisant le Port SceneRepository. + * Fait partie de la couche Application de l'Architecture Hexagonale. + */ +@Service +public class SceneService { + + private final SceneRepository sceneRepository; + + public SceneService(SceneRepository sceneRepository) { + this.sceneRepository = sceneRepository; + } + + public Scene createScene(String name, String description, String chapterId, int order) { + Scene scene = Scene.builder() + .name(name) + .description(description) + .chapterId(chapterId) + .order(order) + .build(); + return sceneRepository.save(scene); + } + + public Optional getSceneById(String id) { + return sceneRepository.findById(id); + } + + public List getAllScenes() { + return sceneRepository.findAll(); + } + + public List getScenesByChapterId(String chapterId) { + return sceneRepository.findByChapterId(chapterId); + } + + /** + * Met à jour une Scene avec tous ses champs narratifs (Parameter Object pattern). + */ + public Scene updateScene(String id, Scene updated) { + Optional existingScene = sceneRepository.findById(id); + if (existingScene.isEmpty()) { + throw new IllegalArgumentException("Scene non trouvée avec l'ID: " + id); + } + + Scene scene = existingScene.get(); + scene.setName(updated.getName()); + scene.setDescription(updated.getDescription()); + scene.setOrder(updated.getOrder()); + scene.setLocation(updated.getLocation()); + scene.setTiming(updated.getTiming()); + scene.setAtmosphere(updated.getAtmosphere()); + scene.setPlayerNarration(updated.getPlayerNarration()); + scene.setGmSecretNotes(updated.getGmSecretNotes()); + scene.setChoicesConsequences(updated.getChoicesConsequences()); + scene.setCombatDifficulty(updated.getCombatDifficulty()); + scene.setEnemies(updated.getEnemies()); + scene.setRelatedPageIds(updated.getRelatedPageIds()); + return sceneRepository.save(scene); + } + + public void deleteScene(String id) { + sceneRepository.deleteById(id); + } + + public boolean sceneExists(String id) { + return sceneRepository.existsById(id); + } +} diff --git a/core/src/main/java/com/loremind/application/lorecontext/LoreNodeService.java b/core/src/main/java/com/loremind/application/lorecontext/LoreNodeService.java new file mode 100644 index 0000000..42efb13 --- /dev/null +++ b/core/src/main/java/com/loremind/application/lorecontext/LoreNodeService.java @@ -0,0 +1,78 @@ +package com.loremind.application.lorecontext; + +import com.loremind.domain.lorecontext.LoreNode; +import com.loremind.domain.lorecontext.ports.LoreNodeRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte LoreNode. + * Orchestre la logique métier en utilisant le Port LoreNodeRepository. + * Fait partie de la couche Application de l'Architecture Hexagonale. + */ +@Service +public class LoreNodeService { + + private final LoreNodeRepository loreNodeRepository; + + public LoreNodeService(LoreNodeRepository loreNodeRepository) { + this.loreNodeRepository = loreNodeRepository; + } + + /** + * Crée un LoreNode (dossier) à partir d'un "objet changes" porteur des valeurs + * souhaitées (pattern Parameter Object) : évite les signatures qui gonflent + * à chaque ajout de champ. + */ + public LoreNode createLoreNode(LoreNode changes) { + LoreNode loreNode = LoreNode.builder() + .name(changes.getName()) + .icon(changes.getIcon()) + .parentId(changes.getParentId()) + .loreId(changes.getLoreId()) + .build(); + return loreNodeRepository.save(loreNode); + } + + public Optional getLoreNodeById(String id) { + return loreNodeRepository.findById(id); + } + + public List getAllLoreNodes() { + return loreNodeRepository.findAll(); + } + + public List getLoreNodesByLoreId(String loreId) { + return loreNodeRepository.findByLoreId(loreId); + } + + public List getLoreNodesByParentId(String parentId) { + return loreNodeRepository.findByParentId(parentId); + } + + public List searchLoreNodes(String query) { + if (query == null || query.isBlank()) return List.of(); + return loreNodeRepository.searchByName(query.trim()); + } + + public LoreNode updateLoreNode(String id, LoreNode changes) { + LoreNode existing = loreNodeRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("LoreNode non trouvé avec l'ID: " + id)); + + existing.setName(changes.getName()); + existing.setIcon(changes.getIcon()); + existing.setParentId(changes.getParentId()); + // loreId volontairement immuable (un dossier ne migre pas d'un Lore à l'autre). + return loreNodeRepository.save(existing); + } + + public void deleteLoreNode(String id) { + loreNodeRepository.deleteById(id); + } + + public boolean loreNodeExists(String id) { + return loreNodeRepository.existsById(id); + } +} diff --git a/core/src/main/java/com/loremind/application/lorecontext/LoreService.java b/core/src/main/java/com/loremind/application/lorecontext/LoreService.java new file mode 100644 index 0000000..e62be04 --- /dev/null +++ b/core/src/main/java/com/loremind/application/lorecontext/LoreService.java @@ -0,0 +1,93 @@ +package com.loremind.application.lorecontext; + +import com.loremind.domain.lorecontext.Lore; +import com.loremind.domain.lorecontext.ports.LoreNodeRepository; +import com.loremind.domain.lorecontext.ports.LoreRepository; +import com.loremind.domain.lorecontext.ports.PageRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Service d'application pour le contexte Lore. + * Orchestre la logique métier en utilisant le Port LoreRepository. + * Fait partie de la couche Application de l'Architecture Hexagonale. + * + * Note: les compteurs nodeCount/pageCount sont calculés à la volée via + * countByLoreId sur les ports LoreNode et Page, plutôt que stockés en BDD + * (la colonne existe encore mais n'est plus fiable). Source of truth = les + * tables nodes/pages elles-mêmes, jamais de désync possible. + */ +@Service +public class LoreService { + + private final LoreRepository loreRepository; + private final LoreNodeRepository loreNodeRepository; + private final PageRepository pageRepository; + + public LoreService(LoreRepository loreRepository, + LoreNodeRepository loreNodeRepository, + PageRepository pageRepository) { + this.loreRepository = loreRepository; + this.loreNodeRepository = loreNodeRepository; + this.pageRepository = pageRepository; + } + + public Lore createLore(String name, String description) { + Lore lore = Lore.builder() + .name(name) + .description(description) + .nodeCount(0) + .pageCount(0) + .build(); + return loreRepository.save(lore); + } + + public Optional getLoreById(String id) { + return loreRepository.findById(id).map(this::withCounts); + } + + public List getAllLores() { + return loreRepository.findAll().stream() + .map(this::withCounts) + .collect(Collectors.toList()); + } + + /** + * Enrichit un Lore avec les compteurs calculés à la volée. + * N+1 acceptable à l'échelle actuelle (quelques dizaines de Lores max). + */ + private Lore withCounts(Lore lore) { + lore.setNodeCount((int) loreNodeRepository.countByLoreId(lore.getId())); + lore.setPageCount((int) pageRepository.countByLoreId(lore.getId())); + return lore; + } + + /** Recherche par nom (ILIKE). Résultats sans compteurs — pas utile pour la command palette. */ + public List searchLores(String query) { + if (query == null || query.isBlank()) return List.of(); + return loreRepository.searchByName(query.trim()); + } + + public Lore updateLore(String id, String name, String description) { + Optional existingLore = loreRepository.findById(id); + if (existingLore.isEmpty()) { + throw new IllegalArgumentException("Lore non trouvé avec l'ID: " + id); + } + + Lore lore = existingLore.get(); + lore.setName(name); + lore.setDescription(description); + return loreRepository.save(lore); + } + + public void deleteLore(String id) { + loreRepository.deleteById(id); + } + + public boolean loreExists(String id) { + return loreRepository.existsById(id); + } +} diff --git a/core/src/main/java/com/loremind/application/lorecontext/PageService.java b/core/src/main/java/com/loremind/application/lorecontext/PageService.java new file mode 100644 index 0000000..c8d2058 --- /dev/null +++ b/core/src/main/java/com/loremind/application/lorecontext/PageService.java @@ -0,0 +1,95 @@ +package com.loremind.application.lorecontext; + +import com.loremind.domain.lorecontext.Page; +import com.loremind.domain.lorecontext.ports.PageRepository; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte Page. + * Orchestre la logique métier via le Port PageRepository. + * Couche Application de l'Architecture Hexagonale. + */ +@Service +public class PageService { + + private final PageRepository pageRepository; + + public PageService(PageRepository pageRepository) { + this.pageRepository = pageRepository; + } + + /** Création MVP : seuls les champs structurels sont requis. Le contenu est + * enrichi plus tard depuis l'écran d'édition. */ + public Page createPage(String loreId, String nodeId, String templateId, String title) { + Page page = Page.builder() + .loreId(loreId) + .nodeId(nodeId) + .templateId(templateId) + .title(title) + .values(new HashMap<>()) + .tags(new ArrayList<>()) + .relatedPageIds(new ArrayList<>()) + .build(); + return pageRepository.save(page); + } + + public Optional getPageById(String id) { + return pageRepository.findById(id); + } + + public List getAllPages() { + return pageRepository.findAll(); + } + + public List getPagesByLoreId(String loreId) { + return pageRepository.findByLoreId(loreId); + } + + public List getPagesByNodeId(String nodeId) { + return pageRepository.findByNodeId(nodeId); + } + + public List searchPages(String query) { + if (query == null || query.isBlank()) return List.of(); + return pageRepository.searchByTitle(query.trim()); + } + + /** + * Met à jour une page existante. + * Parameter Object pattern : le controller construit une Page "changes" + * avec les nouvelles valeurs, le service recharge et applique les champs modifiables. + * Les champs structurels immuables sont : id, loreId, templateId. + * Le nodeId est mutable (déplacement d'une page d'un noeud à l'autre). + */ + public Page updatePage(String id, Page changes) { + Page existing = pageRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("Page non trouvée avec l'ID: " + id)); + + existing.setTitle(changes.getTitle()); + existing.setNodeId(changes.getNodeId()); + existing.setValues(changes.getValues() != null + ? new HashMap<>(changes.getValues()) + : new HashMap<>()); + existing.setNotes(changes.getNotes()); + existing.setTags(changes.getTags() != null + ? new ArrayList<>(changes.getTags()) + : new ArrayList<>()); + existing.setRelatedPageIds(changes.getRelatedPageIds() != null + ? new ArrayList<>(changes.getRelatedPageIds()) + : new ArrayList<>()); + return pageRepository.save(existing); + } + + public void deletePage(String id) { + pageRepository.deleteById(id); + } + + public boolean pageExists(String id) { + return pageRepository.existsById(id); + } +} diff --git a/core/src/main/java/com/loremind/application/lorecontext/TemplateService.java b/core/src/main/java/com/loremind/application/lorecontext/TemplateService.java new file mode 100644 index 0000000..4d89608 --- /dev/null +++ b/core/src/main/java/com/loremind/application/lorecontext/TemplateService.java @@ -0,0 +1,84 @@ +package com.loremind.application.lorecontext; + +import com.loremind.domain.lorecontext.Template; +import com.loremind.domain.lorecontext.ports.TemplateRepository; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Service d'application pour le contexte Template. + * Orchestre la logique métier via le Port TemplateRepository. + * Couche Application de l'Architecture Hexagonale. + */ +@Service +public class TemplateService { + + private final TemplateRepository templateRepository; + + public TemplateService(TemplateRepository templateRepository) { + this.templateRepository = templateRepository; + } + + public Template createTemplate(String loreId, + String name, + String description, + String defaultNodeId, + List fields) { + Template template = Template.builder() + .loreId(loreId) + .name(name) + .description(description) + .defaultNodeId(defaultNodeId) + .fields(fields != null ? new ArrayList<>(fields) : new ArrayList<>()) + .build(); + return templateRepository.save(template); + } + + public Optional