Browse Source

Merge branch 'release/0.6.0'

Warafear 1 year ago
parent
commit
5df2bb8a12
55 changed files with 3462 additions and 783 deletions
  1. 10 0
      .gitignore
  2. 1450 0
      .nx/cache/d/daemon.log
  3. 1 1
      .nx/cache/d/server-process.json
  4. 6 6
      package-lock.json
  5. 2 2
      package.json
  6. 1 0
      src/app/character/character-creator/character-creator.component.ts
  7. 8 5
      src/app/journal/journal-character/class/class.component.html
  8. 10 6
      src/app/journal/journal-character/class/class.component.scss
  9. 73 1
      src/app/journal/journal-character/class/class.component.ts
  10. 1 2
      src/app/journal/journal-character/journal-character.component.html
  11. 32 1
      src/app/journal/journal-character/story/story.component.html
  12. 30 0
      src/app/journal/journal-character/story/story.component.scss
  13. 38 2
      src/app/journal/journal-character/story/story.component.ts
  14. 2 1
      src/app/journal/journal-notes/journal-notes.component.html
  15. 17 0
      src/app/journal/journal-notes/journal-notes.component.ts
  16. 42 43
      src/app/journal/journal-spellcards/add-card/add-card.component.html
  17. 52 5
      src/app/journal/journal-spellcards/add-card/add-card.component.scss
  18. 7 1
      src/app/journal/journal-spellcards/add-card/add-card.component.ts
  19. 26 0
      src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.html
  20. 60 0
      src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.scss
  21. 23 0
      src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.spec.ts
  22. 35 0
      src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.ts
  23. 6 2
      src/app/journal/journal-spellcards/journal-spellcards.component.html
  24. 19 0
      src/app/journal/journal-spellcards/journal-spellcards.component.scss
  25. 75 16
      src/app/journal/journal-spellcards/journal-spellcards.component.ts
  26. 1 1
      src/app/journal/journal-spellcards/spellcard/spellcard.component.html
  27. 4 21
      src/app/journal/journal-spellcards/spellcard/spellcard.component.ts
  28. 5 3
      src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.html
  29. 1 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.ts
  30. 14 14
      src/app/journal/journal-stats/ability-panel/proficiencies-table/proficiencies-table.component.html
  31. 4 4
      src/app/journal/journal-stats/ability-panel/trait-table/trait-modal/trait-modal.component.html
  32. 1 0
      src/app/journal/journal-stats/ability-panel/trait-table/trait-modal/trait-modal.component.ts
  33. 1 1
      src/app/journal/journal-stats/life-container/life/life.component.scss
  34. 2 2
      src/app/journal/journal-stats/weapons-container/spell-table/favorite-spells-modal/favorite-spells-modal.component.html
  35. 1 1
      src/app/journal/journal-stats/weapons-container/spell-table/spell-details/spell-details.component.html
  36. 2 2
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-details/weapon-details.component.html
  37. 28 5
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.html
  38. 1 3
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.scss
  39. 14 0
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.ts
  40. 12 7
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-table.component.ts
  41. 2 0
      src/app/journal/journal.module.ts
  42. 345 111
      src/app/journal/spell-modal/spell-modal.component.html
  43. 84 71
      src/app/journal/spell-modal/spell-modal.component.scss
  44. 64 24
      src/app/journal/spell-modal/spell-modal.component.ts
  45. 5 3
      src/app/shared-components/full-spellcard/full-spellcard.component.html
  46. BIN
      src/assets/images/spells/aid.jpg
  47. BIN
      src/assets/images/spells/spiritualWeapon.jpg
  48. 5 3
      src/interfaces/spell.ts
  49. 3 0
      src/interfaces/weapon.ts
  50. 442 228
      src/services/class/class.service.ts
  51. 6 3
      src/services/data/data.service.ts
  52. 11 2
      src/services/modal/modal.service.ts
  53. 356 180
      src/services/spells/spells.service.ts
  54. 1 0
      src/services/translator/translator.service.ts
  55. 21 0
      src/styles.scss

+ 10 - 0
.gitignore

@@ -13,6 +13,14 @@
 .nx/cache/d/*
 /nx/cache/d/*
 
+*.log
+
+/.nx-cache
+/.nx
+
+.nx\cache\d
+.nx\cache\d\*
+
 # Node
 /node_modules
 npm-debug.log
@@ -48,3 +56,5 @@ testem.log
 # System files
 .DS_Store
 Thumbs.db
+.nx/cache/d/daemon.log
+.nx/cache/d/server-process.json

+ 1450 - 0
.nx/cache/d/daemon.log

@@ -467324,3 +467324,1453 @@ To fix this, set a unique name for each project in a project.json inside the pro
     at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
 [NX Daemon Server] - 2024-02-16T09:47:38.224Z - Time taken for 'hash changed files from watcher' 26.615199998021126ms
 [NX Daemon Server] - 2024-02-16T09:47:38.225Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-16T11:31:04.122Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-16T11:31:04.129Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-16T11:31:04.134Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T11:31:04.134Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-16T11:31:04.135Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T11:31:04.137Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-16T11:31:04.244Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-16T11:31:04.244Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-16T11:31:04.245Z - Time taken for 'hash changed files from watcher' 31.080699995160103ms
+[NX Daemon Server] - 2024-02-16T11:31:04.245Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-16T12:21:22.895Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-16T12:21:22.898Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-16T12:21:22.910Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T12:21:22.910Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-16T12:21:22.910Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T12:21:22.912Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-16T12:21:23.523Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-16T12:21:23.523Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-16T12:21:23.524Z - Time taken for 'hash changed files from watcher' 14.10249999165535ms
+[NX Daemon Server] - 2024-02-16T12:21:23.524Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-16T13:38:09.798Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-16T13:38:09.802Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-16T13:38:09.813Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T13:38:09.814Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-16T13:38:09.815Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T13:38:09.817Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-16T13:38:09.905Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-16T13:38:09.905Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-16T13:38:09.906Z - Time taken for 'hash changed files from watcher' 29.54670000076294ms
+[NX Daemon Server] - 2024-02-16T13:38:09.906Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-16T16:09:21.126Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-16T16:09:21.128Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-16T16:09:21.142Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T16:09:21.142Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-16T16:09:21.143Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T16:09:21.144Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-16T16:09:22.698Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-16T16:09:22.698Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-16T16:09:22.699Z - Time taken for 'hash changed files from watcher' 15.016499996185303ms
+[NX Daemon Server] - 2024-02-16T16:09:22.699Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-16T18:22:33.925Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-16T18:22:33.932Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-16T18:22:33.932Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T18:22:33.933Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-16T18:22:33.933Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-16T18:22:33.935Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-16T18:22:34.151Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-16T18:22:34.151Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-16T18:22:34.152Z - Time taken for 'hash changed files from watcher' 77.96109999716282ms
+[NX Daemon Server] - 2024-02-16T18:22:34.152Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-17T09:56:40.020Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-17T09:56:40.024Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-17T09:56:40.024Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-17T09:56:40.025Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-17T09:56:40.025Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-17T09:56:40.026Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-17T09:56:40.871Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-17T09:56:40.871Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-17T09:56:40.872Z - Time taken for 'hash changed files from watcher' 47.76180000000022ms
+[NX Daemon Server] - 2024-02-17T09:56:40.872Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-17T11:05:57.809Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-17T11:05:57.812Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-17T11:05:57.816Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-17T11:05:57.817Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-17T11:05:57.817Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-17T11:05:57.821Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-17T11:05:58.694Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-17T11:05:58.694Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-17T11:05:58.695Z - Time taken for 'hash changed files from watcher' 26.270800000056624ms
+[NX Daemon Server] - 2024-02-17T11:05:58.695Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-20T15:37:26.209Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-20T15:37:26.212Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-20T15:37:26.212Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-20T15:37:26.213Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-20T15:37:26.213Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-20T15:37:26.214Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-20T15:37:27.231Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-20T15:37:27.231Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-20T15:37:27.232Z - Time taken for 'hash changed files from watcher' 57.033900022506714ms
+[NX Daemon Server] - 2024-02-20T15:37:27.232Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-20T16:58:00.501Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-20T16:58:00.506Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-20T16:58:00.506Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-20T16:58:00.507Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-20T16:58:00.507Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-20T16:58:00.508Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-20T16:58:00.618Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-20T16:58:00.618Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-20T16:58:00.619Z - Time taken for 'hash changed files from watcher' 56.532999992370605ms
+[NX Daemon Server] - 2024-02-20T16:58:00.619Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-22T15:32:20.033Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-22T15:32:20.035Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-22T15:32:20.047Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-22T15:32:20.048Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-22T15:32:20.048Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-22T15:32:20.050Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-22T15:32:21.216Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-22T15:32:21.216Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-22T15:32:21.217Z - Time taken for 'hash changed files from watcher' 28.621599972248077ms
+[NX Daemon Server] - 2024-02-22T15:32:21.217Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-23T07:40:44.965Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-23T07:40:44.967Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-23T07:40:44.980Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-23T07:40:44.981Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-23T07:40:44.981Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-23T07:40:44.983Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-23T07:40:45.811Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-23T07:40:45.811Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-23T07:40:45.811Z - Time taken for 'hash changed files from watcher' 29.652300000190735ms
+[NX Daemon Server] - 2024-02-23T07:40:45.811Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-26T06:02:39.906Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-26T06:02:39.909Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-26T06:02:39.910Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-26T06:02:39.910Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-26T06:02:39.911Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-26T06:02:39.912Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-26T06:02:40.626Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-26T06:02:40.627Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-26T06:02:40.627Z - Time taken for 'hash changed files from watcher' 13.892500042915344ms
+[NX Daemon Server] - 2024-02-26T06:02:40.627Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-26T08:54:38.933Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-26T08:54:38.940Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-26T08:54:38.946Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-26T08:54:38.947Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-26T08:54:38.948Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-26T08:54:38.958Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-26T08:54:40.489Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-26T08:54:40.489Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-26T08:54:40.490Z - Time taken for 'hash changed files from watcher' 33.984099984169006ms
+[NX Daemon Server] - 2024-02-26T08:54:40.491Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-26T21:10:10.303Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-26T21:10:10.311Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-26T21:10:10.316Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-26T21:10:10.317Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-26T21:10:10.317Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-26T21:10:10.321Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-26T21:10:10.514Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-26T21:10:10.514Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-26T21:10:10.515Z - Time taken for 'hash changed files from watcher' 35.52839994430542ms
+[NX Daemon Server] - 2024-02-26T21:10:10.515Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T08:53:57.864Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T08:53:57.868Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T08:53:57.879Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T08:53:57.881Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-27T08:53:57.881Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T08:53:57.883Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T08:53:58.892Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T08:53:58.893Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T08:53:58.893Z - Time taken for 'hash changed files from watcher' 28.74870002269745ms
+[NX Daemon Server] - 2024-02-27T08:53:58.893Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:21.366Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:21.372Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:21.373Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:21.375Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:21.375Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:21.377Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:22.320Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:22.321Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:22.321Z - Time taken for 'hash changed files from watcher' 29.070899963378906ms
+[NX Daemon Server] - 2024-02-27T09:48:22.321Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.322Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.323Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.323Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-02-27T09:48:22.323Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:23.726Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:23.728Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:23.736Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:23.738Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:23.739Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:23.741Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:23.813Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:23.814Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:23.815Z - Time taken for 'hash changed files from watcher' 26.10479998588562ms
+[NX Daemon Server] - 2024-02-27T09:48:23.817Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:24.045Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:24.048Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:24.060Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:24.060Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:24.060Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:24.061Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:24.138Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:24.139Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:24.139Z - Time taken for 'hash changed files from watcher' 32.059200048446655ms
+[NX Daemon Server] - 2024-02-27T09:48:24.139Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:25.460Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:25.464Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:25.475Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:25.477Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:25.477Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:25.478Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:25.535Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:25.535Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:25.537Z - Time taken for 'hash changed files from watcher' 12.052600026130676ms
+[NX Daemon Server] - 2024-02-27T09:48:25.538Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:28.444Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:28.446Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:28.457Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:28.457Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:28.458Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:28.459Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:28.516Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:28.516Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:28.517Z - Time taken for 'hash changed files from watcher' 14.632299900054932ms
+[NX Daemon Server] - 2024-02-27T09:48:28.517Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:29.649Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:29.651Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:29.661Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:29.663Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:29.664Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:29.665Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:29.737Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:29.738Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:29.739Z - Time taken for 'hash changed files from watcher' 27.19159996509552ms
+[NX Daemon Server] - 2024-02-27T09:48:29.741Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:37.788Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:37.790Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:37.800Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:37.801Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:37.801Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:37.803Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:37.873Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:37.873Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:37.874Z - Time taken for 'hash changed files from watcher' 29.356000065803528ms
+[NX Daemon Server] - 2024-02-27T09:48:37.874Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:39.025Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:39.027Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:39.036Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:39.038Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:39.038Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:39.040Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:39.101Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:39.101Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:39.102Z - Time taken for 'hash changed files from watcher' 12.664199948310852ms
+[NX Daemon Server] - 2024-02-27T09:48:39.103Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:54.156Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:54.158Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:54.168Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:54.168Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:48:54.169Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:54.170Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:54.227Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:54.228Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:54.228Z - Time taken for 'hash changed files from watcher' 15.197100043296814ms
+[NX Daemon Server] - 2024-02-27T09:48:54.228Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:48:55.379Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:48:55.383Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:48:55.385Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:55.387Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-27T09:48:55.389Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:48:55.391Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:48:55.462Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:48:55.462Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:48:55.464Z - Time taken for 'hash changed files from watcher' 21.045400023460388ms
+[NX Daemon Server] - 2024-02-27T09:48:55.466Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:49:19.516Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:49:19.518Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:49:19.519Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:49:19.520Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T09:49:19.520Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:49:19.522Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:49:19.597Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:49:19.597Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:49:19.598Z - Time taken for 'hash changed files from watcher' 30.260900020599365ms
+[NX Daemon Server] - 2024-02-27T09:49:19.598Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T09:49:20.724Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T09:49:20.728Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T09:49:20.731Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:49:20.732Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-27T09:49:20.733Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T09:49:20.735Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T09:49:20.810Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T09:49:20.810Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T09:49:20.812Z - Time taken for 'hash changed files from watcher' 22.34089994430542ms
+[NX Daemon Server] - 2024-02-27T09:49:20.814Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T10:34:41.935Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T10:34:41.936Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T10:34:41.943Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T10:34:41.943Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T10:34:41.944Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T10:34:41.946Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T10:34:42.009Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T10:34:42.010Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T10:34:42.010Z - Time taken for 'hash changed files from watcher' 12.541800022125244ms
+[NX Daemon Server] - 2024-02-27T10:34:42.010Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:13:59.070Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:13:59.072Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:13:59.077Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:13:59.078Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:13:59.078Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:13:59.079Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:13:59.172Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:13:59.172Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:13:59.173Z - Time taken for 'hash changed files from watcher' 46.22350001335144ms
+[NX Daemon Server] - 2024-02-27T14:13:59.173Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:00.322Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:00.324Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:00.328Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:00.330Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:00.331Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:00.332Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:00.404Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:00.404Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:00.406Z - Time taken for 'hash changed files from watcher' 26.66069996356964ms
+[NX Daemon Server] - 2024-02-27T14:14:00.407Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:00.630Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:00.632Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:00.645Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:00.646Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:00.646Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:00.647Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:00.704Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:00.704Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:00.704Z - Time taken for 'hash changed files from watcher' 15.381999969482422ms
+[NX Daemon Server] - 2024-02-27T14:14:00.704Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:01.824Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:01.826Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:01.831Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:01.834Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:01.834Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:01.836Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:01.904Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:01.905Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:01.906Z - Time taken for 'hash changed files from watcher' 24.272799968719482ms
+[NX Daemon Server] - 2024-02-27T14:14:01.907Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:04.978Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:04.981Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:04.982Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:04.982Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-27T14:14:04.982Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:04.984Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:05.053Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:05.054Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:05.054Z - Time taken for 'hash changed files from watcher' 26.097999930381775ms
+[NX Daemon Server] - 2024-02-27T14:14:05.054Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:06.184Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:06.188Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:06.189Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:06.189Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-27T14:14:06.191Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:06.192Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:06.279Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:06.279Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:06.280Z - Time taken for 'hash changed files from watcher' 42.3206000328064ms
+[NX Daemon Server] - 2024-02-27T14:14:06.281Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:14.341Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:14.343Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:14.353Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:14.354Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:14.354Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:14.355Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:14.430Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:14.430Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:14.430Z - Time taken for 'hash changed files from watcher' 30.180100083351135ms
+[NX Daemon Server] - 2024-02-27T14:14:14.430Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:15.762Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:15.765Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:15.777Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:15.778Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:15.779Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:15.780Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:15.850Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:15.850Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:15.852Z - Time taken for 'hash changed files from watcher' 25.798799991607666ms
+[NX Daemon Server] - 2024-02-27T14:14:15.853Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:30.950Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:30.952Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:30.964Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:30.965Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:30.965Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:30.966Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:31.022Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:31.022Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:31.023Z - Time taken for 'hash changed files from watcher' 14.42330002784729ms
+[NX Daemon Server] - 2024-02-27T14:14:31.023Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:32.351Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:32.354Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:32.357Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:32.358Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-02-27T14:14:32.360Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:32.362Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:32.429Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:32.429Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:32.430Z - Time taken for 'hash changed files from watcher' 22.496299982070923ms
+[NX Daemon Server] - 2024-02-27T14:14:32.432Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:56.545Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:56.547Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:56.560Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:56.561Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:56.561Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:56.562Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:56.639Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:56.639Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:56.639Z - Time taken for 'hash changed files from watcher' 30.25849997997284ms
+[NX Daemon Server] - 2024-02-27T14:14:56.639Z - Done responding to the client null
+[NX Daemon Server] - 2024-02-27T14:14:57.968Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-02-27T14:14:57.971Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-02-27T14:14:57.978Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:57.980Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-02-27T14:14:57.980Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-02-27T14:14:57.981Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-02-27T14:14:58.053Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2024-02-27T14:14:58.053Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-02-27T14:14:58.054Z - Time taken for 'hash changed files from watcher' 27.379500031471252ms
+[NX Daemon Server] - 2024-02-27T14:14:58.056Z - Done responding to the client null

+ 1 - 1
.nx/cache/d/server-process.json

@@ -1 +1 @@
-{"processId":1936}
+{"processId":13384}

+ 6 - 6
package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "dndtools",
-  "version": "0.4.0",
+  "version": "0.5.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "dndtools",
-      "version": "0.4.0",
+      "version": "0.5.0",
       "dependencies": {
         "@angular/animations": "^17.0.3",
         "@angular/cdk": "^17.0.0",
@@ -22,7 +22,7 @@
         "@popperjs/core": "^2.11.6",
         "bootstrap": "^5.2.3",
         "localbase": "^0.7.5",
-        "marked": "^9.0.0",
+        "marked": "^9.1.6",
         "ngx-editor": "^16.0.1",
         "ngx-markdown": "^17.1.1",
         "rxjs": "~7.8.0",
@@ -17394,9 +17394,9 @@
       }
     },
     "node_modules/marked": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-9.0.0.tgz",
-      "integrity": "sha512-37yoTpjU+TSXb9OBYY5n78z/CqXh76KiQj9xsKxEdztzU9fRLmbWO5YqKxgCVGKlNdexppnbKTkwB3RipVri8w==",
+      "version": "9.1.6",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
+      "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==",
       "bin": {
         "marked": "bin/marked.js"
       },

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "dndtools",
-  "version": "0.5.0",
+  "version": "0.6.0",
   "scripts": {
     "ng": "ng",
     "start": "nx serve",
@@ -25,7 +25,7 @@
     "@popperjs/core": "^2.11.6",
     "bootstrap": "^5.2.3",
     "localbase": "^0.7.5",
-    "marked": "^9.0.0",
+    "marked": "^9.1.6",
     "ngx-editor": "^16.0.1",
     "ngx-markdown": "^17.1.1",
     "rxjs": "~7.8.0",

+ 1 - 0
src/app/character/character-creator/character-creator.component.ts

@@ -142,6 +142,7 @@ export class CharacterCreatorComponent {
           subclass: '',
           race: this.characterSpecies,
           background: this.characterBackground,
+          backgroundStory: '',
           level: 1,
           experience: 0,
           image: '',

+ 8 - 5
src/app/journal/journal-character/class/class.component.html

@@ -1,17 +1,20 @@
 <div class="class-container">
   <div class="title">{{ class.title }}</div>
 
-  <markdown [data]="class.description"></markdown>
+  <div [innerHTML]="class.description"></div>
 
   <div class="features">
     @for(feature of class.features; track feature){
     <div class="feature">
+      <hr />
       <div class="feature-name">{{ feature.name }}</div>
       <div class="feature-level">{{ feature.level }}</div>
-      <markdown
-        class="feature-description"
-        [data]="feature.description"
-      ></markdown>
+      <icon-button
+        [icon]="'add'"
+        class="feature-button"
+        (click)="addFeature(feature)"
+      ></icon-button>
+      <div [innerHTML]="feature.description"></div>
     </div>
     }
   </div>

+ 10 - 6
src/app/journal/journal-character/class/class.component.scss

@@ -21,11 +21,8 @@
     margin: 0 0 2rem 0;
 }
 
-.description {
-}
-
 .feature {
-    margin-top: 2rem;
+    margin-top: 1.5rem;
     position: relative;
 }
 
@@ -33,16 +30,23 @@
     font-size: 1.5rem;
     font-weight: 600;
     margin-bottom: 1rem;
+    margin-left: 1rem;
 }
 
 .feature-level {
     position: absolute;
-    left: -1.75rem;
-    top: 0;
+    left: -1.5rem;
+    top: 1rem;
     font-size: 1.5rem;
     font-weight: 600;
 }
 
+.feature-button {
+    position: absolute;
+    right: 0;
+    top: 1.5rem;
+}
+
 .feature-description {
     margin-top: 1rem;
 }

+ 73 - 1
src/app/journal/journal-character/class/class.component.ts

@@ -1,6 +1,11 @@
 import { Component } from '@angular/core';
 import { ClassService } from 'src/services/class/class.service';
 import { DataService } from 'src/services/data/data.service';
+import { ModalService } from 'src/services/modal/modal.service';
+import { AbilityModalComponent } from '../../journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component';
+import { Ability } from 'src/interfaces/ability';
+import { TraitModalComponent } from '../../journal-stats/ability-panel/trait-table/trait-modal/trait-modal.component';
+import { Trait } from 'src/interfaces/traits';
 
 @Component({
   selector: 'class',
@@ -12,7 +17,8 @@ export class ClassComponent {
   public class: any;
   public constructor(
     private classAccessor: ClassService,
-    private dataAccessor: DataService
+    private dataAccessor: DataService,
+    private modalAccessor: ModalService
   ) {}
 
   public ngOnInit(): void {
@@ -20,4 +26,70 @@ export class ClassComponent {
     this.class = this.classAccessor.getClassDetails(this.className);
     console.log(this.class);
   }
+
+  public addFeature(feature: any) {
+    if ('ability' in feature) {
+      this.addAbility(feature);
+    } else {
+      this.addTrait(feature);
+    }
+  }
+
+  private addAbility(feature: any) {
+    let index = feature.name.indexOf('Optional');
+    if (index > -1) {
+      feature.name = feature.name.slice(index, 8);
+    }
+    let ability: Ability = {
+      name: feature.name,
+      shortDescription: '',
+      longDescription: feature.description,
+      cost: '',
+      charges: 0,
+      currentlyUsedCharges: 0,
+    };
+    this.modalAccessor.openModal(AbilityModalComponent, {
+      ability: ability,
+      isUpdate: true,
+      isAddedFromCharacter: true,
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update' || result.state === 'add') {
+          let ability = this.dataAccessor.abilities;
+          ability.push(result.data);
+          this.dataAccessor.abilities = ability;
+        }
+        resultSubscription.unsubscribe();
+      }
+    );
+  }
+
+  private addTrait(feature: any) {
+    let index = feature.name.indexOf('Optional');
+    if (index > -1) {
+      feature.name = feature.name.slice(index, 8);
+    }
+    let trait: Trait = {
+      name: feature.name,
+      shortDescription: '',
+      longDescription: feature.description,
+      origin: 'Class',
+    };
+    this.modalAccessor.openModal(TraitModalComponent, {
+      trait: trait,
+      isUpdate: true,
+      isAddedFromCharacter: true,
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update' || result.state === 'add') {
+          let traits = this.dataAccessor.traits;
+          traits.push(result.data);
+          this.dataAccessor.traits = traits;
+        }
+        resultSubscription.unsubscribe();
+      }
+    );
+  }
 }

+ 1 - 2
src/app/journal/journal-character/journal-character.component.html

@@ -76,8 +76,7 @@
       <ng-container ngbNavItem="stroy">
         <button ngbNavLink>Geschichte</button>
         <ng-template ngbNavContent>
-          <!-- <class></class> -->
-          story works!
+          <story></story>
         </ng-template>
       </ng-container>
     </div>

+ 32 - 1
src/app/journal/journal-character/story/story.component.html

@@ -1 +1,32 @@
-<p>story works!</p>
+<div class="story-container">
+  <div class="edit">
+    <icon-button
+      [icon]="editMode ? 'cross' : 'edit'"
+      (click)="editMode ? cancel() : edit()"
+    ></icon-button>
+  </div>
+  <div class="title">Hintergrundgeschichte</div>
+
+  @if(characterData.backgroundStory != "" && !editMode){
+  <div class="t-2" [innerHTML]="characterData.backgroundStory"></div>
+  }@else if(editMode){
+  <div class="NgxEditor__Wrapper t-15">
+    <ngx-editor-menu [editor]="editor" [toolbar]="toolbar"> </ngx-editor-menu>
+    <ngx-editor
+      [editor]="editor"
+      [(ngModel)]="editBackgroundStory"
+      placeholder="Hier kann die Hintergrundgeschichte erzählt werden."
+    ></ngx-editor>
+  </div>
+  <div class="horizontal-buttons" style="justify-content: space-around">
+    <ui-button [color]="'green'" (click)="update()" [width]="'w15'"
+      >Anwenden</ui-button
+    >
+    <ui-button [color]="'red'" (click)="cancel()" [width]="'w15'"
+      >Verwerfen</ui-button
+    >
+  </div>
+  }@else { Hintergrundgeschichte bearbeiten
+  <button (click)="edit()">Bearbeiten</button>
+  }
+</div>

+ 30 - 0
src/app/journal/journal-character/story/story.component.scss

@@ -0,0 +1,30 @@
+.story-container {
+    width: 800px;
+    height: calc(100vh - 10.5rem);
+    overflow: auto;
+    margin: auto;
+    border: 1px solid black;
+    padding: 2rem;
+    border-radius: 10px;
+    background-color: var(--items-hover);
+    box-shadow: var(--shadow-large);
+    position: absolute;
+    top: 8.5rem;
+    left: 50%;
+    transform: translateX(-50%);
+
+    .edit {
+        position: absolute;
+        right: 1rem;
+        top: 3rem;
+    }
+}
+
+.title {
+    margin-top: 0;
+}
+
+::ng-deep .ProseMirror {
+    height: 30rem !important;
+    overflow-y: auto;
+}

+ 38 - 2
src/app/journal/journal-character/story/story.component.ts

@@ -1,10 +1,46 @@
 import { Component } from '@angular/core';
+import { DataService } from 'src/services/data/data.service';
+import { Editor } from 'ngx-editor';
 
 @Component({
-  selector: 'app-story',
+  selector: 'story',
   templateUrl: './story.component.html',
-  styleUrl: './story.component.scss'
+  styleUrl: './story.component.scss',
 })
 export class StoryComponent {
+  public characterData: any;
+  public editBackgroundStory: string = '';
+  public editMode: boolean = false;
 
+  editor: Editor = new Editor();
+  html = '';
+  toolbar: any = [
+    // default value
+    ['bold', 'italic'],
+    ['bullet_list'],
+    [{ heading: ['h3', 'h4', 'h5', 'h6'] }],
+  ];
+
+  constructor(private dataAccessor: DataService) {}
+
+  ngOnInit() {
+    this.characterData = this.dataAccessor.characterData;
+  }
+
+  update() {
+    this.characterData.backgroundStory = this.editBackgroundStory;
+    this.dataAccessor.characterData = this.characterData;
+    this.editBackgroundStory = '';
+    this.editMode = false;
+  }
+
+  cancel() {
+    this.editBackgroundStory = this.characterData.backgroundStory;
+    this.editMode = false;
+  }
+
+  edit() {
+    this.editBackgroundStory = this.characterData.backgroundStory;
+    this.editMode = true;
+  }
 }

+ 2 - 1
src/app/journal/journal-notes/journal-notes.component.html

@@ -16,8 +16,9 @@
     [editor]="editor"
     [(ngModel)]="html"
     [disabled]="false"
-    [placeholder]="'Type here...'"
+    [placeholder]="'Coming soon...'"
   ></ngx-editor>
 </div>
+<p [innerHTML]="htmlString"></p>
 
 <div [innerHTML]="html"></div>

+ 17 - 0
src/app/journal/journal-notes/journal-notes.component.ts

@@ -1,5 +1,6 @@
 import { Component, OnInit, OnDestroy } from '@angular/core';
 import { Editor } from 'ngx-editor';
+import { marked } from 'marked';
 
 @Component({
   selector: 'app-journal-notes',
@@ -10,6 +11,22 @@ export class JournalNotesComponent implements OnInit, OnDestroy {
   editor: Editor = new Editor();
   html = '';
 
+  markdownString =
+    ' # Hello \n \
+  this is a test \
+  **hi** \
+   \
+  - 1\
+  - 2';
+
+  htmlString = '';
+
+  constructor() {
+    this.htmlString = marked(this.markdownString);
+    console.log(this.markdownString);
+    console.log(this.htmlString);
+  }
+
   ngOnInit(): void {}
 
   // make sure to destory the editor

+ 42 - 43
src/app/journal/journal-spellcards/add-card/add-card.component.html

@@ -1,54 +1,53 @@
 <div class="add-card">
   @if(state === 1) {
-  <div class="clickable-background" (click)="state = 2">
+  <div class="clickable-card" (click)="state = 2; closeOthers()">
     <img class="add-icon" src="assets/icons/UIIcons/add.svg" />
   </div>
   } @else if(state === 2) {
-  <button
-    class="add-button"
-    (click)="continueToSpellSelection(false); state = 3"
-  >
-    Aus bekannten Zaubern wählen
-  </button>
-  <button
-    class="add-button"
-    (click)="continueToSpellSelection(true); state = 3"
-  >
-    Einen bekannten Zauber bearbeiten
-  </button>
-  <button class="add-button" (click)="emitNewSpell()">
-    Einen neuen Zauber erstellen
-  </button>
+  <div class="button-card">
+    <button (click)="continueToSpellSelection(false); state = 3">
+      Offizieller Zauber
+    </button>
 
-  <button class="cancel-button" (click)="resetThis()">Abbrechen</button>
+    <hr />
+    <button (click)="continueToSpellSelection(true); state = 3">
+      Offiziellen Zauber bearbeiten
+    </button>
+
+    <hr />
+
+    <button (click)="emitNewSpell()">Eigener Zauber</button>
+  </div>
   } @else if (state === 3) {
+  <div class="spell-selection">
+    <input
+      type="text"
+      class="spell-name"
+      [(ngModel)]="newSpellName"
+      placeholder="Zauber durchsuchen"
+      (keyup)="
+        isModification ? filterSpellArrayForModification() : filterSpellArray()
+      "
+    />
+    <div class="available-spells">
+      <ul>
+        @for(spell of availableSpells; track spell) {
+        <li>
+          <button
+            (click)="
+              isModification
+                ? emitNewSpellFromOfficial(spell)
+                : spellSelected(spell)
+            "
+          >
+            {{ spell.german }}
+          </button>
+        </li>
+        } @empty { Keine Zauber gefunden }
+      </ul>
+    </div>
 
-  <input
-    type="text"
-    class="spell-name"
-    [(ngModel)]="newSpellName"
-    placeholder="Zauber durchsuchen"
-    (keyup)="
-      isModification ? filterSpellArrayForModification() : filterSpellArray()
-    "
-  />
-  <div class="available-spells">
-    <ul>
-      @for(spell of availableSpells; track spell) {
-      <li>
-        <button
-          (click)="
-            isModification
-              ? emitNewSpellFromOfficial(spell)
-              : spellSelected(spell)
-          "
-        >
-          {{ spell.german }}
-        </button>
-      </li>
-      } @empty { Keine Zauber gefunden }
-    </ul>
+    <button class="cancel-button" (click)="resetThis()">Abbrechen</button>
   </div>
-  <button class="cancel-button" (click)="resetThis()">Abbrechen</button>
   }
 </div>

+ 52 - 5
src/app/journal/journal-spellcards/add-card/add-card.component.scss

@@ -8,7 +8,38 @@
     overflow: hidden;
     transition: all 0.3s ease-in-out;
 
-    .clickable-background {
+    .button-card {
+        height: 100%;
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+
+        button {
+            height: 33.3%;
+            width: 100%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            background-color: var(--items);
+            &:hover {
+                background-color: var(--items-hover);
+            }
+            transition: all 0.2s ease-in-out;
+            // cursor: pointer;
+        }
+
+        hr {
+            margin: 0;
+        }
+
+        button {
+            border: none;
+            font-size: 1.125rem;
+            font-weight: 600;
+        }
+    }
+
+    .clickable-card {
         width: 100%;
         height: 100%;
         position: relative;
@@ -29,6 +60,13 @@
     }
 }
 
+.spell-selection {
+    width: 100%;
+    height: 100%;
+    background-color: var(--background-color);
+    padding-top: 0.875rem;
+}
+
 .add-button {
     width: 90%;
     margin: 0 0.5rem;
@@ -47,10 +85,11 @@
 
 .spell-name {
     width: 94%;
-    margin: 1rem auto;
+    margin: auto;
     display: block;
     border-radius: 5px;
     border: var(--border);
+    // box-shadow: var(--shadow);
 }
 
 .available-spells {
@@ -58,9 +97,10 @@
     padding: 0.5rem;
     border: var(--border);
     border-radius: 5px;
-    // box-shadow: var(--shadow);
     overflow: auto;
-    height: 12rem;
+    height: 13rem;
+    background-color: white;
+    box-shadow: var(--shadow);
 
     button {
         all: unset;
@@ -70,6 +110,13 @@
         margin: 0 auto 0.375rem auto;
         display: block;
         width: 90%;
+        box-shadow: var(--shadow);
+        cursor: pointer;
+        transition: all 0.2s ease-in-out;
+        background-color: var(--items);
+        &:hover {
+            background-color: var(--items-hover);
+        }
     }
 }
 
@@ -83,7 +130,7 @@ ul {
     width: 10rem;
     height: 2.5rem;
     display: block;
-    margin: 1rem auto 0 auto;
+    margin: 0.75rem auto 0 auto;
     background-color: var(--delete);
     border: var(--border);
     border-radius: 10px;

+ 7 - 1
src/app/journal/journal-spellcards/add-card/add-card.component.ts

@@ -34,6 +34,8 @@ export class AddCardComponent {
     );
     this.filterSpellArray();
     this.spellsAccessor.closeSubject$.subscribe((level) => {
+      console.log('Close subject received: ', level);
+
       if (level !== this.level) {
         this.resetThis();
       }
@@ -65,7 +67,7 @@ export class AddCardComponent {
     } else {
       this.filterSpellArray();
     }
-    this.spellsAccessor.closeAllOthers(this.level);
+    this.closeOthers();
   }
 
   public spellSelected(spell: any): void {
@@ -73,6 +75,10 @@ export class AddCardComponent {
     this.resetThis();
   }
 
+  public closeOthers(): void {
+    this.spellsAccessor.closeAllOthers(this.level);
+  }
+
   public resetThis(): void {
     this.newSpellName = '';
     this.state = 1;

+ 26 - 0
src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.html

@@ -0,0 +1,26 @@
+<div class="dimensions">
+  <div class="content">
+    <div class="title">Eigene Zauber verwalten</div>
+    <div class="spell-list">
+      @for(spell of spells; let index = $index; track spell){
+
+      <div
+        matRipple
+        class="spell"
+        [ngClass]="{ selected: indexList.includes(index) }"
+        (click)="toggleSpellSelection(index)"
+      >
+        {{ spell.german }}
+      </div>
+      }
+    </div>
+  </div>
+  <div class="horizontal-buttons" style="padding: 2rem 1.5rem">
+    <ui-button [color]="'red'" [width]="'w15'" (click)="delete()"
+      >Ausgewählte Löschen</ui-button
+    >
+    <ui-button [color]="'red'" [width]="'w15'" (click)="cancel()"
+      >Abbrechen</ui-button
+    >
+  </div>
+</div>

+ 60 - 0
src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.scss

@@ -0,0 +1,60 @@
+.dimensions {
+    width: 35rem;
+    height: 45rem;
+    padding: 0;
+}
+
+.title {
+    box-shadow: var(--shadow-bottom);
+    padding: 1.5rem 0 1rem 0;
+    margin-top: 0;
+}
+
+.content {
+    margin: 0;
+}
+
+.spell-list {
+    height: 32rem;
+    padding: 1rem 1rem 0 1rem;
+    overflow-y: auto;
+    gap: 0.5rem;
+}
+
+.spell {
+    height: 3rem;
+    padding: 15px 10px;
+    margin-bottom: 0.5rem;
+    color: rgba(0, 0, 0, 0.87);
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    background: var(--items);
+    border-radius: 10px;
+    border: var(--border);
+    font-size: 1rem;
+    font-weight: 600;
+    // text-align: center;
+    cursor: pointer;
+    box-shadow:
+        0 5px 5px -3px rgba(0, 0, 0, 0.2),
+        0 8px 8px 1px rgba(0, 0, 0, 0.14),
+        0 3px 10px 2px rgba(0, 0, 0, 0.12);
+    transition: background-color 0.2s ease-in-out;
+    &:hover {
+        background-color: #f8d8c6;
+    }
+}
+
+.selected {
+    background-color: #f8d8c6;
+    box-sizing: border-box;
+    border: 3px solid var(--primary);
+    &:hover {
+        background-color: var(--items);
+    }
+}
+
+.horizontal-buttons {
+    box-shadow: var(--shadow-top);
+}

+ 23 - 0
src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CustomSpellsModalComponent } from './custom-spells-modal.component';
+
+describe('CustomSpellsModalComponent', () => {
+  let component: CustomSpellsModalComponent;
+  let fixture: ComponentFixture<CustomSpellsModalComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [CustomSpellsModalComponent]
+    })
+    .compileComponents();
+    
+    fixture = TestBed.createComponent(CustomSpellsModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 35 - 0
src/app/journal/journal-spellcards/custom-spells-modal/custom-spells-modal.component.ts

@@ -0,0 +1,35 @@
+import { Component, Input } from '@angular/core';
+import { Spell } from 'src/interfaces/spell';
+import { ModalService } from 'src/services/modal/modal.service';
+
+@Component({
+  selector: 'custom-spells-modal',
+  templateUrl: './custom-spells-modal.component.html',
+  styleUrl: './custom-spells-modal.component.scss',
+})
+export class CustomSpellsModalComponent {
+  @Input() public spells: Spell[] = [];
+  public indexList: number[] = [];
+
+  public constructor(private modalAccessor: ModalService) {}
+
+  public toggleSpellSelection(index: number): void {
+    if (this.indexList.includes(index)) {
+      this.indexList = this.indexList.filter((i) => i !== index);
+    } else {
+      this.indexList.push(index);
+    }
+  }
+
+  public delete(): void {
+    const deletionList: Spell[] = [];
+    this.indexList.forEach((index) => deletionList.push(this.spells[index]));
+    this.modalAccessor.handleModalClosing('delete', deletionList);
+    this.indexList = [];
+  }
+
+  public cancel(): void {
+    this.modalAccessor.handleModalClosing('cancel', undefined);
+    this.indexList = [];
+  }
+}

+ 6 - 2
src/app/journal/journal-spellcards/journal-spellcards.component.html

@@ -1,7 +1,11 @@
 <div class="spellcards-container">
+  <button class="manage-spells" (click)="openManageCustomSpellsModal()">
+    <img src="assets/icons/UIIcons/settings.svg" /> Eigene Zauber verwalten
+  </button>
+
   <div cdkDropListGroup>
     <!-- TODO: revert array to 0-9 -->
-    @for(level of [0,1]; track level; let index = $index) {
+    @for(level of [0,1,2,3]; track level; let index = $index) {
 
     <div class="example-container">
       <div
@@ -50,7 +54,7 @@
           (createNewSpellFromOfficial)="
             openSpellCreationModal(index, true, $event)
           "
-          (onSpellSelected)="handleSpellSelection($event, index)"
+          (onSpellSelected)="addSpellToSpelllist($event, index)"
         ></add-card>
         }
       </div>

+ 19 - 0
src/app/journal/journal-spellcards/journal-spellcards.component.scss

@@ -5,6 +5,25 @@
   overflow-y: auto;
   display: flex;
   flex-direction: column;
+  position: relative;
+}
+
+.manage-spells {
+  position: absolute;
+  right: 2rem;
+  top: 1rem;
+  font-size: 1.25rem;
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  gap: 0.5rem;
+  border-radius: 10px;
+  padding: 0.5rem 1rem;
+  box-shadow: var(--shadow);
+  background: var(--edit);
+  &:hover {
+    background: var(--edit-hover);
+  }
 }
 
 .example-container {

+ 75 - 16
src/app/journal/journal-spellcards/journal-spellcards.component.ts

@@ -1,9 +1,6 @@
 import { Component } from '@angular/core';
 import {
   CdkDragDrop,
-  CdkDrag,
-  CdkDropList,
-  CdkDropListGroup,
   moveItemInArray,
   transferArrayItem,
 } from '@angular/cdk/drag-drop';
@@ -12,13 +9,8 @@ import { DataService } from 'src/services/data/data.service';
 import { ModalService } from 'src/services/modal/modal.service';
 import { SpellsService } from 'src/services/spells/spells.service';
 import { SpellModalComponent } from 'src/app/journal/spell-modal/spell-modal.component';
-import { NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
-import { Observable, OperatorFunction } from 'rxjs';
-import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
-import { FormsModule } from '@angular/forms';
-import { JsonPipe } from '@angular/common';
-import { FormControl } from '@angular/forms';
 import { FullSpellcardComponent } from 'src/app/shared-components/full-spellcard/full-spellcard.component';
+import { CustomSpellsModalComponent } from './custom-spells-modal/custom-spells-modal.component';
 
 @Component({
   selector: 'app-journal-spellcards',
@@ -53,9 +45,9 @@ export class JournalSpellcardsComponent {
   public draggingIndex: number | undefined;
 
   public constructor(
-    public dataAccessor: DataService,
+    private dataAccessor: DataService,
     private modalAccessor: ModalService,
-    private spellsService: SpellsService
+    public spellsService: SpellsService
   ) {
     this.loadSpells();
     this.hideEmptySpelllists();
@@ -109,7 +101,11 @@ export class JournalSpellcardsComponent {
     );
   }
 
-  // TODO: Update favorites, when modifying a spell
+  /**
+   * Opens a modal to modify an existing spell. The spell is then updated in the dataAccessor, local level and favorites.
+   * @param level The current level of the spell.
+   * @param index The index where the spell is located in the spell list.
+   */
   public openSpellModificationModal(level: number, index: number): void {
     this.modalAccessor.openModal(SpellModalComponent, {
       spell:
@@ -160,33 +156,91 @@ export class JournalSpellcardsComponent {
     const resultSubscription = this.modalAccessor.result$.subscribe(
       (result) => {
         if (result.state === 'add') {
-          console.warn('Add spell: ', result.data);
-
           this.addSpell(result.data, level);
           // this.spellsService.addCustomSpell(result.data);
           this.dataAccessor.addCustomSpell(result.data);
         } else {
-          console.warn('Result state from modal: ' + result.state);
         }
         resultSubscription.unsubscribe();
       }
     );
   }
 
-  public handleSpellSelection(spell: Spell, level: number): void {
+  /**
+   * Opens the modal to manage custom spells. Here, custom spells can be deleted.
+   */
+  public openManageCustomSpellsModal(): void {
+    this.modalAccessor.openModal(CustomSpellsModalComponent, {
+      spells: this.dataAccessor.customSpells,
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        console.warn('CustomSpellsModalComponent: result', result);
+
+        if (result.state === 'delete') {
+          result.data.forEach((spell: Spell) => {
+            this.deleteCustomSpell(spell);
+          });
+        }
+        resultSubscription.unsubscribe();
+      }
+    );
+  }
+
+  /**
+   * Deletes a custom spell from the custom spells list.
+   * It is deleted in the spells and data service.
+   * It is also removed from the prepared and favorite spells list if present.
+   * @param spell
+   */
+  public deleteCustomSpell(spell: Spell): void {
+    this.dataAccessor.deleteCustomSpell(spell);
+    this.spellsService.deleteCustomSpell(spell);
+    let list = this.getSpellList(spell.level);
+    const index = list.findIndex((spellList) => spellList.id === spell.id);
+    if (index > -1) {
+      list.splice(index, 1);
+      this.dataAccessor.removeFavoriteSpell(spell);
+      this.updateSpellsInDatabase(spell.level);
+    }
+  }
+
+  /**
+   * Adds a given spell to the spelllist of a specific level.
+   * @param spell The spell to add.
+   * @param level The level the spell needs to be added to.
+   */
+  public addSpellToSpelllist(spell: Spell, level: number): void {
     this.addSpell(spell, level);
   }
 
+  /**
+   * Adds a given spell to the spell list specified by level.
+   * Also updates the spell list in the database.
+   * @param spell The spell to add.
+   * @param level The level to add the spell to.
+   */
   public addSpell(spell: Spell, level: number) {
     this.getSpellList(level).push(spell);
     this.updateSpellsInDatabase(level);
   }
 
+  /**
+   * Overrides a spell in a given spell list, specified by the index.
+   * @param spell The new spell.
+   * @param level The level to add the spell to.
+   * @param index The index at which the spell should be overridden.
+   */
   public updateSpell(spell: Spell, level: number, index: number): void {
     this.getSpellList(level)![index] = spell;
     this.updateSpellsInDatabase(level);
   }
 
+  /**
+   * Returns the reference to the spell list specified by the level.
+   * @param level Specifies the level of the spell list.
+   * @returns Returns the spell list specified by the level.
+   */
   public getSpellList(level: number): Spell[] {
     switch (level) {
       case 0:
@@ -215,6 +269,11 @@ export class JournalSpellcardsComponent {
     }
   }
 
+  /**
+   * A lookup function to match spell levels from 0-9 to strings eg: 2 => "Level 2".
+   * @param level The level that is looked up.
+   * @returns Returns a string with the name to display in the view.
+   */
   public getSpellLevel(level: number): string {
     switch (level) {
       case 0:

+ 1 - 1
src/app/journal/journal-spellcards/spellcard/spellcard.component.html

@@ -13,7 +13,7 @@
   </div>
   <img
     class="spell-image"
-    [src]="'assets/images/spells/' + spell.english + '.jpg'"
+    [src]="'assets/images/spells/' + spell.image + '.jpg'"
     (error)="setBackupImage($event)"
     [style.box-shadow]="'var(--' + spell.school.toLowerCase() + '-border)'"
     alt="spell image"

+ 4 - 21
src/app/journal/journal-spellcards/spellcard/spellcard.component.ts

@@ -10,32 +10,15 @@ import { TranslatorService } from 'src/services/translator/translator.service';
 export class SpellcardComponent {
   @Input() public spell!: Spell;
   public schools: any;
-  public backgroundColors: any = {
-    Abjuration: '#F0E3CE', //final
-    Conjuration: '#26714a', //final
-    Divination: '#F0E3CE', //final
-    Enchantment: '#629179', //final
-    Evocation: '#a46a7d',
-    Illusion: '#69a', //final
-    Necromancy: '#000000', //final
-    Transmutation: '#69a', //final
-  };
-
-  public borders: any = {
-    Abjuration: '0 0 0 2px #171314, 0 0 0 5px #FFFFFF',
-    Conjuration: '0 0 0 2px #171314, 0 0 0 5px #26714a', //final
-    Divination: '0 0 0 2px #171314, 0 0 0 5px #FFFFFF',
-    Enchantment: '0 0 0 2px #171314, 0 0 0 5px #26714a', //final
-    Evocation: '0 0 0 2px #171314, 0 0 0 5px #863f57',
-    Illusion: '0 0 0 2px #171314, 0 0 0 5px #2d6475', //final
-    Necromancy: '0 0 0 2px #171314, 0 0 0 5px #36353a', //final
-    Transmutation: '0 0 0 2px #171314, 0 0 0 5px #2d6475', //final
-  };
 
   public constructor(public translator: TranslatorService) {
     this.schools = translator.schools;
   }
 
+  public ngOnInit(): void {
+    console.log(this.spell);
+  }
+
   public setBackupImage(event: any): void {
     event.target.src = 'assets/images/spells/backup.jpg';
   }

+ 5 - 3
src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.html

@@ -1,5 +1,7 @@
 <div class="dimensions">
-  <div class="title">Fähigkeit @if(isUpdate){anpassen}@else{erstellen}</div>
+  <div class="title">
+    Fähigkeit @if(isUpdate && !isAddedFromCharacter){anpassen}@else{erstellen}
+  </div>
 
   <div class="flex-form t-15">
     <div>
@@ -65,13 +67,13 @@
     </div>
 
     <div class="horizontal-buttons">
-      @if(isUpdate){
+      @if(isUpdate && !isAddedFromCharacter){
       <ui-button [color]="'green'" style="width: 45%" (click)="update()"
         >Aktualisieren</ui-button
       >
       }@else{
       <ui-button [color]="'green'" style="width: 45%" (click)="add()"
-        >hinzufügen</ui-button
+        >Hinzufügen</ui-button
       >
       }
       <ui-button [color]="'red'" style="width: 45%" (click)="cancel()"

+ 1 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.ts

@@ -11,6 +11,7 @@ import { Ability } from 'src/interfaces/ability';
 export class AbilityModalComponent {
   @Input() public isUpdate: boolean = false;
   @Input() public ability: Ability | undefined;
+  @Input() public isAddedFromCharacter: boolean = false;
 
   shortEditor: Editor = new Editor();
   longEditor: Editor = new Editor();

+ 14 - 14
src/app/journal/journal-stats/ability-panel/proficiencies-table/proficiencies-table.component.html

@@ -7,33 +7,33 @@
         </mat-expansion-panel-header>
         <form [formGroup]="proficiencies" (change)="updateDatabase()">
           <div class="centered-line">
-            <input type="checkbox" formControlName="light" />
-            <label>Leichte Rüstungen</label>
+            <input id="light" type="checkbox" formControlName="light" />
+            <label for="light">Leichte Rüstungen</label>
           </div>
           <div class="centered-line">
-            <input type="checkbox" formControlName="medium" />
-            <label>Mittlere Rüstungen</label>
+            <input id="medium" type="checkbox" formControlName="medium" />
+            <label for="medium">Mittlere Rüstungen</label>
           </div>
           <div class="centered-line">
-            <input type="checkbox" formControlName="heavy" />
-            <label>Schwere Rüstungen</label>
+            <input id="heavy" type="checkbox" formControlName="heavy" />
+            <label for="heavy">Schwere Rüstungen</label>
           </div>
           <div class="centered-line">
-            <input type="checkbox" formControlName="shields" />
-            <label>Schilde</label>
+            <input id="shields" type="checkbox" formControlName="shields" />
+            <label for="shields">Schilde</label>
           </div>
           <div class="centered-line">
-            <input type="checkbox" formControlName="simple" />
-            <label>Einfache Waffen</label>
+            <input id="simple" type="checkbox" formControlName="simple" />
+            <label for="simple">Einfache Waffen</label>
           </div>
 
           <div class="centered-line">
-            <input type="checkbox" formControlName="martial" />
-            <label>Schwere Waffen</label>
+            <input id="martial" type="checkbox" formControlName="martial" />
+            <label for="martial">Schwere Waffen</label>
           </div>
           <div class="centered-line">
-            <label>Weitere Waffen</label>
-            <input formControlName="other" />
+            <label for="other">Weitere Waffen</label>
+            <input id="other" formControlName="other" />
           </div>
         </form>
       </mat-expansion-panel>

+ 4 - 4
src/app/journal/journal-stats/ability-panel/trait-table/trait-modal/trait-modal.component.html

@@ -1,7 +1,7 @@
 <div class="dimensions">
   <div class="title">
-    <h3 *ngIf="!isUpdate">Eigenschaft erstellen</h3>
-    <h3 *ngIf="isUpdate">Eigenschaft anpassen</h3>
+    @if(isUpdate && !isAddedFromCharacter){Eigenschaft apassen}
+    @else{Eigenschaft erstellen}
   </div>
   <div class="flex-form t-15">
     <div>
@@ -40,13 +40,13 @@
     </div>
 
     <div class="horizontal-buttons">
-      @if(isUpdate){
+      @if(isUpdate && !isAddedFromCharacter){
       <ui-button [color]="'green'" style="width: 45%" (click)="update()"
         >Aktualisieren</ui-button
       >
       }@else{
       <ui-button [color]="'green'" style="width: 45%" (click)="add()"
-        >hinzufügen</ui-button
+        >Hinzufügen</ui-button
       >
       }
       <ui-button [color]="'red'" style="width: 45%" (click)="cancel()"

+ 1 - 0
src/app/journal/journal-stats/ability-panel/trait-table/trait-modal/trait-modal.component.ts

@@ -11,6 +11,7 @@ import { ModalService } from 'src/services/modal/modal.service';
 export class TraitModalComponent {
   @Input() public isUpdate: boolean = false;
   @Input() public trait: Trait | undefined;
+  @Input() public isAddedFromCharacter: boolean = false;
 
   shortEditor: Editor = new Editor();
   longEditor: Editor = new Editor();

+ 1 - 1
src/app/journal/journal-stats/life-container/life/life.component.scss

@@ -20,7 +20,7 @@
     display: flex;
     flex-direction: row;
     height: 4rem;
-    margin: 0 0.5rem;
+    margin: 0 1rem;
     border-radius: 10px;
     box-shadow: var(--shadow);
     overflow: hidden;

+ 2 - 2
src/app/journal/journal-stats/weapons-container/spell-table/favorite-spells-modal/favorite-spells-modal.component.html

@@ -91,7 +91,7 @@
 <ng-template #costTemplate let-spell="spell">
   <div class="bold">
     <span *ngIf="spell.cost === 'action'">A</span>
-    <span *ngIf="spell.cost === 'bonus'">B</span>
+    <span *ngIf="spell.cost === 'bonus action'">B</span>
     <span *ngIf="spell.cost === 'reaction'">R</span>
   </div>
 </ng-template>
@@ -163,7 +163,7 @@
     <div *ngIf="!spell.isRanged">Berührung</div>
 
     <div *ngIf="spell.hasAreaOfEffect">
-      <span>{{ spell.radius }} ft. {{ areas[spell.areaOfEffectType] }} </span>
+      <span>{{ spell.diameter }} ft. {{ areas[spell.areaOfEffectType] }} </span>
     </div>
   </div>
 </ng-template>

+ 1 - 1
src/app/journal/journal-stats/weapons-container/spell-table/spell-details/spell-details.component.html

@@ -22,7 +22,7 @@
   <div class="details-content-small">
     <div>Reichweite: {{ spell.range }} ft.</div>
     <div *ngIf="spell.hasAreaOfEffect">
-      Flächeneffekt: {{ spell.radius }} ft. {{ spell.areaOfEffectType }}
+      Flächeneffekt: {{ spell.diameter }} ft. {{ spell.areaOfEffectType }}
     </div>
   </div>
 

+ 2 - 2
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-details/weapon-details.component.html

@@ -12,9 +12,9 @@
 <div class="flex-row">
   <div class="label">Schaden:</div>
   @for(damage of weapon?.damage; let index = $index; track damage){
-  {{ damage.diceNumber }} {{ damage.diceType }}
+  {{ damage.diceNumber }} {{ damage.diceType }} &nbsp;
   <span *ngIf="index === 0 && damageModifier !== '0'">
-    {{ damageModifier }}
+    {{ damageModifier }} &nbsp;
   </span>
   {{ damageTranslator[damage.damageType] }}
 

+ 28 - 5
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.html

@@ -3,7 +3,7 @@
     @if(isUpdate){Waffe bearbeiten} @else{Waffe hinzufügen}
   </div>
 
-  <div class="content">
+  <div class="content b-0">
     <div class="input-label">Name</div>
     <mat-form-field appearance="outline" class="w-100">
       <input matInput [(ngModel)]="name" />
@@ -16,6 +16,14 @@
           <input id="proficient" type="checkbox" [(ngModel)]="proficient" />
           <label for="proficient">Geübt</label>
         </div>
+        <div class="checkbox-row">
+          <input
+            id="useAttributeModifier"
+            type="checkbox"
+            [(ngModel)]="useAttributeModifier"
+          />
+          <label for="useAttributeModifier">Attributmodifikator anwenden</label>
+        </div>
         <div class="checkbox-row">
           <input id="finesse" type="checkbox" [(ngModel)]="isFinesse" />
           <label for="finesse">Finesse</label>
@@ -47,6 +55,14 @@
           <input id="isMagical" type="checkbox" [(ngModel)]="isMagical" />
           <label for="isMagical">Magisch</label>
         </div>
+        <div class="checkbox-row">
+          <input
+            id="additionalDamage"
+            type="checkbox"
+            [(ngModel)]="hasAdditionalDamage"
+          />
+          <label for="additionalDamage">Zusatzschaden</label>
+        </div>
       </div>
     </div>
 
@@ -97,7 +113,7 @@
 
               <div class="damage-box">
                 <div class="subheading left t-025">
-                  @if(index == 0){Schaden} @else {Zusatzschaden}
+                  @if(index == 0){Schaden} @else {Weiterer Schaden}
                 </div>
                 <div class="input-label">Anzahl Würfel</div>
                 <mat-form-field appearance="outline">
@@ -141,6 +157,15 @@
                   [icon]="'delete'"
                   (click)="removeDamage(index)"
                 ></icon-button>
+                } @else if (hasAdditionalDamage){
+                <div class="input-label t-05">Zusatzschaden</div>
+                <mat-form-field appearance="outline">
+                  <mat-select [(ngModel)]="additionalDamage">
+                    @for (damage of additonalDamages; track damage) {
+                    <mat-option [value]="damage"> +{{ damage }} </mat-option>
+                    }
+                  </mat-select>
+                </mat-form-field>
                 }
               </div>
               @if(damage.length < 2){
@@ -248,7 +273,7 @@
       ></div>
     </div>
 
-    <hr />
+    <hr style="margin-bottom: 0" />
   </div>
 
   <div class="horizontal-buttons">
@@ -266,5 +291,3 @@
     </ui-button>
   </div>
 </div>
-
-Hallo, was geht ab ? Ich möchte gerne

+ 1 - 3
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.scss

@@ -41,6 +41,7 @@
 
     input {
         -moz-appearance: textfield;
+        appearance: textfield;
     }
 
     .input-value {
@@ -73,16 +74,13 @@ div.nav-pills.flex-column.nav {
     border-right: 1px solid rgba(0, 0, 0, 0.125);
     padding-right: 4px;
     width: 11rem;
-    // box-shadow: var(--shadow);
 
     .nav-link {
         width: 100%;
         border-radius: 10px;
         transition: all 0.25s ease-in-out;
-        // font-size: 1.25rem;
         font-weight: 600;
         color: var(--text);
-        // padding: 0;
 
         &.active,
         &:hover {

+ 14 - 0
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.ts

@@ -20,6 +20,9 @@ export class WeaponModalComponent {
   public throwRange: number[] = [5, 5];
   public attackBonus: string = '+0';
   public damage: Damage[] = [{ diceNumber: '', diceType: '', damageType: '' }];
+  public hasAdditionalDamage: boolean = false;
+  public additionalDamage: number = 0;
+  public useAttributeModifier: boolean = false;
   public proficient: boolean = false;
   public isVersatile: boolean = false;
   public isTwoHanded: boolean = false;
@@ -102,6 +105,8 @@ export class WeaponModalComponent {
     '+20',
   ];
 
+  additonalDamages: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
   public magicBonuses: any[] = [
     { display: '+1', value: 1 },
     { display: '+2', value: 2 },
@@ -123,6 +128,9 @@ export class WeaponModalComponent {
     this.throwRange = this.item.throwRange;
     this.attackBonus = this.item.attackBonus;
     this.damage = this.item.damage;
+    this.hasAdditionalDamage = this.item.hasAdditionalDamage;
+    this.additionalDamage = this.item.additionalDamage;
+    this.useAttributeModifier = this.item.useAttributeModifier;
     this.proficient = this.item.proficient;
     this.isVersatile = this.item.isVersatile;
     this.isTwoHanded = this.item.isTwoHanded;
@@ -162,6 +170,9 @@ export class WeaponModalComponent {
       throwRange: this.throwRange,
       attackBonus: this.attackBonus,
       damage: this.damage,
+      hasAdditionalDamage: this.hasAdditionalDamage,
+      additionalDamage: this.additionalDamage,
+      useAttributeModifier: this.useAttributeModifier,
       proficient: this.proficient,
       isVersatile: this.isVersatile,
       isTwoHanded: this.isTwoHanded,
@@ -186,6 +197,9 @@ export class WeaponModalComponent {
     this.throwRange = [5, 5];
     this.attackBonus = '+0';
     this.damage = [{ diceNumber: '', diceType: '', damageType: '' }];
+    this.hasAdditionalDamage = false;
+    this.additionalDamage = 0;
+    this.useAttributeModifier = false;
     this.proficient = false;
     this.isVersatile = false;
     this.isTwoHanded = false;

+ 12 - 7
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-table.component.ts

@@ -71,19 +71,24 @@ export class WeaponTableComponent {
   }
 
   private calculateSingleDamageModifier(index: number): void {
-    let value: number;
+    let value: number = 0;
     let bonus: number = 0;
     const weapon: Weapon = this.weapons[index];
-    if (this.isMonk || weapon.isFinesse) {
-      value = Math.max(this.strengthValue, this.dexterityValue);
-    } else if (weapon.isRanged) {
-      value = this.dexterityValue;
-    } else {
-      value = this.strengthValue;
+    if (weapon.useAttributeModifier) {
+      if (this.isMonk || weapon.isFinesse) {
+        value = Math.max(this.strengthValue, this.dexterityValue);
+      } else if (weapon.isRanged) {
+        value = this.dexterityValue;
+      } else {
+        value = this.strengthValue;
+      }
     }
     if (weapon.isMagical) {
       bonus = weapon.magicBonus!;
     }
+    if (weapon.hasAdditionalDamage) {
+      bonus += weapon.additionalDamage!;
+    }
     this.damageModifiers[index] = this.calculateModifier(value, bonus);
   }
 

+ 2 - 0
src/app/journal/journal.module.ts

@@ -94,6 +94,7 @@ import { BackgroundComponent } from './journal-character/background/background.c
 import { StoryComponent } from './journal-character/story/story.component';
 import { FavoriteSpellsModalComponent } from './journal-stats/weapons-container/spell-table/favorite-spells-modal/favorite-spells-modal.component';
 import { MatRippleModule } from '@angular/material/core';
+import { CustomSpellsModalComponent } from './journal-spellcards/custom-spells-modal/custom-spells-modal.component';
 
 @NgModule({
   declarations: [
@@ -171,6 +172,7 @@ import { MatRippleModule } from '@angular/material/core';
     BackgroundComponent,
     StoryComponent,
     FavoriteSpellsModalComponent,
+    CustomSpellsModalComponent,
   ],
   imports: [
     CommonModule,

+ 345 - 111
src/app/journal/spell-modal/spell-modal.component.html

@@ -1,78 +1,334 @@
-<div class="modal-dimensions">
-  <h2 style="text-align: center">
+<div class="dimensions">
+  <div class="title">
     @if(isModification){Zauber bearbeiten}@else{Zauber erstellen}
-  </h2>
-
-  <div class="add-form-group">
-    <div class="input-element">
-      <label for="weaponName">Name</label>
-      <input
-        type="text"
-        class="add-input"
-        id="weaponName"
-        [(ngModel)]="german"
-      />
-    </div>
-    <div class="form-element-row">
-      <!-- general -->
-      <div class="checkbox-element">
-        <input type="checkbox" [(ngModel)]="needsVerbal" />
-        <label>Verbal</label>
-      </div>
-      <div class="checkbox-element">
-        <input type="checkbox" [(ngModel)]="needsSomatic" />
-        <label>Geste</label>
-      </div>
-      <div class="checkbox-element">
-        <input type="checkbox" [(ngModel)]="needsMaterial" />
-        <label>Material</label>
-      </div>
+  </div>
 
-      <div class="checkbox-element">
-        <input type="checkbox" [(ngModel)]="needsConcentration" />
-        <label>Konzentration</label>
-      </div>
+  <div class="content b-0">
+    <div class="input-label">Name</div>
+    <mat-form-field appearance="outline" class="w-100">
+      <input matInput [(ngModel)]="name" />
+    </mat-form-field>
+    <hr />
 
-      <div class="checkbox-element">
-        <select [(ngModel)]="cost">
-          <option *ngFor="let cost of costs" [value]="cost.value">
-            {{ cost.display }}
-          </option>
-        </select>
-        <label>Kosten</label>
+    <div class="flex-row t-1">
+      <div class="checkbox-column">
+        <div class="checkbox-row">
+          <input id="verbal" type="checkbox" [(ngModel)]="needsVerbal" />
+          <label for="verbal">Verbal</label>
+        </div>
+        <div class="checkbox-row">
+          <input id="somatic" type="checkbox" [(ngModel)]="needsSomatic" />
+          <label for="somatic">Geste</label>
+        </div>
+        <div class="checkbox-row">
+          <input id="material" type="checkbox" [(ngModel)]="needsMaterial" />
+          <label for="material">Material</label>
+        </div>
+        <div class="checkbox-row">
+          <input
+            id="concentration"
+            type="checkbox"
+            [(ngModel)]="needsConcentration"
+          />
+          <label for="concentration">Konzentration</label>
+        </div>
+
+        <div class="checkbox-row">
+          <input
+            id="canRitual"
+            type="checkbox"
+            (change)="unsetRitual($event)"
+            [(ngModel)]="canRitual"
+          />
+          <label for="canRitual">Ritual möglich</label>
+        </div>
+        <div class="checkbox-row">
+          <input
+            id="isRitual"
+            type="checkbox"
+            (change)="setRitual($event)"
+            [(ngModel)]="isRitual"
+          />
+          <label for="isRitual">Ist Ritual</label>
+        </div>
       </div>
+      <div class="checkbox-column">
+        <div class="checkbox-row">
+          <input id="doesDamage" type="checkbox" [(ngModel)]="doesDamage" />
+          <label for="doesDamage">Schaden</label>
+        </div>
+        <div class="checkbox-row">
+          <input id="doesHeal" type="checkbox" [(ngModel)]="doesHeal" />
+          <label for="doesHeal">Heilung</label>
+        </div>
+        <div class="checkbox-row">
+          <input id="isRanged" type="checkbox" [(ngModel)]="isRanged" />
+          <label for="isRanged">Hat Reichweite</label>
+        </div>
+        <div class="checkbox-row">
+          <input
+            id="hasAreaOfEffect"
+            type="checkbox"
+            [(ngModel)]="hasAreaOfEffect"
+          />
+          <label for="hasAreaOfEffect">Hat Flächeneffekt</label>
+        </div>
 
-      <div class="checkbox-element">
-        <input type="checkbox" [(ngModel)]="canRitual" />
-        <label>Ritual möglich?</label>
+        <div class="checkbox-row">
+          <input
+            id="needsSavingThrow"
+            type="checkbox"
+            [(ngModel)]="needsSavingThrow"
+          />
+          <label for="needsSavingThrow">Erfordert Rettungswurf</label>
+        </div>
+        <div class="checkbox-row">
+          @if(!needsSavingThrow){
+          <input
+            id="needsAttackRoll"
+            type="checkbox"
+            [(ngModel)]="needsAttackRoll"
+          />
+          <label for="needsAttackRoll">Erfordert Angriffswurf</label>
+          }@else {
+          <label>Attribut</label>
+          <select [(ngModel)]="savingThrowAttribute" *ngIf="needsSavingThrow">
+            <option
+              *ngFor="let attribute of savingThrowAttributes"
+              [value]="attribute.value"
+            >
+              {{ attribute.display }}
+            </option>
+          </select>
+          }
+        </div>
       </div>
 
-      <div class="checkbox-element">
-        <select [(ngModel)]="level">
-          <option
-            *ngFor="let level of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
-            [value]="level"
-          >
-            @if(level == 0){Zaubertrick}@else{ {{ level }}}
-          </option>
-        </select>
-        <label>Stufe</label>
+      <div class="checkbox-column">
+        <div class="input-row">
+          <label>Kosten</label>
+          <mat-form-field appearance="outline">
+            <mat-select [(ngModel)]="cost">
+              @for (cost of costs; track cost) {
+              <mat-option [value]="cost.value">{{ cost.display }}</mat-option
+              >}
+            </mat-select>
+          </mat-form-field>
+        </div>
+
+        <div class="input-row duration">
+          <label>Dauer</label>
+          <mat-form-field appearance="outline">
+            <input type="number" matInput [(ngModel)]="duration" />
+            <span matSuffix class="suffix">Runden</span>
+          </mat-form-field>
+        </div>
+
+        <div class="input-row">
+          <label>Stufe</label>
+          <mat-form-field appearance="outline">
+            <mat-select [(ngModel)]="level">
+              @for (level of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; track level) {
+              <mat-option [value]="level">{{ level }}</mat-option
+              >}
+            </mat-select>
+          </mat-form-field>
+        </div>
+        <div class="input-row">
+          <label>Schule</label>
+          <mat-form-field appearance="outline">
+            <mat-select [(ngModel)]="school">
+              @for (school of schools; track school) {
+              <mat-option [value]="school.value">{{
+                school.display
+              }}</mat-option
+              >}
+            </mat-select>
+          </mat-form-field>
+        </div>
       </div>
+    </div>
 
-      <div class="checkbox-element">
-        <select [(ngModel)]="school">
-          <option *ngFor="let school of schools" [value]="school.value">
-            {{ school.display }}
-          </option>
-        </select>
-        <label>Schule</label>
+    <hr />
+
+    <!-- TAB-PANEL -->
+    <div class="d-flex">
+      <div
+        ngbNav
+        #nav="ngbNav"
+        [(activeId)]="active"
+        class="flex-column navigation-bar"
+        orientation="vertical"
+      >
+        <!-- DAMAGE -->
+        <ng-container ngbNavItem="damage">
+          @if(doesDamage){
+          <button ngbNavLink>Schaden</button>
+          }@else {
+          <button class="disabled-button" disabled>Schaden</button>
+          }
+          <ng-template ngbNavContent>
+            <div class="tab-content flex-row t-05">
+              @for(damageEntry of damage; let index = $index; track
+              damageEntry){
+
+              <div class="damage-box">
+                <div class="subheading left t-025">
+                  @if(index == 0){Schaden} @else {Weiterer Schaden}
+                </div>
+                <div class="input-label">Anzahl Würfel</div>
+                <mat-form-field appearance="outline">
+                  <mat-select [(ngModel)]="damageEntry.diceNumber">
+                    @for (number of numbers; track number) {
+                    <mat-option [value]="number"> {{ number }} </mat-option>}
+                  </mat-select>
+                </mat-form-field>
+
+                <div class="input-label t-05">Würfelart</div>
+                <mat-form-field appearance="outline">
+                  <mat-select [(ngModel)]="damageEntry.diceType">
+                    @for (die of dice; track die) {
+                    <mat-option [value]="die"> {{ die }} </mat-option>}
+                  </mat-select>
+                </mat-form-field>
+
+                <div class="input-label t-05">Schadensart</div>
+                <mat-form-field appearance="outline">
+                  <mat-select [(ngModel)]="damageEntry.damageType">
+                    @for (type of damageTypes; track type) {
+                    <mat-option [value]="type.value">
+                      {{ type.display }}
+                    </mat-option>
+                    }
+                  </mat-select>
+                </mat-form-field>
+                @if(index !== 0){
+                <icon-button
+                  [icon]="'delete'"
+                  (click)="removeDamage(index)"
+                ></icon-button>
+                }
+              </div>
+              @if(damage.length < 2){
+              <icon-button
+                [icon]="'add'"
+                style="margin-top: 7rem; margin-left: 5rem"
+                (click)="addDamage()"
+              ></icon-button>
+              } }
+            </div>
+          </ng-template>
+        </ng-container>
+        <!-- HEAL -->
+        <ng-container ngbNavItem="heal">
+          @if(doesHeal){
+          <button ngbNavLink>Heilung</button>} @else {
+          <button class="disabled-button" disabled>Heilung</button>
+          }
+          <ng-template ngbNavContent>
+            <div class="tab-content t-05">
+              <div class="input-label">Würfelanzahl</div>
+              <mat-form-field appearance="outline">
+                <mat-select [(ngModel)]="heal.diceNumber">
+                  @for (number of numbers; track number) {
+                  <mat-option [value]="number">{{ number }}</mat-option
+                  >}
+                </mat-select>
+              </mat-form-field>
+
+              <div class="input-label">Würfelart</div>
+              <mat-form-field appearance="outline">
+                <mat-select [(ngModel)]="heal.diceType">
+                  @for (die of dice; track die) {
+                  <mat-option [value]="die">{{ die }}</mat-option
+                  >}
+                </mat-select>
+              </mat-form-field>
+            </div>
+          </ng-template>
+        </ng-container>
+        <!-- RANGE -->
+        <ng-container ngbNavItem="range">
+          @if(isRanged || hasAreaOfEffect){
+          <button ngbNavLink>Reichweite</button>
+          } @else {
+          <button class="disabled-button" disabled>Reichweite</button>
+          }
+          <ng-template ngbNavContent>
+            <div class="range-container">
+              <div class="input-label">Reichweite</div>
+              <mat-form-field appearance="outline">
+                <input type="number" matInput [(ngModel)]="range" />
+                <span class="suffix" matTextSuffix>Fuß</span>
+              </mat-form-field>
+              @if(hasAreaOfEffect) {
+              <div class="input-label">Flächenart</div>
+              <mat-form-field appearance="outline">
+                <mat-select [(ngModel)]="areaOfEffectType">
+                  @for (areaType of areaTypes; track areaType) {
+                  <mat-option [value]="areaType.value">{{
+                    areaType.display
+                  }}</mat-option
+                  >}
+                </mat-select>
+              </mat-form-field>
+              <div class="input-label">Durchmesser</div>
+              <mat-form-field appearance="outline">
+                <input type="number" matInput [(ngModel)]="diameter" />
+                <span class="suffix" matTextSuffix>Fuß</span>
+              </mat-form-field>
+              }
+            </div>
+          </ng-template>
+        </ng-container>
+        <!-- DESCRIPTION -->
+        <ng-container ngbNavItem="description">
+          <button ngbNavLink>Beschreibung</button>
+          <ng-template ngbNavContent>
+            <div class="NgxEditor__Wrapper">
+              <ngx-editor-menu [editor]="editor" [toolbar]="toolbar">
+              </ngx-editor-menu>
+              <ngx-editor
+                [editor]="editor"
+                [(ngModel)]="description_de"
+                placeholder="Beschreibung des Zaubers"
+              ></ngx-editor>
+            </div>
+          </ng-template>
+        </ng-container>
       </div>
+
+      <div
+        [ngbNavOutlet]="nav"
+        style="
+          width: 100%;
+          min-height: 20rem;
+          max-height: 26rem;
+          overflow-y: auto;
+          overflow-x: hidden;
+        "
+        class="ms-4"
+      ></div>
     </div>
 
-    <!-- ranged and area -->
-    <h3 style="text-align: center">Reichweite und Fläche</h3>
+    <hr class="b-0" />
+  </div>
+
+  <!-- <div class="horizontal-buttons">
+    @if(isModification){
+    <ui-button [color]="'green'" style="width: 40%" (click)="update()">
+      Anpassen
+    </ui-button>
+    }@else{
+    <ui-button [color]="'green'" style="width: 40%" (click)="add()">
+      Erstellen
+    </ui-button>
+    }
+    <ui-button [color]="'red'" style="width: 40%" (click)="cancel()">
+      Abbrechen
+    </ui-button> -->
 
-    <div class="range-area-container">
+  <!-- <div class="range-area-container">
       <div class="range-box">
         <div class="checkbox-element">
           <input type="checkbox" [(ngModel)]="isRanged" />
@@ -90,8 +346,8 @@
           <label>Flächeneffekt</label>
         </div>
         <div class="input-element" *ngIf="hasAreaOfEffect">
-          <input type="text" class="add-input" [(ngModel)]="radius" />
-          <label>Radius</label>
+          <input type="text" class="add-input" [(ngModel)]="diameter" />
+          <label>diameter</label>
         </div>
         <div class="checkbox-element" *ngIf="hasAreaOfEffect">
           <select [(ngModel)]="areaOfEffectType">
@@ -105,16 +361,6 @@
     </div>
 
     <div style="display: flex">
-      <div>
-        <input type="checkbox" [(ngModel)]="doesDamage" />
-        <label>Schaden?</label>
-      </div>
-
-      <div>
-        <input type="checkbox" [(ngModel)]="doesHeal" />
-        <label>Heilung?</label>
-      </div>
-
       <div>
         <input type="checkbox" [(ngModel)]="needsSavingThrow" />
         <label>Rettungswurf?</label>
@@ -124,9 +370,9 @@
         <input type="checkbox" [(ngModel)]="needsAttackRoll" />
         <label>Angriff?</label>
       </div>
-    </div>
+    </div> -->
 
-    <ng-container
+  <!-- <ng-container
       *ngIf="needsSavingThrow"
       [ngTemplateOutlet]="attackTabContent"
     ></ng-container>
@@ -141,39 +387,27 @@
       [ngTemplateOutlet]="healTabContent"
     ></ng-container>
 
-    <ng-container [ngTemplateOutlet]="descriptionTabContent"></ng-container>
-
-    <!-- Button section -->
-    <div class="button-wrapper-2-block">
-      @if(isModification){
-      <ui-button
-        [type]="'update'"
-        [size]="'xlarge'"
-        [color]="'primary'"
-        (click)="update()"
-      ></ui-button>
-      }@else{
-      <ui-button
-        *ngIf="!isModification"
-        [type]="'add'"
-        [size]="'xlarge'"
-        [color]="'primary'"
-        (click)="add()"
-      ></ui-button>
-      }
-      <ui-button
-        [type]="'cancel'"
-        [size]="'xlarge'"
-        [color]="'primary'"
-        (click)="cancel()"
-      ></ui-button>
-    </div>
+    <ng-container [ngTemplateOutlet]="descriptionTabContent"></ng-container> -->
+
+  <!-- Button section -->
+  <div class="horizontal-buttons">
+    <ui-button
+      [color]="'green'"
+      style="width: 40%"
+      (click)="isModification ? update() : add()"
+    >
+      @if(isModification){Anwenden}@else{Erstellen}
+    </ui-button>
+    <ui-button [color]="'red'" style="width: 40%" (click)="cancel()"
+      >Abbrechen
+    </ui-button>
   </div>
 </div>
+<!-- </div> -->
 
 <!-- templates -->
 
-<ng-template #attackTabContent>
+<!-- <ng-template #attackTabContent>
   <div>
     <select [(ngModel)]="savingThrowAttribute" *ngIf="needsSavingThrow">
       <option
@@ -185,9 +419,9 @@
     </select>
     <label *ngIf="needsSavingThrow">Attribut</label>
   </div>
-</ng-template>
+</ng-template> -->
 
-<ng-template #damageTabContent>
+<!-- <ng-template #damageTabContent>
   <div class="damage-container">
     <div class="damage-box" *ngFor="let damage of damage; let index = index">
       <div class="dice-row">
@@ -235,9 +469,9 @@
       [class]="'pointer'"
     ></icon>
   </div>
-</ng-template>
+</ng-template> -->
 
-<ng-template #healTabContent>
+<!-- <ng-template #healTabContent>
   <div class="heal-container">
     <div class="dice-row">
       <div class="flex-column">
@@ -260,8 +494,8 @@
     </div>
     <label>Heilung</label>
   </div>
-</ng-template>
+</ng-template> -->
 
-<ng-template #descriptionTabContent>
+<!-- <ng-template #descriptionTabContent>
   <textarea style="height: 10rem" [(ngModel)]="description_de"></textarea>
-</ng-template>
+</ng-template> -->

+ 84 - 71
src/app/journal/spell-modal/spell-modal.component.scss

@@ -1,95 +1,108 @@
-.modal-dimensions {
-    width: 40vw;
-    background-color: antiquewhite;
-    border-radius: 10px;
-    border: 1px solid var(--border-color);
-    padding: 1rem;
-}
-
-.range-area-container {
-    display: flex;
-    flex-direction: row;
-}
-
-.range-box,
-.area-box {
+.checkbox-column {
+    width: 33.3%;
     display: flex;
     flex-direction: column;
-    flex-basis: 45%;
-    gap: 1rem;
+    gap: 0.5rem;
+    padding-left: 0.5rem;
 }
 
-.add-form-group {
+.checkbox-row {
     display: flex;
-    flex-direction: column;
+    flex-direction: row;
     gap: 1rem;
-}
-.input-element {
-    display: flex;
-    flex-direction: column;
-    // gap: 0.1rem;
-    // align-items: center;
-    // justify-content: center;
+    align-items: center;
 }
 
-.checkbox-element {
+.input-row {
     display: flex;
-    flex-direction: column;
+    flex-direction: row;
+    justify-content: space-between;
     align-items: center;
-    justify-content: center;
-    flex-basis: 33.33%;
 }
 
-.form-element-row {
-    display: flex;
-    flex-direction: row;
-    flex-wrap: wrap;
-    justify-content: space-around;
-    text-align: center;
-    row-gap: 1rem;
+.damage-box {
+    width: 50%;
 }
 
-.damage-container {
-    display: flex;
-    flex-direction: row;
-    gap: 1rem;
-    // align-items: center;
-    // justify-content: center;
+.damage-box {
+    icon-button {
+        padding-left: 4rem;
+        margin-bottom: 1rem;
+        margin-top: 0.5rem;
+    }
 }
 
-.damage-row {
-    display: flex;
-    flex-direction: row;
-    justify-content: center;
-    align-items: center;
-    gap: 0.1rem;
+.flex-row,
+.range-container {
+    ::ng-deep .mat-mdc-text-field-wrapper {
+        width: 10rem !important;
+    }
+    ::ng-deep .mat-mdc-form-field-infix {
+        height: 32px !important;
+        min-height: 32px !important;
+        padding-top: 4px !important;
+    }
+    input::-webkit-outer-spin-button,
+    input::-webkit-inner-spin-button {
+        display: none;
+    }
+
+    input {
+        -moz-appearance: textfield;
+        appearance: textfield;
+    }
 }
 
-.damage-box {
-    display: flex;
-    flex-direction: column;
-    align-items: left;
-    gap: 0.5rem;
-    flex-basis: 30%;
+.tab-content {
+    ::ng-deep .mat-mdc-text-field-wrapper {
+        width: 10rem !important;
+    }
+    ::ng-deep .mat-mdc-form-field-infix {
+        height: 40px !important;
+        min-height: 40px !important;
+        padding-top: 8px !important;
+    }
 }
 
-.dice-row {
-    display: flex;
-    flex-direction: row;
-    // justify-content: center;
-    // align-items: center;
-    gap: 1rem;
-    margin-bottom: 1rem;
+div.nav-pills.flex-column.nav {
+    border-right: 1px solid darkgray;
+    padding-right: 4px;
+}
+
+::ng-deep .ProseMirror {
+    height: 17.5rem !important;
+    overflow-y: auto;
 }
 
-.button-wrapper {
-    width: 100%;
-    display: grid;
-    grid-template-rows: 1fr 1fr;
-    grid-template-columns: 1fr;
-    gap: 10px;
-    margin-top: 2rem;
-    margin-top: 2rem;
+.navigation-bar {
+    padding-top: 0.5rem;
+    gap: 1rem;
+    height: 20rem;
     align-items: center;
-    justify-content: center;
+    border-right: 1px solid rgba(0, 0, 0, 0.125);
+    padding-right: 4px;
+    width: 11rem;
+
+    .nav-link {
+        width: 100%;
+        border-radius: 10px;
+        transition: all 0.25s ease-in-out;
+        font-weight: 600;
+        color: var(--text);
+
+        &.active,
+        &:hover {
+            background-color: var(--tab-active);
+            box-shadow: var(--shadow);
+        }
+    }
+
+    .disabled-button {
+        padding: 8px 0;
+        border: none;
+        font-weight: 600;
+        color: black;
+        cursor: not-allowed;
+        opacity: 0.5;
+    }
 }

+ 64 - 24
src/app/journal/spell-modal/spell-modal.component.ts

@@ -3,6 +3,7 @@ import { ModalService } from 'src/services/modal/modal.service';
 import { Damage } from 'src/interfaces/damage';
 import { Heal } from 'src/interfaces/heal';
 import { Spell } from 'src/interfaces/spell';
+import { Editor } from 'ngx-editor';
 
 @Component({
   selector: 'spell-modal',
@@ -19,18 +20,22 @@ export class SpellModalComponent {
   @Input() public isBasedOnOfficialSpell: boolean = false;
 
   // #region Properties
+  public name: string = '';
   public german: string = '';
   public english: string = '';
+  public image: string = '';
   public cost: string = 'action';
   public duration: number = 0;
   public timeToCast: number = 0;
-  public canRitual: 'true' | 'false' | 'only' = 'false';
+  public canRitual: boolean = false;
+  public isRitual: boolean = false;
   public needsConcentration: boolean = false;
   public needsVerbal: boolean = false;
   public needsSomatic: boolean = false;
   public needsMaterial: boolean = false;
-  public school: string = '';
+  public school: string = 'Evocation';
   public description_de: string = '';
+  public description_en: string = '';
   public doesDamage: boolean = false;
   public doesHeal: boolean = false;
   public needsAttackRoll: boolean = false;
@@ -46,30 +51,39 @@ export class SpellModalComponent {
   public isRanged: boolean = false;
   public range: number = 5;
   public hasAreaOfEffect: boolean = false;
-  public radius: number = 0;
-  public areaOfEffectType: string = '';
+  public diameter: number = 5;
+  public areaOfEffectType: string = 'circle';
 
+  active = 'description';
+  editor: Editor = new Editor();
+  html = '';
+  toolbar: any = [
+    // default value
+    ['bold', 'italic'],
+    ['bullet_list'],
+    [{ heading: ['h3', 'h4', 'h5', 'h6'] }],
+  ];
   // #endregion
 
   // #region OPTIONS
   public areaTypes: any[] = [
+    { display: 'Kreis', value: 'circle' },
     { display: 'Kegel', value: 'cone' },
     { display: 'Kugel', value: 'sphere' },
-    { display: 'Kreis', value: 'circle' },
     { display: 'Linie', value: 'line' },
     { display: 'Quadrat', value: 'square' },
     { display: 'Würfel', value: 'cube' },
   ];
 
   public schools: any[] = [
-    { display: 'Verwandlung', value: 'transmutation' },
-    { display: 'Verzauberung', value: 'enchantment' },
-    { display: 'Illusion', value: 'illusion' },
-    { display: 'Nekromantie', value: 'necromancy' },
-    { display: 'Beschwörung', value: 'conjuration' },
-    { display: 'Hervorrufung', value: 'evocation' },
-    { display: 'Bannmagie', value: 'abjuration' },
-    { display: 'Wahrsagerei', value: 'divination' },
+    { display: 'Verwandlung', value: 'Transmutation' },
+    { display: 'Verzauberung', value: 'Enchantment' },
+    { display: 'Illusion', value: 'Illusion' },
+    { display: 'Nekromantie', value: 'Necromancy' },
+    { display: 'Beschwörung', value: 'Conjuration' },
+    { display: 'Hervorrufung', value: 'Evocation' },
+    { display: 'Bannmagie', value: 'Abjuration' },
+    { display: 'Wahrsagerei', value: 'Divination' },
   ];
 
   public savingThrowAttributes: any[] = [
@@ -151,15 +165,21 @@ export class SpellModalComponent {
     if (this.isModification) {
       this.id = this.spell.id;
       this.german = this.spell.german;
+      this.english = this.spell.english;
+      // TODO: Implement internationalization
+      this.name = this.spell.german;
       this.classes = this.spell.classes;
     } else {
       this.german = this.spell.german + ' (Kopie)';
+      this.english = this.spell.english + ' (copy)';
+      this.name = this.spell.german + ' (Kopie)';
     }
-
-    this.english = this.spell.english;
+    this.image = this.spell.image;
+    this.classes = this.spell.classes;
     this.level = this.spell.level;
     this.cost = this.spell.cost;
     this.canRitual = this.spell.canRitual;
+    this.isRitual = this.spell.isRitual;
     this.duration = this.spell.duration;
     this.timeToCast = this.spell.timeToCast;
     this.needsConcentration = this.spell.needsConcentration;
@@ -168,6 +188,7 @@ export class SpellModalComponent {
     this.needsMaterial = this.spell.needsMaterial;
     this.school = this.spell.school;
     this.description_de = this.spell.description_de;
+    this.description_en = this.spell.description_en;
     this.doesDamage = this.spell.doesDamage;
     this.needsSavingThrow = this.spell.needsSavingThrow;
     this.savingThrowAttribute = this.spell.savingThrowAttribute;
@@ -175,7 +196,7 @@ export class SpellModalComponent {
     this.isRanged = this.spell.isRanged;
     this.range = this.spell.range;
     this.hasAreaOfEffect = this.spell.hasAreaOfEffect;
-    this.radius = this.spell.radius;
+    this.diameter = this.spell.diameter;
     this.areaOfEffectType = this.spell.areaOfEffectType;
     this.needsAttackRoll = this.spell.needsAttackRoll;
     this.attackBonus = this.spell.attackBonus;
@@ -187,8 +208,9 @@ export class SpellModalComponent {
     const spell: Spell = {
       id: this.id,
       isCustom: true,
-      english: this.english,
-      german: this.german,
+      english: this.name,
+      german: this.name,
+      image: this.image,
       classes: this.classes,
       duration: 0, // FIXME: only mocked
       timeToCast: 0, // FIXME: only mocked
@@ -197,18 +219,20 @@ export class SpellModalComponent {
       level: parseInt(this.level.toString()),
       cost: this.cost,
       canRitual: this.canRitual,
+      isRitual: this.isRitual,
       school: this.school,
       description_de: this.description_de,
+      description_en: this.description_de,
       needsConcentration: this.needsConcentration,
       needsVerbal: this.needsVerbal,
       needsSomatic: this.needsSomatic,
       needsMaterial: this.needsMaterial,
-      needsAttackRoll: this.needsAttackRoll,
+      needsAttackRoll: this.needsSavingThrow ? false : this.needsAttackRoll,
       needsSavingThrow: this.needsSavingThrow,
       savingThrowAttribute: this.savingThrowAttribute,
       isRanged: this.isRanged,
       range: this.range,
-      radius: this.radius,
+      diameter: this.diameter,
       hasAreaOfEffect: this.hasAreaOfEffect,
       areaOfEffectType: this.areaOfEffectType,
       doesDamage: this.doesDamage,
@@ -221,18 +245,22 @@ export class SpellModalComponent {
     this.id = 0;
     this.german = '';
     this.english = '';
+    this.name = '';
+    this.image = '';
     this.classes = [];
     this.level = 0;
     this.cost = 'action';
-    this.canRitual = 'false';
+    this.canRitual = false;
+    this.isRitual = false;
     this.duration = 0;
     this.timeToCast = 0;
     this.needsConcentration = false;
     this.needsVerbal = false;
     this.needsSomatic = false;
     this.needsMaterial = false;
-    this.school = '';
+    this.school = 'Evocation';
     this.description_de = '';
+    this.description_en = '';
     this.doesDamage = true;
     this.needsSavingThrow = false;
     this.savingThrowAttribute = '';
@@ -240,8 +268,8 @@ export class SpellModalComponent {
     this.isRanged = false;
     this.range = 5;
     this.hasAreaOfEffect = false;
-    this.radius = 0;
-    this.areaOfEffectType = '';
+    this.diameter = 5;
+    this.areaOfEffectType = 'circle';
     this.needsAttackRoll = false;
     this.attackBonus = '';
     this.doesHeal = false;
@@ -256,5 +284,17 @@ export class SpellModalComponent {
     this.damage.splice(index, 1);
   }
 
+  public setRitual(event: any): void {
+    if (event.target.checked) {
+      this.canRitual = true;
+    }
+  }
+
+  public unsetRitual(event: any): void {
+    if (!event.target.checked) {
+      this.isRitual = false;
+    }
+  }
+
   // #endregion
 }

+ 5 - 3
src/app/shared-components/full-spellcard/full-spellcard.component.html

@@ -66,8 +66,8 @@
           <td>{{ spell.areaOfEffectType }}</td>
         </tr>
         <tr>
-          <td>Radius</td>
-          <td>{{ spell.radius }}</td>
+          <td>Durchmesser</td>
+          <td>{{ spell.diameter }}</td>
         </tr>
         } @if (spell.needsAttackRoll){
         <tr>
@@ -129,8 +129,10 @@
     @if(spell.isCustom){
     <button class="edit-button" (click)="update()">Anpassen</button>
     }
+
     <button class="delete-button" (click)="remove()">Entfernen</button>
+    @if(spell.isCustom){
     <button class="delete-button" (click)="delete()">Löschen</button>
-    }
+    } }
   </div>
 </div>

BIN
src/assets/images/spells/aid.jpg


BIN
src/assets/images/spells/spiritualWeapon.jpg


+ 5 - 3
src/interfaces/spell.ts

@@ -3,26 +3,28 @@ export interface Spell {
   isCustom: boolean;
   german: string;
   english: string;
+  image: string;
   classes: string[];
   level: number;
   cost: string;
   timeToCast: number;
   duration: number;
-  canRitual: 'true' | 'false' | 'only';
+  canRitual: boolean;
+  isRitual: boolean;
   needsConcentration: boolean;
   needsVerbal: boolean;
   needsSomatic: boolean;
   needsMaterial: boolean;
   school: string;
   description_de: string;
-  description_en?: string;
+  description_en: string;
   needsAttackRoll: boolean;
   needsSavingThrow: boolean;
   savingThrowAttribute?: string;
   isRanged: boolean;
   range?: number;
   hasAreaOfEffect: boolean;
-  radius?: number;
+  diameter?: number;
   areaOfEffectType?: string;
 
   doesDamage: boolean;

+ 3 - 0
src/interfaces/weapon.ts

@@ -2,6 +2,9 @@ export interface Weapon {
   name: string;
   damage: Damage[];
   attackBonus: string;
+  useAttributeModifier: boolean;
+  hasAdditionalDamage: boolean;
+  additionalDamage: number;
   range: number[];
   hasReach: boolean;
   throwRange?: number[];

+ 442 - 228
src/services/class/class.service.ts

@@ -16,6 +16,8 @@ export class ClassService {
         return this.barbarian;
       case 'Cleric':
         return this.cleric;
+      case 'Monk':
+        return this.monk;
       default:
         return this.notImplementedYet;
     }
@@ -23,195 +25,412 @@ export class ClassService {
 
   // CLASS DETAILS
 
+  public monk: any = {
+    title: 'Mönch',
+    description: `
+      <p>Monks are united in their ability to magically harness the energy that flows in their bodies. Whether channeled as a striking display of combat prowess or a subtler focus of defensive ability and speed, this energy infuses all that a monk does.</p>
+      <h4>Class Features</h4>
+      <p>As a monk, you gain the following class features.</p>
+      <h5 id="toc1"><span>Hit Points</span></h5>
+      <p><strong>Hit Dice:</strong> 1d8 per monk level<br />
+      <strong>Hit Points at 1st Level:</strong> 8 + your Constitution modifier<br />
+      <strong>Hit Points at Higher Levels:</strong> 1d8 (or 5) + your Constitution modifier per monk level after 1st</p>
+      <h5 id="toc2"><span>Proficiencies</span></h5>
+      <p><strong>Armor:</strong> None<br />
+      <strong>Weapons:</strong> Simple weapons, shortswords<br />
+      <strong>Tools:</strong> Choose one type of artisan's tools or one musical instrument<br />
+      <strong>Saving Throws:</strong> Strength, Dexterity<br />
+      <strong>Skills:</strong> Choose two from Acrobatics, Athletics, History, Insight, Religion, and Stealth</p>
+      <h5 id="toc3"><span>Equipment</span></h5>
+      <p>You start with the following equipment, in addition to the equipment granted by your background:</p>
+      <ul>
+      <li>(a) a shortsword or (b) any simple weapon</li>
+      <li>(a) a dungeoneer's pack or (b) an explorer's pack</li>
+      <li>10 darts</li>
+      </ul>`,
+    features: [
+      {
+        name: 'Unarmored Defense',
+        level: 1,
+        description: `
+          <p>Beginning at 1st level, while you are wearing no armor and not wielding a shield, your AC equals 10 + your Dexterity modifier + your Wisdom modifier.</p>
+          `,
+      },
+      {
+        name: 'Martial Arts',
+        level: 1,
+        description: `
+          <p>At 1st level, your practice of martial arts gives you mastery of combat styles that use unarmed strikes and monk weapons, which are shortswords and any simple melee weapons that don't have the two-handed or heavy property.</p>
+          <p>You gain the following benefits while you are unarmed or wielding only monk weapons and you aren't wearing armor or wielding a shield:</p>
+          <ul>
+          <li>You can use Dexterity instead of Strength for the attack and damage rolls of your unarmed strikes and monk weapons.</li>
+          </ul>
+          <ul>
+          <li>You can roll a d4 in place of the normal damage of your unarmed strike or monk weapon. This die changes as you gain monk levels, as shown in the Martial Arts column of the Monk table.</li>
+          </ul>
+          <ul>
+          <li>When you use the Attack action with an unarmed strike or a monk weapon on your turn, you can make one unarmed strike as a bonus action. For example, if you take the Attack action and attack with a quarterstaff, you can also make an unarmed strike as a bonus action, assuming you haven't already taken a bonus action this turn.</li>
+          </ul>
+          <p>Certain monasteries use specialized forms of the monk weapons. For example, you might use a club that is two lengths of wood connected by a short chain (called a nunchaku) or a sickle with a shorter, straighter blade (called a kama). Whatever name you use for a monk weapon, you can use the game statistics provided for the weapon on the <a href="http://dnd5e.wikidot.com/weapons">Weapons</a> page.</p>
+          `,
+      },
+      {
+        name: 'Ki',
+        level: 2,
+        description: `
+          <p>Starting at 2nd level, your training allows you to harness the mystic energy of ki. Your access to this energy is represented by a number of ki points. Your monk level determines the number of points you have, as shown in the Ki Points column of the Monk table.</p>
+          <p>You can spend these points to fuel various ki features. You start knowing three such features: Flurry of Blows, Patient Defense, and Step of the Wind. You learn more ki features as you gain levels in this class.</p>
+          <p>When you spend a ki point, it is unavailable until you finish a short or long rest, at the end of which you draw all of your expended ki back into yourself. You must spend at least 30 minutes of the rest meditating to regain your ki points.</p>
+          <p>Some of your ki features require your target to make a saving throw to resist the feature's effects. The saving throw DC is calculated as follows:</p>
+          <p><strong>Ki save DC</strong> = 8 + your proficiency bonus + your Wisdom modifier</p>
+          <ul>
+          <li><strong>Flurry of Blows.</strong> Immediately after you take the Attack action on your turn, you can spend 1 ki point to make two unarmed strikes as a bonus action.</li>
+          </ul>
+          <ul>
+          <li><strong>Patient Defense.</strong> You can spend 1 ki point to take the Dodge action as a bonus action on your turn.</li>
+          </ul>
+          <ul>
+          <li><strong>Step of the Wind.</strong> You can spend 1 ki point to take the Disengage or Dash action as a bonus action on your turn, and your jump distance is doubled for the turn.</li>
+          </ul>`,
+      },
+      {
+        name: 'Unarmored Movement',
+        level: 2,
+        description: `
+          <p>Starting at 2nd level, your speed increases by 10 feet while you are not wearing armor or wielding a shield. This bonus increases when you reach certain monk levels, as shown in the Monk table.</p>
+          <p>At 9th level, you gain the ability to move along vertical surfaces and across liquids on your turn without falling during the move.</p>
+          `,
+      },
+      {
+        name: 'Dedicated Weapons (Optional)',
+        level: 2,
+        description: `
+        <p>Also at 2nd level, you train yourself to use a variety of weapons as monk weapons, not just simple melee weapons and shortswords. Whenever you finish a short or long rest, you can touch one weapon, focus your ki on it, and then count that weapon as a monk weapon until you use this feature again.</p>
+          <p>The chosen weapon must meet these criteria:</p>
+          <ul>
+          <li>The weapon must be a simple or martial weapon.</li>
+          </ul>
+          <ul>
+          <li>You must be proficient with it.</li>
+          </ul>
+          <ul>
+          <li>It must lack the heavy and special properties.</li>
+          </ul>`,
+      },
+      {
+        name: 'Monasteric Tradition',
+        level: 3,
+        description: `
+          <p>When you reach 3rd level, you commit yourself to a monastic tradition. Your tradition grants you features at 3rd level and again at 6th, 11th, and 17th level.</p>
+            `,
+      },
+      {
+        name: 'Deflect Missile',
+        level: 3,
+        description: `
+        <p>Starting at 3rd level, you can use your reaction to deflect or catch the missile when you are hit by a ranged weapon attack. When you do so, the damage you take from the attack is reduced by 1d10 + your Dexterity modifier + your monk level.</p>
+        <p>If you reduce the damage to 0, you can catch the missile if it is small enough for you to hold in one hand and you have at least one hand free. If you catch a missile in this way, you can spend 1 ki point to make a ranged attack with a range of 20/60 using the weapon or piece of ammunition you just caught, as part of the same reaction. You make this attack with proficiency, regardless of your weapon proficiencies, and the missile counts as a monk weapon for the attack.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Ki-Fueled Attack (Optional)',
+        level: 3,
+        description: `
+        <p>Also at 3rd level, if you spend 1 ki point or more as part of your action on your turn, you can make one attack with an unarmed strike or a monk weapon as a bonus action before the end of the turn.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 4,
+        description: `
+        <p>When you reach 4th level, and again at 8th, 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
+      {
+        name: 'Slow Fall',
+        level: 4,
+        description: `
+        <p>Beginning at 4th level, you can use your reaction when you fall to reduce any falling damage you take by an amount equal to five times your monk level.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Quickened Healing',
+        level: 4,
+        description: `
+        <p>Also at 4th level, as an action, you can spend 2 ki points and roll a Martial Arts die. You regain a number of hit points equal to the number rolled plus your proficiency bonus.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Extra Attack',
+        level: 5,
+        description: `
+        <p>Beginning at 5th level, you can attack twice, instead of once, whenever you take the Attack action on your turn.</p>
+        `,
+      },
+      {
+        name: 'Stunning Strike',
+        level: 5,
+        description: `
+        <p>Starting at 5th level, you can interfere with the flow of ki in an opponent's body. When you hit another creature with a melee weapon attack, you can spend 1 ki point to attempt a stunning strike. The target must succeed on a Constitution saving throw or be stunned until the end of your next turn.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Focused Aim (Optional)',
+        level: 5,
+        description: `
+        <p>Also at 5th level, when you miss with an attack roll, you can spend 1 to 3 ki points to increase your attack roll by 2 for each of these ki points you spend, potentially turning the miss into a hit.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Ki-Empowered Strikes',
+        level: 6,
+        description: `
+        <p>Starting at 6th level, your unarmed strikes count as magical for the purpose of overcoming resistance and immunity to nonmagical attacks and damage.</p>
+        `,
+      },
+      {
+        name: 'Evasion',
+        level: 7,
+        description: `
+        <p>At 7th level, your instinctive agility lets you dodge out of the way of certain area effects, such as a blue dragon's lightning breath or a fireball spell. When you are subjected to an effect that allows you to make a Dexterity saving throw to take only half damage, you instead take no damage if you succeed on the saving throw, and only half damage if you fail.</p>
+        `,
+      },
+      {
+        name: 'Stillness of Mind',
+        level: 7,
+        description: `
+        <p>Starting at 7th level, you can use your action to end one effect on yourself that is causing you to be charmed or frightened.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Purity of Blood',
+        level: 10,
+        description: `
+        <p>At 10th level, your mastery of the ki flowing through you makes you immune to disease and poison.</p>
+        `,
+      },
+      {
+        name: 'Tongue of the Sun and Moon',
+        level: 13,
+        description: `
+        <p>Starting at 13th level, you learn to touch the ki of other minds so that you understand all spoken languages. Moreover, any creature that can understand a language can understand what you say.</p>
+        `,
+      },
+      {
+        name: 'Diamond Soul',
+        level: 14,
+        description: `
+        <p>Beginning at 14th level, your mastery of ki grants you proficiency in all saving throws.</p>
+        `,
+      },
+      {
+        name: 'Timeless Body',
+        level: 15,
+        description: `
+        <p>At 15th level, your ki sustains you so that you suffer none of the frailty of old age, and you can't be aged magically. You can still die of old age, however. In addition, you no longer need food or water.</p>
+        `,
+      },
+      {
+        name: 'Empty Body',
+        level: 18,
+        description: `
+        <p>Beginning at 18th level, you can use your action to spend 4 ki points to become invisible for 1 minute. During that time, you also have resistance to all damage but force damage.</p>
+        <p>Additionally, you can spend 8 ki points to cast the <em><a href="/spell:astral-projection">astral projection</a></em> spell, without needing material components. When you do so, you can't take any other creatures with you.</p>
+        `,
+        ability: '',
+      },
+      {
+        name: 'Perfect Self',
+        level: 20,
+        description: `
+        <p>At 20th level, when you roll for initiative and have no ki points remaining, you regain 4 ki points.</p>
+        `,
+      },
+    ],
+  };
+
   public fighter: any = {
     title: 'Kämpfer',
     description: `
-    Fighters share an unparalleled mastery with weapons and armor, and a thorough knowledge of the skills of combat. They are well acquainted with death, both meting it out and staring it defiantly in the face.
-
-
-    ### Class Features
-
-    As a fighter, you gain the following class features.
-
-    #### Hit Points
-
-    **Hit Dice:** 1d10 per fighter level
-    
-    **Hit Points at 1st Level:** 10 + your Constitution modifier
-    
-    **Hit Points at Higher Levels:** 1d10 (or 6) + your Constitution modifier per fighter level after 1st
-
-    #### Proficiencies
-    **Armor:** All armor, shields
-
-    **Weapons:** Simple weapons, martial weapons
-
-    **Tools:** None
-
-    **Saving Throws:** Strength, Constitution
-
-    **Skills:** Choose two skills from Acrobatics, Animal Handling, Athletics, History, Insight, Intimidation, Perception, and Survival
-
-    #### Equipment
-    - (a) chain mail or (b) leather, longbow, and 20 arrows
-    - (a) a martial weapon and a shield or (b) two martial weapons
-    - (a) a light crossbow and 20 bolts or (b) two handaxes
-    - (a) a dungeoneer's pack or (b) an explorer's pack
+    <p>Fighters share an unparalleled mastery with weapons and armor, and a thorough knowledge of the skills of combat. They are well acquainted with death, both meting it out and staring it defiantly in the face.</p>
+    <h4>Class Features</h4>
+    <p>As a fighter, you gain the following class features.</p>
+
+    <h4> Hit Points </h4>
+    <b>Hit Dice:</b> 1d10 per fighter level <br>
+    <b>Hit Points at 1st Level:</b> 10 + your Constitution modifier  <br>
+    <b>Hit Points at Higher Levels:</b> 1d10 (or 6) + your Constitution modifier per fighter level after 1st  <br>
+    <h4> Proficiencies</h4>
+    <b>Armor:</b> All armor, shields  <br>
+    <b>Weapons:</b> Simple weapons, martial weapons  <br>
+    <b>Tools:</b> None  <br>
+    <b>Saving Throws:</b> Strength, Constitution <br>
+    <b>Skills:</b> Choose two skills from Acrobatics, Animal Handling, Athletics, History, Insight, Intimidation, Perception, and Survival <br>
+    <h4> Equipment</h4>
+    <ul>
+    <li>(a) chain mail or (b) leather, longbow, and 20 arrows</li>
+    <li>(a) a martial weapon and a shield or (b) two martial weapons</li>
+    <li>(a) a light crossbow and 20 bolts or (b) two handaxes</li>
+    <li>(a) a dungeoneer's pack or (b) an explorer's pack</li>
     `,
     features: [
       {
         name: 'Fighting Style',
         level: 1,
         description: `
-
-      You adopt a particular style of fighting as your specialty. Choose one of the following options. You can't take a Fighting Style option more than once, even if you later get to choose again.
-
-      - Archery (PHB). You gain a +2 bonus to attack rolls you make with ranged weapons.
-      - Blind Fighting (TCE). You have blindsight with a range of 10 feet. Within that range, you can effectively see anything that isn't behind total cover, even if you're blinded or in darkness. Moreover, you can see an invisible creature within that range, unless the creature successfully hides from you.
-      - Defense (PHB). While you are wearing armor, you gain a +1 bonus to AC.
-      - Dueling (PHB). When you are wielding a melee weapon in one hand and no other weapons, you gain a +2 bonus to damage rolls with that weapon.
-      - Great Weapon Fighting (PHB). When you roll a 1 or 2 on a damage die for an attack you make with a melee weapon that you are wielding with two hands, you can reroll the die and must use the new roll, even if the new roll is a 1 or a 2. The weapon must have the two-handed or versatile property for you to gain this benefit.
-      - Interception (TCE). When a creature you can see hits a target, other than you, within 5 feet of you with an attack, you can use your reaction to reduce the damage the target takes by 1d10 + your proficiency bonus (to a minimum of 0 damage). You must be wielding a shield or a simple or martial weapon to use this reaction.
-      - Protection (PHB). When a creature you can see attacks a target other than you that is within 5 feet of you, you can use your reaction to impose disadvantage on the attack roll. You must be wielding a shield.
-      - Superior Technique (TCE). You learn one maneuver of your choice from among those available to the Battle Master archetype. If a maneuver you use requires your target to make a saving throw to resist the maneuver's effects, the saving throw DC equals 8 + your proficiency bonus + your Strength or Dexterity modifier (your choice.)
-      - You gain one superiority die, which is a d6 (this die is added to any superiority dice you have from another source). This die is used to fuel your maneuvers. A superiority die is expended when you use it. You regain your expended superiority dice when you finish a short or long rest.
-      - Thrown Weapon Fighting (TCE). You can draw a weapon that has the thrown property as part of the attack you make with the weapon.
-      - In addition, when you hit with a ranged attack using a thrown weapon, you gain a +2 bonus to the damage roll.
-      - Two-Weapon Fighting (PHB). When you engage in two-weapon fighting, you can add your ability modifier to the damage of the second attack.
-      - Unarmed Fighting (TCE). Your unarmed strikes can deal bludgeoning damage equal to 1d6 + your Strength modifier on a hit. If you aren't wielding any weapons or a shield when you make the attack roll, the d6 becomes a d8.
-      - At the start of each of your turns, you can deal 1d4 bludgeoning damage to one creature grappled by you.
-      - Close Quarters Shooter (UA). When making a ranged attack while you are within 5 feet of a hostile creature, you do not have disadvantage on the attack roll. Your ranged attacks ignore half cover and three-quarters cover against targets within 30 feet of you. You have a +1 bonus to attack rolls on ranged attacks.
-      - Mariner (UA). As long as you are not wearing heavy armor or using a shield, you have a swimming speed and a climbing speed equal to your normal speed, and you gain a +1 bonus to armor class.
-      - Tunnel Fighter (UA). As a bonus action, you can enter a defensive stance that lasts until the start of your next turn. While in your defensive stance, you can make opportunity attacks without using your reaction, and you can use your reaction to make a melee attack against a creature that moves more than 5 feet while within your reach.
-      
+      <p>You adopt a particular style of fighting as your specialty. Choose one of the following options. You can't take a Fighting Style option more than once, even if you later get to choose again.<p>
+      <ul>
+        <li> Archery (PHB). You gain a +2 bonus to attack rolls you make with ranged weapons.</li>
+        <li> Blind Fighting (TCE). You have blindsight with a range of 10 feet. Within that range, you can effectively see anything that isn't behind total cover, even if you're blinded or in darkness. Moreover, you can see an invisible creature within that range, unless the creature successfully hides from you.</li>
+        <li> Defense (PHB). While you are wearing armor, you gain a +1 bonus to AC.</li>
+        <li> Dueling (PHB). When you are wielding a melee weapon in one hand and no other weapons, you gain a +2 bonus to damage rolls with that weapon.</li>
+        <li> Great Weapon Fighting (PHB). When you roll a 1 or 2 on a damage die for an attack you make with a melee weapon that you are wielding with two hands, you can reroll the die and must use the new roll, even if the new roll is a 1 or a 2. The weapon must have the two-handed or versatile property for you to gain this benefit.</li>
+        <li> Interception (TCE). When a creature you can see hits a target, other than you, within 5 feet of you with an attack, you can use your reaction to reduce the damage the target takes by 1d10 + your proficiency bonus (to a minimum of 0 damage). You must be wielding a shield or a simple or martial weapon to use this reaction.</li>
+        <li> Protection (PHB). When a creature you can see attacks a target other than you that is within 5 feet of you, you can use your reaction to impose disadvantage on the attack roll. You must be wielding a shield.</li>
+        <li> Superior Technique (TCE). You learn one maneuver of your choice from among those available to the Battle Master archetype. If a maneuver you use requires your target to make a saving throw to resist the maneuver's effects, the saving throw DC equals 8 + your proficiency bonus + your Strength or Dexterity modifier (your choice.)</li>
+        <li> You gain one superiority die, which is a d6 (this die is added to any superiority dice you have from another source). This die is used to fuel your maneuvers. A superiority die is expended when you use it. You regain your expended superiority dice when you finish a short or long rest.</li>
+        <li> Thrown Weapon Fighting (TCE). You can draw a weapon that has the thrown property as part of the attack you make with the weapon.</li>
+        <li> In addition, when you hit with a ranged attack using a thrown weapon, you gain a +2 bonus to the damage roll.</li>
+        <li> Two-Weapon Fighting (PHB). When you engage in two-weapon fighting, you can add your ability modifier to the damage of the second attack.</li>
+        <li> Unarmed Fighting (TCE). Your unarmed strikes can deal bludgeoning damage equal to 1d6 + your Strength modifier on a hit. If you aren't wielding any weapons or a shield when you make the attack roll, the d6 becomes a d8.</li>
+        <li> At the start of each of your turns, you can deal 1d4 bludgeoning damage to one creature grappled by you.</li>
+        <li> Close Quarters Shooter (UA). When making a ranged attack while you are within 5 feet of a hostile creature, you do not have disadvantage on the attack roll. Your ranged attacks ignore half cover and three-quarters cover against targets within 30 feet of you. You have a +1 bonus to attack rolls on ranged attacks.</li>
+        <li> Mariner (UA). As long as you are not wearing heavy armor or using a shield, you have a swimming speed and a climbing speed equal to your normal speed, and you gain a +1 bonus to armor class.</li>
+        <li> Tunnel Fighter (UA). As a bonus action, you can enter a defensive stance that lasts until the start of your next turn. While in your defensive stance, you can make opportunity attacks without using your reaction, and you can use your reaction to make a melee attack against a creature that moves more than 5 feet while within your reach.</li>
+      </ul>
       `,
       },
       {
         name: 'Second Wind',
         level: 1,
         description: `
-          You have a limited well of stamina that you can draw on to protect yourself from harm. On your turn, you can use a bonus action to regain hit points equal to 1d10 + your fighter level.
-
-          Once you use this feature, you must finish a short or long rest before you can use it again.
-      
+          <p>You have a limited well of stamina that you can draw on to protect yourself from harm. On your turn, you can use a bonus action to regain hit points equal to 1d10 + your fighter level.</p>
+          <p>Once you use this feature, you must finish a short or long rest before you can use it again.</p>
         `,
+        ability: '',
       },
       {
         name: 'Action Surge',
         level: 2,
         description: `
-          Starting at 2nd level, you can push yourself beyond your normal limits for a moment. On your turn, you can take one additional action.
-
-          Once you use this feature, you must finish a short or long rest before you can use it again. Starting at 17th level, you can use it twice before a rest, but only once on the same turn.
-      
+          <p> Starting at 2nd level, you can push yourself beyond your normal limits for a moment. On your turn, you can take one additional action.</p>
+          <p>Once you use this feature, you must finish a short or long rest before you can use it again. Starting at 17th level, you can use it twice before a rest, but only once on the same turn.</p>
         `,
+        ability: '',
       },
       {
         name: 'Martial Archetype',
         level: 3,
         description: `
-          At 3rd level, you choose an archetype that you strive to emulate in your combat styles and techniques. The archetype you choose grants you features at 3rd level and again at 7th, 10th, 15th, and 18th level.    
+          <p>At 3rd level, you choose an archetype that you strive to emulate in your combat styles and techniques. The archetype you choose grants you features at 3rd level and again at 7th, 10th, 15th, and 18th level.</p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 4,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Extra Attack',
         level: 5,
         description: `
-          Beginning at 5th level, you can attack twice, instead of once, whenever you take the Attack action on your turn.
-
-          The number of attacks increases to three when you reach 11th level in this class and to four when you reach 20th level in this class.    
+          <p>Beginning at 5th level, you can attack twice, instead of once, whenever you take the Attack action on your turn.<p>
+          <p>The number of attacks increases to three when you reach 11th level in this class and to four when you reach 20th level in this class.</p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 6,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 6th level, and again at 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 8,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 8th level, and again at 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Indomitable',
         level: 9,
         description: `
-          Beginning at 9th level, you can reroll a saving throw that you fail. If you do so, you must use the new roll, and you can't use this feature again until you finish a long rest.  
+          <p>Beginning at 9th level, you can reroll a saving throw that you fail. If you do so, you must use the new roll, and you can't use this feature again until you finish a long rest.</p>
         `,
       },
       {
         name: 'Extra Attack (x3)',
         level: 11,
         description: `
-          You can now attack thrice whenever you take the Attack action on your turn.   
+          <p>You can now attack three times whenever you take the Attack action on your turn.</p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 12,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 12th level, and again at 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Indomitable (x2)',
         level: 13,
         description: `
-          You can reroll a saving throw that you fail. If you do so, you must use the new roll, and you can't use this feature again until you finish a long rest. You can now use this feature twice between long rests.  
+          <p>You can reroll a saving throw that you fail. If you do so, you must use the new roll, and you can't use this feature again until you finish a long rest. You can now use this feature twice between long rests.</p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 14,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 14th level, and again at 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 16,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 16th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Indomitable (x3)',
         level: 17,
         description: `
-          You can reroll a saving throw that you fail. If you do so, you must use the new roll, and you can't use this feature again until you finish a long rest. You can now use this feature thrice between long rests.  
+          <p>You can reroll a saving throw that you fail. If you do so, you must use the new roll, and you can't use this feature again until you finish a long rest. You can now use this feature thrice between long rests.</p>
         `,
       },
       {
         name: 'Action Surge (x2)',
         level: 17,
         description: `
-          Starting at 17th level, you can use it twice before a rest, but only once on the same turn.
-      
+          <p>Starting at 17th level, you can use it twice before a rest, but only once on the same turn.</p>
+
         `,
+        ability: '',
       },
       {
         name: 'Ability Score Improvement',
         level: 19,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+         <p>When you reach 19th level you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
       },
       {
         name: 'Extra Attack (x4)',
         level: 20,
         description: `
-          You can now attack four times whenever you take the Attack action on your turn. 
+          <p>You can now attack four times whenever you take the Attack action on your turn.</p>
         `,
       },
     ],
@@ -220,149 +439,147 @@ export class ClassService {
   public barbarian: any = {
     title: 'Barbar',
     description: `
-    Barbarians are savage warriors who deal with their opponents through a combination of sheer brute force and terrifying rage. Their strength and ferocity make them well suited for melee combat. Barbarians are also able to wreak havoc on their enemies using unorthodox methods, such as throwing improvised weapons or even their own bodies.
-
-    ### Class Features
-
-    As a barbarian, you gain the following class features.
-
-    #### Hit Points
-
-    **Hit Dice:** 1d12 per barbarian level
-    
-    **Hit Points at 1st Level:** 12 + your Constitution modifier
-    
-    **Hit Points at Higher Levels:** 1d12 (or 7) + your Constitution modifier per barbarian level after 1st
-
-    #### Proficiencies
-    **Armor:** Light armor, medium armor, shields
-
-    **Weapons:** Simple weapons, martial weapons
-
-    **Tools:** None
-
-    **Saving Throws:** Strength, Constitution
-
-    **Skills:** Choose two skills from Animal Handling, Athletics, Intimidation, Nature, Perception, and Survival
-
-    #### Equipment
-    - (a) a greataxe or (b) any martial melee weapon
-    - (a) two handaxes or (b) any simple weapon
-    - An explorer's pack and four javelins
+    <p>Barbarians are savage warriors who deal with their opponents through a combination of sheer brute force and terrifying rage. Their strength and ferocity make them well suited for melee combat. Barbarians are also able to wreak havoc on their enemies using unorthodox methods, such as throwing improvised weapons or even their own bodies.</p>
+    <h4>Class Features</h4>
+    <p>As a barbarian, you gain the following class features.</p>
+    <h4> Hit Points</h4>
+    <b>Hit Dice:</b> 1d12 per barbarian level <br>
+    <b>Hit Points at 1st Level:</b> 12 + your Constitution modifier <br> 
+    <b>Hit Points at Higher Levels:</b> 1d12 (or 7) + your Constitution modifier per barbarian level after 1st <br>
+    <h4>Proficiencies</h4>
+    <b>Armor:</b> Light armor, medium armor, shields <br>
+    <b>Weapons:</b> Simple weapons, martial weapons <br>
+    <b>Tools:</b> None <br>
+    <b>Saving Throws:</b> Strength, Constitution <br>
+    <b>Skills:</b> Choose two skills from Animal Handling, Athletics, Intimidation, Nature, Perception, and Survival
+
+    <h4>Equipment</h4>
+    <ul>
+    <li> (a) a greataxe or (b) any martial melee weapon </li>
+    <li> (a) two handaxes or (b) any simple weapon </li>
+    <li> An explorer's pack and four javelins </li>
+    </ul>
     `,
     features: [
       {
         name: 'Rage',
         level: 1,
         description: `
-          In battle, you fight with primal ferocity. On your turn, you can enter a rage as a bonus action.
-
-          While raging, you gain the following benefits if you aren't wearing heavy armor:
-
-          - You have advantage on Strength checks and Strength saving throws.
-          - When you make a melee weapon attack using Strength, you gain a bonus to the damage roll that increases as you gain levels as a barbarian, as shown in the Rage Damage column of the Barbarian table.
-          - You have resistance to bludgeoning, piercing, and slashing damage.
-          - If you are able to cast spells, you can't cast them or concentrate on them while raging.
-          - Your rage lasts for 1 minute. It ends early if you are knocked unconscious or if your turn ends and you haven't attacked a hostile creature since your last turn or taken damage since then. You can also end your rage on your turn as a bonus action.
-          - Once you have raged the number of times shown for your barbarian level in the Rages column of the Barbarian table, you must finish a long rest before you can rage again.
-        `,
+        <p>In battle, you fight with primal ferocity. On your turn, you can enter a rage as a bonus action.</p>
+        <p>While raging, you gain the following benefits if you aren't wearing heavy armor:</p>
+        <ul>
+          <li> You have advantage on Strength checks and Strength saving throws. </li>
+          <li> When you make a melee weapon attack using Strength, you gain a bonus to the damage roll that increases as you gain levels as a barbarian, as shown in the Rage Damage column of the Barbarian table. </li>  
+          <li> You have resistance to bludgeoning, piercing, and slashing damage. </li>
+          <li> If you are able to cast spells, you can't cast them or concentrate on them while raging. </li>
+          <li> Your rage lasts for 1 minute. It ends early if you are knocked unconscious or if your turn ends and you haven't attacked a hostile creature since your last turn or taken damage since then. You can also end your rage on your turn as a bonus action. </li>
+          <li> Once you have raged the number of times shown for your barbarian level in the Rages column of the Barbarian table, you must finish a long rest before you can rage again. </li>
+        <ul>
+          `,
+        ability: '',
       },
       {
         name: 'Unarmored Defense',
         level: 1,
         description: `
-          While you are not wearing any armor, your Armor Class equals 10 + your Dexterity modifier + your Constitution modifier. You can use a shield and still gain this benefit.
+          <p>While you are not wearing any armor, your Armor Class equals 10 + your Dexterity modifier + your Constitution modifier. You can use a shield and still gain this benefit. </p>
         `,
       },
       {
         name: 'Reckless Attack',
         level: 2,
         description: `
-          Starting at 2nd level, you can throw aside all concern for defense to attack with fierce desperation. When you make your first attack on your turn, you can decide to attack recklessly. Doing so gives you advantage on melee weapon attack rolls using Strength during this turn, but attack rolls against you have advantage until your next turn.
+          <p>Starting at 2nd level, you can throw aside all concern for defense to attack with fierce desperation. When you make your first attack on your turn, you can decide to attack recklessly. Doing so gives you advantage on melee weapon attack rolls using Strength during this turn, but attack rolls against you have advantage until your next turn. </p>
         `,
+        ability: '',
       },
       {
         name: 'Danger Sense',
         level: 2,
         description: `
-          At 2nd level, you gain an uncanny sense of when things nearby aren't as they should be, giving you an edge when you dodge away from danger.
-
-          You have advantage on Dexterity saving throws against effects that you can see, such as traps and spells. To gain this benefit, you can't be blinded, deafened, or incapacitated.
+          <p>At 2nd level, you gain an uncanny sense of when things nearby aren't as they should be, giving you an edge when you dodge away from danger. </p>
+          <p>You have advantage on Dexterity saving throws against effects that you can see, such as traps and spells. To gain this benefit, you can't be blinded, deafened, or incapacitated. <p>
         `,
       },
+      {
+        name: 'Primal Path',
+        level: 3,
+        description: `
+          <p>At 3rd level, you choose a path that shapes the nature of your rage. Choose the Path of the Berserker or the Path of the Totem Warrior, both detailed at the end of the class description. Your choice grants you features at 3rd level and again at 6th, 10th, and 14th levels. </p>
+          `,
+      },
       {
         name: 'Ability Score Improvement',
         level: 4,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+         <p> When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  </p>
         `,
       },
       {
         name: 'Extra Attack',
         level: 5,
         description: `
-          Beginning at 5th level, you can attack twice, instead of once, whenever you take the Attack action on your turn.
-
-          The number of attacks increases to three when you reach 11th level in this class and to four when you reach 20th level in this class.    
+          <p>Beginning at 5th level, you can attack twice, instead of once, whenever you take the Attack action on your turn.<p>
+          <p>The number of attacks increases to three when you reach 11th level in this class and to four when you reach 20th level in this class.  </p>  
         `,
       },
       {
         name: 'Fast Movement',
         level: 5,
         description: `
-          Starting at 5th level, your speed increases by 10 feet while you aren't wearing heavy armor.
+          <p>Starting at 5th level, your speed increases by 10 feet while you aren't wearing heavy armor. </p>
         `,
       },
       {
         name: 'Feral Instinct',
         level: 7,
         description: `
-          By 7th level, your instincts are so honed that you have advantage on initiative rolls.
-
-          Additionally, if you are surprised at the beginning of combat and aren't incapacitated, you can act normally on your first turn, but only if you enter your rage before doing anything else on that turn.
+          <p>By 7th level, your instincts are so honed that you have advantage on initiative rolls.</p>
+         <p> Additionally, if you are surprised at the beginning of combat and aren't incapacitated, you can act normally on your first turn, but only if you enter your rage before doing anything else on that turn. </p>
         `,
       },
       {
         name: 'Brutal Critical',
         level: 9,
         description: `
-          Beginning at 9th level, you can roll one additional weapon damage die when determining the extra damage for a critical hit with a melee attack.
-
-          This increases to two additional dice at 13th level and three additional dice at 17th level.
+          <p>Beginning at 9th level, you can roll one additional weapon damage die when determining the extra damage for a critical hit with a melee attack. </p>
+          <p>This increases to two additional dice at 13th level and three additional dice at 17th level. </p>
         `,
       },
       {
         name: 'Relentless Rage',
         level: 11,
         description: `
-          Starting at 11th level, your rage can keep you fighting despite grievous wounds. If you drop to 0 hit points while you're raging and don't die outright, you can make a DC 10 Constitution saving throw. If you succeed, you drop to 1 hit point instead.
-
-          Each time you use this feature after the first, the DC increases by 5. When you finish a short or long rest, the DC resets to 10.
+          <p>Starting at 11th level, your rage can keep you fighting despite grievous wounds. If you drop to 0 hit points while you're raging and don't die outright, you can make a DC 10 Constitution saving throw. If you succeed, you drop to 1 hit point instead. </p>
+          <p>Each time you use this feature after the first, the DC increases by 5. When you finish a short or long rest, the DC resets to 10. </p>
         `,
       },
       {
         name: 'Ability Score Improvement',
         level: 12,
         description: `
-          When you reach 4th level, and again at 6th, 8th, 12th, 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 12th level, and again at 14th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature. </p>
         `,
       },
       {
         name: 'Persistent Rage',
         level: 15,
         description: `
-          Beginning at 15th level, your rage is so fierce that it ends early only if you fall unconscious or if you choose to end it.
+          <p>Beginning at 15th level, your rage is so fierce that it ends early only if you fall unconscious or if you choose to end it. <p>
         `,
       },
       {
         name: 'Indomitable Might',
         level: 18,
         description: `
-          Beginning at 18th level, if your total for a Strength check is less than your Strength score, you can use that score in place of the total.
-
-          ### Primal Champion
-
-          At 20th level, you embody the power of the wilds. Your Strength and Constitution scores increase by 4. Your maximum for those scores is now 24.
+          <p>Beginning at 18th level, if your total for a Strength check is less than your Strength score, you can use that score in place of the total.</p>
+        `,
+      },
+      {
+        name: 'Primal Champion',
+        level: 20,
+        description: `
+          <p>At 20th level, you embody the power of the wilds. Your Strength and Constitution scores increase by 4. Your maximum for those scores is now 24. </p>
         `,
       },
     ],
@@ -371,143 +588,140 @@ export class ClassService {
   public cleric: any = {
     title: 'Cleric',
     description: `
-    Clerics are intermediaries between the mortal world and the distant planes of the gods. As varied as the gods they serve, clerics strive to embody the handiwork of their deities. No ordinary priest, a cleric is imbued with divine magic.
-
-    ### Class Features
-
-    As a cleric, you gain the following class features.
-
-    #### Hit Points
-
-    **Hit Dice:** 1d8 per cleric level
-    
-    **Hit Points at 1st Level:** 8 + your Constitution modifier
-    
-    **Hit Points at Higher Levels:** 1d8 (or 5) + your Constitution modifier per cleric level after 1st
-
-    #### Proficiencies
-    **Armor:** Light armor, medium armor, shields
-
-    **Weapons:** Simple weapons
-
-    **Tools:** None
-
-    **Saving Throws:** Wisdom, Charisma
-
-    **Skills:** Choose two from History, Insight, Medicine, Persuasion, and Religion
-
-    #### Equipment
-    - (a) a mace or (b) a warhammer (if proficient)
-    - (a) scale mail, (b) leather armor, or (c) chain mail (if proficient)
-    - (a) a light crossbow and 20 bolts or (b) any simple weapon
-    - (a) a priest's pack or (b) an explorer's pack
-    - A shield and a holy symbol
-
-    ### Spellcasting
-
-    As a conduit for divine power, you can cast cleric spells.
-
-    #### Cantrips
-
-    At 1st level, you know three cantrips of your choice from the cleric spell list. You learn additional cleric cantrips of your choice at higher levels, as shown in the Cantrips Known column of the Cleric table.
-
-    #### Spell Slots
-
-    The Cleric table shows how many spell slots you have to cast your cleric spells of 1st level and higher. To cast one of these spells, you must expend a slot of the spell's level or higher. You regain all expended spell slots when you finish a long rest.
-
-    You prepare the list of cleric spells that are available for you to cast, choosing from the cleric spell list. When you do so, choose a number of cleric spells equal to your Wisdom modifier + your cleric level (minimum of one spell). The spells must be of a level for which you have spell slots.
-
-    For example, if you are a 3rd-level cleric, you have four 1st-level and two 2nd-level spell slots. With a Wisdom of 16, your list of prepared spells can include six spells of 1st or 2nd level, in any combination. If you prepare the 1st-level spell Cure Wounds, you can cast it using a 1st-level or 2nd-level slot. Casting the spell doesn't remove it from your list of prepared spells.
-
-    You can change your list of prepared spells when you finish a long rest. Preparing a new list of cleric spells requires time spent in prayer and meditation: at least 1 minute per spell level for each spell on your list.
-
-    #### Spellcasting Ability
-
-    Wisdom is your spellcasting ability for your cleric spells. The power of your spells comes from your devotion to your deity. You use your Wisdom whenever a cleric spell refers to your spellcasting ability. In addition, you use your Wisdom modifier when setting the saving throw DC for a cleric spell you cast and when making an attack roll with one.
-
-    **Spell save DC:** 8 + your proficiency bonus + your Wisdom modifier
-
-    **Spell attack modifier:** your proficiency bonus + your Wisdom modifier
-
+    <p>Clerics are intermediaries between the mortal world and the distant planes of the gods. As varied as the gods they serve, clerics strive to embody the handiwork of their deities. No ordinary priest, a cleric is imbued with divine magic.</p>
+    <h4>Class Features</h4>
+    <p>As a cleric, you gain the following class features.</p>
+    <h4> Hit Points</h4>
+    <b>Hit Dice:</b> 1d8 per cleric level <br>
+    <b>Hit Points at 1st Level:</b> 8 + your Constitution modifier<br>
+    <b>Hit Points at Higher Levels:</b> 1d8 (or 5) + your Constitution modifier per cleric level after 1st<br>
+    <h4> Proficiencies</h4>
+    <b>Armor:</b> Light armor, medium armor, shields<br>
+    <b>Weapons:</b> Simple weapons<br>
+    <b>Tools:</b> None<br>
+    <b>Saving Throws:</b> Wisdom, Charisma<br>
+    <b>Skills:</b> Choose two from History, Insight, Medicine, Persuasion, and Religion<br>
+    <h4> Equipment</h4>
+    <ul>
+    <li> (a) a mace or (b) a warhammer (if proficient)</li>
+    <li> (a) scale mail, (b) leather armor, or (c) chain mail (if proficient)</li>
+    <li> (a) a light crossbow and 20 bolts or (b) any simple weapon</li>
+    <li> (a) a priest's pack or (b) an explorer's pack</li>
+    <li> A shield and a holy symbol</li>
+    <ul>
     `,
     features: [
+      {
+        name: 'Spellcasting',
+        level: 1,
+        description: `
+        <b>Cantrips</b>
+        <p>At 1st level, you know three cantrips of your choice from the cleric spell list. You learn additional cleric cantrips of your choice at higher levels, as shown in the Cantrips Known column of the Cleric table.</p>
+        <b>Spell Slots</b>
+        <p>The Cleric table shows how many spell slots you have to cast your cleric spells of 1st level and higher. To cast one of these spells, you must expend a slot of the spell's level or higher. You regain all expended spell slots when you finish a long rest.</p>
+        <p>You prepare the list of cleric spells that are available for you to cast, choosing from the cleric spell list. When you do so, choose a number of cleric spells equal to your Wisdom modifier + your cleric level (minimum of one spell). The spells must be of a level for which you have spell slots.</p>
+        <p>For example, if you are a 3rd-level cleric, you have four 1st-level and two 2nd-level spell slots. With a Wisdom of 16, your list of prepared spells can include six spells of 1st or 2nd level, in any combination. If you prepare the 1st-level spell Cure Wounds, you can cast it using a 1st-level or 2nd-level slot. Casting the spell doesn't remove it from your list of prepared spells.</p>
+        <p>You can change your list of prepared spells when you finish a long rest. Preparing a new list of cleric spells requires time spent in prayer and meditation: at least 1 minute per spell level for each spell on your list.</p>
+        <h4>Spellcasting Ability</h4>
+        <p>Wisdom is your spellcasting ability for your cleric spells. The power of your spells comes from your devotion to your deity. You use your Wisdom whenever a cleric spell refers to your spellcasting ability. In addition, you use your Wisdom modifier when setting the saving throw DC for a cleric spell you cast and when making an attack roll with one.</p>
+        <b>Spell save DC:</b> 8 + your proficiency bonus + your Wisdom modifier<br>
+        <b>Spell attack modifier:</b> your proficiency bonus + your Wisdom modifier<br>
+        `,
+      },
       {
         name: 'Divine Domain',
         level: 1,
         description: `
-          At 1st level, you choose a domain shaped by your choice of Deity and the gifts they grant you. Your choice grants you domain spells and other features when you choose it at 1st level. It also grants you additional ways to use Channel Divinity when you gain that feature at 2nd level, and additional benefits at 6th, 8th, and 17th levels.
+          <p>At 1st level, you choose a domain shaped by your choice of Deity and the gifts they grant you. Your choice grants you domain spells and other features when you choose it at 1st level. It also grants you additional ways to use Channel Divinity when you gain that feature at 2nd level, and additional benefits at 6th, 8th, and 17th levels.</p>
           `,
       },
       {
         name: 'Channel Divinity',
         level: 2,
         description: `
-          At 2nd level, you gain the ability to channel divine energy directly from your deity, using that energy to fuel magical effects. You start with two such effects: Turn Undead and an effect determined by your domain. Some domains grant you additional effects as you advance in levels, as noted in the domain description.
-
-          When you use your Channel Divinity, you choose which effect to create. You must then finish a short or long rest to use your Channel Divinity again.
-
-          Some Channel Divinity effects require saving throws. When you use such an effect from this class, the DC equals your cleric spell save DC.
-
-          Beginning at 6th level, you can use your Channel Divinity twice between rests, and beginning at 18th level, you can use it three times between rests. When you finish a short or long rest, you regain your expended uses.
+          <p>At 2nd level, you gain the ability to channel divine energy directly from your deity, using that energy to fuel magical effects. You start with two such effects: Turn Undead and an effect determined by your domain. Some domains grant you additional effects as you advance in levels, as noted in the domain description.</p>
+          <p>When you use your Channel Divinity, you choose which effect to create. You must then finish a short or long rest to use your Channel Divinity again.</p>
+          <p>Some Channel Divinity effects require saving throws. When you use such an effect from this class, the DC equals your cleric spell save DC.</p>
+          <p>Beginning at 6th level, you can use your Channel Divinity twice between rests, and beginning at 18th level, you can use it three times between rests. When you finish a short or long rest, you regain your expended uses.</p>
           `,
       },
       {
         name: 'Channel Divinity Turn Undead',
         level: 2,
         description: `
-          As an action, you present your holy symbol and speak a prayer censuring the undead. Each undead that can see or hear you within 30 feet of you must make a Wisdom saving throw. If the creature fails its saving throw, it is turned for 1 minute or until it takes any damage.
-
-          A turned creature must spend its turns trying to move as far away from you as it can, and it can't willingly move to a space within 30 feet of you. It also can't take reactions. For its action, it can use only the Dash action or try to escape from an effect that prevents it from moving. If there's nowhere to move, the creature can use the Dodge action.
+          <p>As an action, you present your holy symbol and speak a prayer censuring the undead. Each undead that can see or hear you within 30 feet of you must make a Wisdom saving throw. If the creature fails its saving throw, it is turned for 1 minute or until it takes any damage.</p>
+          <p>A turned creature must spend its turns trying to move as far away from you as it can, and it can't willingly move to a space within 30 feet of you. It also can't take reactions. For its action, it can use only the Dash action or try to escape from an effect that prevents it from moving. If there's nowhere to move, the creature can use the Dodge action.</p>
           `,
+        ability: '',
       },
       {
         name: 'Harness Divine Power',
         level: 2,
         description: `
-          At 2nd level, you can expend a use of your Channel Divinity to fuel your spells. As a bonus action, you touch your holy symbol, utter a prayer, and regain one expended spell slot, the level of which can be no higher than half your proficiency bonus (rounded up). The number of times you can use this feature is based on the level you've reached in this class: 2nd level, once; 6th level, twice; and 18th level, thrice. You regain all expended uses when you finish a long rest.
+          <p>At 2nd level, you can expend a use of your Channel Divinity to fuel your spells. As a bonus action, you touch your holy symbol, utter a prayer, and regain one expended spell slot, the level of which can be no higher than half your proficiency bonus (rounded up). The number of times you can use this feature is based on the level you've reached in this class: 2nd level, once; 6th level, twice; and 18th level, thrice. You regain all expended uses when you finish a long rest.<p>
           `,
+        ability: '',
       },
       {
         name: 'Ability Score Improvement',
         level: 4,
         description: `
-          When you reach 4th level, and again at 8th, 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 4th level, and again at 8th, 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature. </p>
           `,
       },
       {
         name: 'Destroy Undead',
         level: 5,
         description: `
-          Starting at 5th level, when an undead fails its saving throw against your Turn Undead feature, the creature is instantly destroyed if its challenge rating is at or below a certain threshold, as shown in the Cleric table above.          `,
+          <p>Starting at 5th level, when an undead fails its saving throw against your Turn Undead feature, the creature is instantly destroyed if its challenge rating is at or below a certain threshold, as shown in the Cleric table above.</p>`,
       },
       {
         name: 'Blessed Strikes',
         level: 8,
         description: `
-          Replaces the Divine Strike or Potent Spellcasting feature
-
-          When you reach 8th level, you are blessed with divine might in battle. When a creature takes damage from one of your cantrips or weapon attacks, you can also deal 1d8 radiant damage to that creature. Once you deal this damage, you can't use this feature again until the start of your next turn.
+          <p>Replaces the Divine Strike or Potent Spellcasting feature</p>
+          <p>When you reach 8th level, you are blessed with divine might in battle. When a creature takes damage from one of your cantrips or weapon attacks, you can also deal 1d8 radiant damage to that creature. Once you deal this damage, you can't use this feature again until the start of your next turn.</p>
         `,
+        ability: '',
       },
       {
         name: 'Ability Score Improvement',
         level: 8,
         description: `
-          When you reach 4th level, and again at 8th, 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          <p>When you reach 8th level, and again at 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature. </p>
           `,
       },
       {
         name: 'Divine Intervention',
         level: 10,
         description: `
-          Beginning at 10th level, you can call on your deity to intervene on your behalf when your need is great.
-
-          Imploring your deity's aid requires you to use your action. Describe the assistance you seek, and roll percentile dice. If you roll a number equal to or lower than your cleric level, your deity intervenes. The GM chooses the nature of the intervention; the effect of any cleric spell or cleric domain spell would be appropriate.
-
-          If your deity intervenes, you can't use this feature again for 7 days. Otherwise, you can use it again after you finish a long rest.
-
-          At 20th level, your call for intervention succeeds automatically, no roll required.
+          <p>Beginning at 10th level, you can call on your deity to intervene on your behalf when your need is great.</p>
+          <p>Imploring your deity's aid requires you to use your action. Describe the assistance you seek, and roll percentile dice. If you roll a number equal to or lower than your cleric level, your deity intervenes. The GM chooses the nature of the intervention; the effect of any cleric spell or cleric domain spell would be appropriate.</p>
+          <p>If your deity intervenes, you can't use this feature again for 7 days. Otherwise, you can use it again after you finish a long rest.</p>
+          <p>At 20th level, your call for intervention succeeds automatically, no roll required.</p>
         `,
+        ability: '',
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 12,
+        description: `
+          <p>When you reach 4th level, and again at 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature. </p>
+          `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 16,
+        description: `
+          <p>When you reach 4th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature. </p>
+          `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 19,
+        description: `
+          <p>When you reach 19th level you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature. </p>
+          `,
       },
     ],
   };
@@ -515,7 +729,7 @@ export class ClassService {
   private notImplementedYet: any = {
     title: 'Not implemented yet',
     description: `
-    This class is not implemented yet. Please check back later.
+    This class is not implemented yet, please check back later.
     `,
     features: [],
   };

+ 6 - 3
src/services/data/data.service.ts

@@ -160,6 +160,7 @@ export class DataService {
     subclass: '',
     race: '',
     background: '',
+    backgroundStory: '',
     level: 1,
     experience: 0,
   };
@@ -210,8 +211,10 @@ export class DataService {
 
   public removeFavoriteSpell(spell: Spell): void {
     const index = this._favoriteSpells.indexOf(spell);
-    this._favoriteSpells.splice(index, 1);
-    this.setData('favoriteSpells', { spells: this._favoriteSpells });
+    if (index > -1) {
+      this._favoriteSpells.splice(index, 1);
+      this.setData('favoriteSpells', { spells: this._favoriteSpells });
+    }
   }
 
   private _customSpells: Spell[] = [];
@@ -271,7 +274,7 @@ export class DataService {
     });
   }
 
-  private _customSpellId: number = 100;
+  private _customSpellId: number = 10000;
 
   public get customSpellId(): number {
     return this._customSpellId;

+ 11 - 2
src/services/modal/modal.service.ts

@@ -14,14 +14,23 @@ export class ModalService {
   private _resultSubject = new Subject<any>();
   result$ = this._resultSubject.asObservable();
 
+  /**
+   * Opens the modal with the specified component and provides the data as input for the component.
+   * @param component The component to open in the modal.
+   * @param data The data for the input of the component.
+   */
   public openModal(component: any, data: any) {
     console.log('ModalService: openModal');
     this._modalSubject.next({ component, data });
   }
 
-  // Is called from the dynamic content component to close the modal
+  /**
+   * This function closes the modal and sends a result state and an optinal data object to the host component.
+   * @param result The result state. Can be 'cancel', 'update' etc.
+   * @param data The oprional data object that eg contains a new or modifed weapon object.
+   */
   public handleModalClosing(result: any, data?: any) {
-    // Is listened to in the host component where the panel was opened, to initiate further steps
+    //The host components subscribe to the result$ Observable to get the result of the modal
     this._resultSubject.next({ state: result, data: data });
     this._closeModalSubject.next('close');
   }

+ 356 - 180
src/services/spells/spells.service.ts

@@ -34,8 +34,6 @@ export class SpellsService {
       .filter((spell) => spell.level === level)
       .filter((spell) => spell.classes.includes(characterClass));
     result.push(...this.customSpells.filter((spell) => spell.level === level));
-    console.log(result);
-
     return result;
   }
 
@@ -66,13 +64,15 @@ export class SpellsService {
       id: 0,
       isCustom: false,
       german: 'Göttliche Führung',
-      english: 'guidance',
+      english: 'Guidance',
+      image: 'guidance',
       classes: ['Test', 'Cleric', 'Druid'],
       level: 0,
       cost: 'action',
       duration: 10,
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -94,19 +94,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1,
       isCustom: false,
       german: 'Totenläuten',
-      english: 'tollTheDead',
+      english: 'Toll the Dead',
+      image: 'tollTheDead',
       classes: ['Test', 'Cleric', 'Warlock', 'Wizard'],
       level: 0,
       cost: 'action',
       duration: 0,
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -133,19 +135,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 2,
       isCustom: false,
       german: 'Thaumaturgie',
-      english: 'thaumaturgy',
+      english: 'Thaumaturgy',
+      image: 'thaumaturgy',
       classes: ['Test', 'Cleric'],
       level: 0,
       cost: 'action',
       duration: 10,
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: false,
@@ -184,19 +188,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 3,
       german: 'Gift versprühen',
-      english: 'sprayPoison',
+      english: 'Spray Posion',
+      image: 'sprayPoison',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Artificer', 'Sorcerer', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -217,19 +223,21 @@ export class SpellsService {
       range: 10,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 4,
       german: 'Ausbessern',
-      english: 'mending',
+      english: 'Mending',
+      image: 'mending',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Cleric', 'Druid', 'Wizard', 'Sorcerer'],
       timeToCast: 10,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -252,19 +260,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 5,
       german: 'Befall',
-      english: 'infestation',
+      english: 'Infestation',
+      image: 'infestation',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Sorcerer', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -307,14 +317,16 @@ export class SpellsService {
     {
       id: 6,
       german: 'Blitzköder',
-      english: 'lightningLure',
+      english: 'Lightning Lure',
+      image: 'lightningLure',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard', 'Warlock'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: false,
@@ -344,14 +356,16 @@ export class SpellsService {
     {
       id: 7,
       german: 'Botschaft',
-      english: 'message',
+      english: 'Message',
+      image: 'message',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Wizard', 'Sorcerer'],
       timeToCast: 0,
       cost: 'action',
       duration: 1,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -374,19 +388,21 @@ export class SpellsService {
       range: 120,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 8,
       german: 'Donnerschlag',
-      english: 'thunderclap',
+      english: 'Thunderclap',
+      image: 'thunderclap',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Druid', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -411,19 +427,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: true,
       areaOfEffectType: 'circle',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 9,
       german: 'Dornenpeitsche',
-      english: 'thornWhip',
+      english: 'Thorn Whip',
+      image: 'thornWhip',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -446,12 +464,13 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 10,
       german: 'Druidenkunst',
-      english: 'druidcraft',
+      english: 'Druidcraft',
+      image: 'druidcraft',
       level: 0,
       isCustom: false,
 
@@ -459,7 +478,8 @@ export class SpellsService {
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -493,19 +513,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 11,
       german: 'Dröhnende Klinge',
-      english: 'boomingBlade',
+      english: 'Booming Blade',
+      image: 'boomingBlade',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 1,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: true,
@@ -529,19 +551,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 11,
       german: 'Einfache Illusion',
-      english: 'minorIllusion',
+      english: 'Minor Illusion',
+      image: 'minorIllusion',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Wizard', 'Warlock', 'Sorcerer'],
       timeToCast: 0,
       cost: 'action',
       duration: 1,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: true,
@@ -566,19 +590,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 12,
       german: 'Erde Formen',
-      english: 'moldEarth',
+      english: 'Mold Earth',
+      image: 'moldEarth',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 600,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -612,19 +638,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: true,
       areaOfEffectType: 'cube',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 13,
       german: 'Erfrierung',
-      english: 'frostbite',
+      english: 'Frostbite',
+      image: 'frostbite',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Warlock', 'Artificer', 'Sorcerer', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -649,19 +677,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 14,
       german: 'Feuerpfeil',
-      english: 'fireBolt',
+      english: 'Fire Bolt',
+      image: 'fireBolt',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -685,19 +715,21 @@ export class SpellsService {
       range: 120,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 15,
       german: 'Flammen Erzeugen',
-      english: 'produceFlames',
+      english: 'Produce Flame',
+      image: 'produceFlames',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid'],
       timeToCast: 0,
       cost: 'action',
       duration: 100,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -723,19 +755,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 16,
       german: 'Flammen kontrollieren',
-      english: 'controlFlames',
+      english: 'Control Flames',
+      image: 'controlFlames',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Artificer', 'Sorcerer', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 600,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -771,19 +805,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: true,
       areaOfEffectType: 'cube',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 17,
       german: 'Freundschaft',
-      english: 'friends',
+      english: 'Friends',
+      image: 'friends',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 10,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: true,
@@ -805,19 +841,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 18,
       german: 'Gedankensplitter',
-      english: 'mindSliver',
+      english: 'Mind Sliver',
+      image: 'mindSliver',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: false,
@@ -834,24 +872,30 @@ export class SpellsService {
         <p>Du treibst einen verstörenden Splitter psychischer Energie in den Geist einer Kreatur, die du in Reichweite sehen kannst. Das Ziel muss einen erfolgreichen Rettungswurf auf Intelligenz durchführen, sonst nimmt es 1W6 psychischen Schaden und muss 1W4 von seinem nächsten Rettungswurf vor Ende deines nächsten Zuges abziehen.</p>
         <p><b>Auf höheren Stufen:</b> Der Schaden des Zaubers erhöht sich um je 1W6 wenn du Stufe 5 (auf 2W6), Stufe 11 (auf 3W6) und Stufe 17 (auf 4W6) erreichst.</p>
       `,
+      description_en: `
+        <p>You drive a disorienting spike of psychic energy into the mind of one creature you can see within range. The target must succeed on an Intelligence saving throw or take 1d6 psychic damage and subtract 1d4 from the next saving throw it makes before the end of your next turn.</p>
+        <p><b>At higher levels:</b> The spell’s damage increases by 1d6 when you reach 5th level (2d6), 11th level (3d6), and 17th level (4d6).</p>
+      `,
       school: 'Enchantment',
       isRanged: true,
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 19,
       german: 'Gehässiger Spott',
-      english: 'viciousMockery',
+      english: 'Vicious Mockery',
+      image: 'viciousMockery',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: false,
@@ -875,19 +919,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 20,
       german: 'Gift versprühen',
-      english: 'poisonSpray',
+      english: 'Poison Spray',
+      image: 'poisonSpray',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -912,19 +958,21 @@ export class SpellsService {
       range: 10,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 21,
       german: 'Grünfeuerklinge',
-      english: 'greenFlameBlade',
+      english: 'Green-Flame Blade',
+      image: 'greenFlameBlade',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: true,
@@ -948,19 +996,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 22,
       german: 'Heilige Flamme',
-      english: 'sacredFlame',
+      english: 'Sacred Flame',
+      image: 'sacredFlame',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Cleric'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -985,19 +1035,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 23,
       german: 'Kalte Hand',
-      english: 'chillTouch',
+      english: 'Chill Touch',
+      image: 'chillTouch',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1023,19 +1075,21 @@ export class SpellsService {
       range: 120,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 24,
       german: 'Klingenbann',
-      english: 'bladeWard',
+      english: 'Blade Ward',
+      image: 'bladeWard',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 100,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: false,
@@ -1057,19 +1111,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 25,
       german: 'Kältestrahl',
-      english: 'rayOfFrost',
+      english: 'Ray of Frost',
+      image: 'rayOfFrost',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1093,19 +1149,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 26,
       german: 'Lagerfeuer erschaffen',
-      english: 'createBonfire',
+      english: 'Create Bonfire',
+      image: 'createBonfire',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 10,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1130,12 +1188,13 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: true,
       areaOfEffectType: 'cube',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 27,
       german: 'Licht',
-      english: 'light',
+      english: 'Light',
+      image: 'light',
       level: 0,
       isCustom: false,
       classes: [
@@ -1150,7 +1209,8 @@ export class SpellsService {
       timeToCast: 0,
       cost: 'action',
       duration: 600,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: true,
@@ -1162,7 +1222,7 @@ export class SpellsService {
       doesHeal: false,
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de: `
-      <p>Du berührst einen Gegenstand, der nicht größer als 10 Fuß in einer beliebigen Dimension ist. Bis der Zauber endet, strahlt das Objekt helles Licht in einem Radius von 20 Fußn und schwaches Licht für weitere 20 Fuß aus. Das Licht kann nach Belieben gefärbt werden. Wenn du das Objekt vollständig mit etwas Undurchsichtigem abdeckst, wird das Licht blockiert. Der Zauber endet, wenn du ihn erneut wirkst oder ihn als Aktion abbrichst.</p>
+      <p>Du berührst einen Gegenstand, der nicht größer als 10 Fuß in einer beliebigen Dimension ist. Bis der Zauber endet, strahlt das Objekt helles Licht in einem Radius von 20 Fuß und schwaches Licht für weitere 20 Fuß aus. Das Licht kann nach Belieben gefärbt werden. Wenn du das Objekt vollständig mit etwas Undurchsichtigem abdeckst, wird das Licht blockiert. Der Zauber endet, wenn du ihn erneut wirkst oder ihn als Aktion abbrichst.</p>
       <p>Wenn du ein Objekt anvisierst, das von einer feindlichen Kreatur gehalten oder getragen wird, muss diese Kreatur einen Rettungswurf auf Geschicklichkeit bestehen, um den Zauber zu vermeiden.</p>
       `,
       description_en: `
@@ -1173,20 +1233,22 @@ export class SpellsService {
       isRanged: false,
       range: 5,
       hasAreaOfEffect: false,
-      areaOfEffectType: '',
-      radius: 0,
+      areaOfEffectType: 'circle',
+      diameter: 40,
     },
     {
       id: 28,
       german: 'Magierhand',
-      english: 'mageHand',
+      english: 'Mage Hand',
+      image: 'mageHand',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 10,
-      canRitual: 'true',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1212,19 +1274,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 29,
       german: 'Magiestein',
-      english: 'magicStone',
+      english: 'Magic Stone',
+      image: 'magicStone',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Hexenmeister'],
       timeToCast: 0,
       cost: 'bonus',
       duration: 10,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1248,19 +1312,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 30,
       german: 'Resistenz',
-      english: 'resistance',
+      english: 'Resistance',
+      image: 'resistance',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Cleric', 'Druid', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 10,
-      canRitual: 'true',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -1282,19 +1348,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 31,
       german: 'Schauriger Strahl',
-      english: 'eldritchBlast',
+      english: 'Eldritch Blast',
+      image: 'eldritchBlast',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Hexenmeister'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1318,19 +1386,21 @@ export class SpellsService {
       range: 120,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 32,
       german: 'Schockgriff',
-      english: 'shockingGrasp',
+      english: 'Shocking Grasp',
+      image: 'shockingGrasp',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1354,19 +1424,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 33,
       german: 'Schwertexplosion',
-      english: 'swordBurst',
+      english: 'Sword Burst',
+      image: 'swordBurst',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Warlock', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -1391,19 +1463,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: true,
       areaOfEffectType: 'circle',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 34,
       german: 'Shillelagh',
-      english: 'shillelagh',
+      english: 'Shillelagh',
+      image: 'shillelagh',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid'],
       timeToCast: 0,
       cost: 'bonus',
       duration: 10,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -1425,19 +1499,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 35,
       german: 'Säurespritzer',
-      english: 'acidSplash',
+      english: 'Acid Splash',
+      image: 'acidSplash',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1462,19 +1538,21 @@ export class SpellsService {
       range: 60,
       hasAreaOfEffect: true,
       areaOfEffectType: 'circle',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 36,
       german: 'Tanzende Lichter',
-      english: 'dancingLights',
+      english: 'Dancing Lights',
+      image: 'dancingLights',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 10,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -1497,19 +1575,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 37,
       german: 'Taschenspielerei',
-      english: 'prestidigitation',
+      english: 'Prestidigitation',
+      image: 'prestidigitation',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 600,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1549,19 +1629,21 @@ export class SpellsService {
       range: 10,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 38,
       german: 'Verschonung der Toten',
-      english: 'spareTheDying',
+      english: 'Spare the Dying',
+      image: 'spareTheDying',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Cleric'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1583,19 +1665,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 39,
       german: 'Urtümliche Wildheit',
-      english: 'primalSavagery',
+      english: 'Primal Savagery',
+      image: 'primalSavagery',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -1619,19 +1703,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 40,
       german: 'Wasser formen',
-      english: 'shapeWater',
+      english: 'Shape Water',
+      image: 'shapeWater',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 600,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -1667,19 +1753,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: true,
       areaOfEffectType: 'cube',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 41,
       german: 'Windböe',
-      english: 'gust',
+      english: 'Gust',
+      image: 'gust',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Druid', 'Sorcerer', 'Wizard', 'Artificer'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1712,19 +1800,21 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 42,
       german: 'Wort des Strahlens',
-      english: 'wordOfRadiance',
+      english: 'Word of Radiance',
+      image: 'wordOfRadiance',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Cleric'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1749,19 +1839,21 @@ export class SpellsService {
       range: 5,
       hasAreaOfEffect: true,
       areaOfEffectType: 'circle',
-      radius: 5,
+      diameter: 5,
     },
     {
       id: 43,
       german: 'Zielsicherer Schlag',
-      english: 'trueStrike',
+      english: 'True Strike',
+      image: 'trueStrike',
       level: 0,
       isCustom: false,
       classes: ['Test', 'Sorcerer', 'Wizard'],
       timeToCast: 0,
       cost: 'action',
       duration: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: false,
       needsSomatic: true,
       needsMaterial: false,
@@ -1783,20 +1875,22 @@ export class SpellsService {
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     // Level 1
     {
       id: 1000,
       german: 'Wunden verursachen',
-      english: 'inflictWounds',
+      english: 'Inflict Wounds',
+      image: 'inflictWounds',
       level: 1,
       cost: 'action',
       isCustom: false,
       classes: ['Test', 'Cleric'],
       duration: 0,
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1809,24 +1903,28 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Mach einen Nahkampf-Zauberangriff gegen eine Kreatur deiner Wahl. Bei einem Erfolg erleidet das Ziel 3W10 Nekrotischen Schaden. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, steigt der Schaden für jeden Grad über dem 1. um 1W10.',
+      description_en:
+        'Make a melee spell attack against a creature you can reach. On a hit, the target takes 3d10 necrotic damage. At higher levels: When you cast this spell using a spell slot of 2nd level or higher, the damage increases by 1d10 for each slot level above 1st.',
       school: 'Necromancy',
       isRanged: false,
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1001,
       german: 'Heilende Berührung',
-      english: 'cureWounds',
+      english: 'Cure Wounds',
+      image: 'cureWounds',
       level: 1,
       cost: 'action',
       duration: 0,
       isCustom: false,
       classes: ['Test', 'Bard', 'Cleric', 'Druid', 'Paladin', 'Ranger'],
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1839,17 +1937,20 @@ export class SpellsService {
       heal: { diceNumber: '1', diceType: 'd8', additionalHeal: 4 },
       description_de:
         'Eine Kreatur, die du berührst, gewinnt Trefferpunkte in Höhe von 1W8 + deinem Attributsmodifikator im Zauberwirken zurück. Dieser Zauber wirkt nicht auf Untote oder Konstrukte. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, steigt die Heilung für jeden Grad über dem 1. um 1W8.',
+      description_en:
+        'A creature you touch regains a number of hit points equal to 1d8 + your spellcasting ability modifier. This spell has no effect on undead or constructs. At higher levels: When you cast this spell using a spell slot of 2nd level or higher, the healing increases by 1d8 for each slot level above 1st.',
       school: 'Evocation',
       isRanged: false,
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1002,
       german: 'Magie entdecken',
-      english: 'detectMagic',
+      english: 'Detact Magic',
+      image: 'detectMagic',
       level: 1,
       cost: 'action',
       duration: 100,
@@ -1865,7 +1966,8 @@ export class SpellsService {
         'Wizard',
       ],
       timeToCast: 0,
-      canRitual: 'true',
+      canRitual: true,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1878,24 +1980,28 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Während der Wirkungsdauer nimmst du die Gegenwart von Magie im Abstand von bis zu 30 Fuß von dir wahr. Wenn du auf diese Weise Magie wahrnimmst, kannst du deine Aktion verwenden, um schwache Auren um sichtbare magische Kreaturen oder Objekte sowie ihre magische Schule zu erkennen, falls vorhanden. Dieser Zauber durchdringt die meisten Barrieren, wird aber von 30 Zentimeter Stein, 2,5 Zentimetern gewöhnlichem Metall, dünnem Bleiblech sowie von einem Meter Holz oder Erde blockiert.',
+      description_en:
+        'For the duration, you sense the presence of magic within 30 feet of you. If you sense magic in this way, you can use your action to see a faint aura around any visible creature or object in the area that bears magic, and you learn its school of magic, if any. The spell can penetrate most barriers, but it is blocked by 1 foot of stone, 1 inch of common metal, a thin sheet of lead, or 3 feet of wood or dirt.',
       school: 'Divination',
       isRanged: true,
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1003,
       german: 'Segnen',
-      english: 'bless',
+      english: 'Bless',
+      image: 'bless',
       level: 1,
       cost: 'action',
       duration: 10,
       isCustom: false,
       classes: ['Test', 'Cleric', 'Paladin'],
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -1908,24 +2014,28 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Du segnest bis zu drei Kreaturen deiner Wahl in Reichweite. Wenn ein Ziel während der Wirkungsdauer einen Angriffs- oder Rettungswurf ausführt, darf es mit einem W4 würfeln und das Würfelergebnis zu seinem Angriffs- oder Rettungswurf addieren. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, kannst du für jeden Grad über dem 1. eine zusätzliche Kreatur als Ziel wählen.',
+      description_en:
+        'You bless up to three creatures of your choice within range. Whenever a target makes an attack roll or a saving throw before the spell ends, the target can roll a d4 and add the number rolled to the attack roll or saving throw. At higher levels: When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st.',
       school: 'Enchantment',
       isRanged: true,
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1004,
       german: 'Heilendes Wort',
-      english: 'healingWord',
+      english: 'Healing Word',
+      image: 'healingWord',
       isCustom: false,
       classes: ['Test', 'Bard', 'Cleric', 'Druid'],
       level: 1,
       cost: 'bonus action',
       duration: 0,
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: false,
       needsMaterial: false,
@@ -1938,24 +2048,28 @@ export class SpellsService {
       heal: { diceNumber: '1', diceType: 'd4', additionalHeal: 4 },
       description_de:
         'Eine Kreatur deiner Wahl in Reichweite, die du sehen kannst, gewinnt Trefferpunkte in Höhe von 1W4 + deinem Zauberwirken-Attributsmodifikator zurück. Dieser Zauber wirkt nicht auf Untote oder Konstrukte. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, steigt die Heilung für jeden Grad über dem 1. um 1W4.',
+      description_en:
+        'A creature of your choice that you can see within range regains hit points equal to 1d4 + your spellcasting ability modifier. This spell has no effect on undead or constructs. At higher levels: When you cast this spell using a spell slot of 2nd level or higher, the healing increases by 1d4 for each slot level above 1st.',
       school: 'Evocation',
       isRanged: true,
       range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1005,
       german: 'Lenkendes Geschoss',
-      english: 'guidingBolt',
+      english: 'Guiding Bolt',
+      image: 'guidingBolt',
       level: 1,
       cost: 'action',
       duration: 0,
       isCustom: false,
       classes: ['Test', 'Cleric'],
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -1968,24 +2082,28 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Ein Lichtblitz schießt auf eine Kreatur deiner Wahl in Reichweite zu. Führe einen Fernkampf-Zauberangriff gegen das Ziel aus. Bei einem Erfolg erleidet das Ziel 4W6 gleißenden Schaden. Dank des mystischen dämmrigen Lichts, das auf dem Ziel glitzert, ist der nächste Angriffswurf gegen das Ziel vor Ende deines nächsten Zugs im Vorteil. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, steigt der Schaden für jeden Grad über dem 1. um 1W6.',
+      description_en:
+        'A flash of light streaks toward a creature of your choice within range. Make a ranged spell attack against the target. On a hit, the target takes 4d6 radiant damage, and the next attack roll made against this target before the end of your next turn has advantage, thanks to the mystical dim light glittering on the target until then. At higher levels: When you cast this spell using a spell slot of 2nd level or higher, the damage increases by 1d6 for each slot level above 1st.',
       school: 'Evocation',
       isRanged: true,
       range: 120,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1006,
       german: 'Gift und Krankheiten entdecken',
-      english: 'detectPoisonAndDisease',
+      english: 'Detect Poison and Disease',
+      image: 'detectPoisonAndDisease',
       level: 1,
       cost: 'action',
       duration: 100,
       isCustom: false,
       classes: ['Test', 'Cleric', 'Druid', 'Paladin', 'Ranger'],
       timeToCast: 0,
-      canRitual: 'true',
+      canRitual: true,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -1998,24 +2116,28 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Während der Wirkungsdauer nimmst du die Gegenwart und die Position von Giften, giftigen Kreaturen und Krankheiten im Abstand von bis zu neun Metern von dir wahr. Du kannst auch die Art des Gifts, der giftigen Kreatur oder der Krankheit bestimmen. Dieser Zauber durchdringt die meisten Barrieren, wird aber von 1 Fußn Stein, 2,5 Zentimetern gewöhnlichem Metall, dünnem Bleiblech sowie von einem Meter Holz oder Erde blockiert.',
+      description_en:
+        'For the duration, you can sense the presence and location of poisons, poisonous creatures, and diseases within 30 feet of you. You also identify the kind of poison, poisonous creature, or disease in each case. The spell can penetrate most barriers, but it is blocked by 1 foot of stone, 1 inch of common metal, a thin sheet of lead, or 3 feet of wood or dirt.',
       school: 'Divination',
       isRanged: true,
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1007,
       german: 'Heldenmut',
-      english: 'heroism',
+      english: 'Heroism',
+      image: 'heroism',
       level: 1,
       cost: 'action',
       duration: 10,
       isCustom: false,
       classes: ['Test', 'Bard', 'Paladin'],
       timeToCast: 0,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: false,
@@ -2028,24 +2150,28 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Du berührst eine bereitwillige Kreatur und erfüllst sie mit Tapferkeit. Bis der Zauber endet, kann die Kreatur nicht verängstigt werden, und sie erhält zu Beginn jedes ihrer Züge temporäre Trefferpunkte in Höhe deines Zauberwirken-Attributsmodifikators. Wenn der Zauber endet, verliert das Ziel alle verbleibenden temporären Trefferpunkte dieses Zaubers. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, kannst du für jeden Grad über dem 1. eine zusätzliche Kreatur als Ziel wählen.',
+      description_en:
+        'A willing creature you touch is imbued with bravery. Until the spell ends, the creature is immune to being frightened and gains temporary hit points equal to your spellcasting ability modifier at the start of each of its turns. When the spell ends, the target loses any remaining temporary hit points from this spell. At higher levels: When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st.',
       school: 'Enchantment',
       isRanged: false,
       range: 5,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
     {
       id: 1008,
       german: 'Heiligtum',
-      english: 'sanctuary',
+      english: 'Sanctuary',
+      image: 'sanctuary',
       level: 1,
       isCustom: false,
       classes: ['Test', 'Cleric'],
       timeToCast: 0,
       cost: 'bonus action',
       duration: 10,
-      canRitual: 'false',
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
@@ -2058,44 +2184,94 @@ export class SpellsService {
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
       description_de:
         'Du schützt eine Kreatur in Reichweite vor Angriffen. Während der Wirkungsdauer muss jede Kreatur, die bei einem Angriff oder schädlichen Zauber die geschützte Kreatur als Ziel hat, zuerst einen Weisheitsrettungswurf bestehen. Scheitert der Wurf, muss die Kreatur ein neues Ziel wählen, oder sie verliert den Angriff oder Zauber. Dieser Zauber schützt die entsprechende Kreatur nicht vor Flächeneffekten wie der Explosion eines Feuerballs. Greift die geschützte Kreatur an oder wirkt sie einen Zauber auf eine feindliche Kreatur, endet der Effekt dieses Zaubers.',
+      description_en:
+        'You ward a creature within range against attack. Until the spell ends, any creature who targets the warded creature with an attack or a harmful spell must first make a Wisdom saving throw. On a failed save, the creature must choose a new target or lose the attack or spell. This spell doesn’t protect the warded creature from area effects, such as the explosion of a fireball. If the warded creature makes an attack or casts a spell that affects an enemy creature, this spell ends.',
       school: 'Abjuration',
       isRanged: true,
       range: 30,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
+
+    // Level 2
     {
-      id: 1009,
-      german: 'Illusion',
-      english: 'illusion',
-      level: 1,
+      id: 2000,
+      german: 'Beistand',
+      english: 'Aid',
+      image: 'aid',
+      level: 2,
       isCustom: false,
-      classes: ['Test', 'Cleric'],
+      classes: ['Test', 'Cleric', 'Paladin'],
       timeToCast: 0,
-      cost: 'bonus action',
-      duration: 10,
-      canRitual: 'false',
+      cost: 'action',
+      duration: 4800,
+      canRitual: false,
+      isRitual: false,
       needsVerbal: true,
       needsSomatic: true,
       needsMaterial: true,
-      needsConcentration: true,
+      needsConcentration: false,
       needsAttackRoll: false,
       needsSavingThrow: false,
       doesDamage: false,
       damage: [{ diceNumber: '', diceType: '', damageType: '' }],
+      doesHeal: true,
+      heal: { diceNumber: '', diceType: '', additionalHeal: 5 },
+      description_de: `
+        <p>Dein Zauber unterstützt deine Verbündeten. Wähle bis zu 3 Kreaturen in Reichweite. Das Trefferpunkte-Maximum, sowie die momentanen trefferpunkte werden um 5 erhöht.</p>
+        <p><b>Auf höheren Graden:</b> Wirkst du diesen Zauber mit einem Zauberplatz des 3. Grades oder höher, erhöht sich das Trefferpunkte-Maximum um zusätzliche 5 Trefferpunkte für jeden Grad über dem 2.</p>
+      `,
+      description_en: `
+        <p>Your spell bolsters your allies with toughness and resolve. Choose up to three creatures within range. Each target’s hit point maximum and current hit points increase by 5 for the duration.</p>
+        <p><b>At higher levels:</b> When you cast this spell using a spell slot of 3rd level or higher, a target’s hit points increase by an additional 5 for each slot level above 2nd.</p>
+      `,
+      school: 'Abjuration',
+      isRanged: true,
+      range: 30,
+      hasAreaOfEffect: false,
+      areaOfEffectType: '',
+      diameter: 0,
+    },
+    {
+      id: 2001,
+      german: 'Waffe des Glaubens',
+      english: 'Spiritual Weapon',
+      image: 'spiritualWeapon',
+      level: 2,
+      isCustom: false,
+      classes: ['Test', 'Cleric'],
+      timeToCast: 0,
+      cost: 'bonus action',
+      duration: 10,
+      canRitual: false,
+      isRitual: false,
+      needsVerbal: true,
+      needsSomatic: true,
+      needsMaterial: false,
+      needsConcentration: false,
+      needsAttackRoll: true,
+      needsSavingThrow: false,
+      doesDamage: true,
+      damage: [{ diceNumber: '1', diceType: 'd8', damageType: 'force' }],
       doesHeal: false,
       heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
-      description_de:
-        'Du schützt eine Kreatur in Reichweite vor Angriffen. Während der Wirkungsdauer muss jede Kreatur, die bei einem Angriff oder schädlichen Zauber die geschützte Kreatur als Ziel hat, zuerst einen Weisheitsrettungswurf bestehen. Scheitert der Wurf, muss die Kreatur ein neues Ziel wählen, oder sie verliert den Angriff oder Zauber. Dieser Zauber schützt die entsprechende Kreatur nicht vor Flächeneffekten wie der Explosion eines Feuerballs. Greift die geschützte Kreatur an oder wirkt sie einen Zauber auf eine feindliche Kreatur, endet der Effekt dieses Zaubers.',
-      school: 'Illusion',
+      description_de: `
+        <p>Du erschaffst eine Schwebende, gespenstische Waffe in Reichweite, die für die Wirkungsdauer anhält oder bis du den Zauber erneut wirkst. Wenn du den Zauber wirkst, kannst du einen Nahkampfangriff gegen eine Kreatur innerhalb von 5 Fuß zur Waffe durchführen. Bei einem Treffer erleidet das Ziel 1W8 + deinen Zaubermodifikator als Energieschaden.</p>
+        <p>Als Bonusaktion in deinem Zug kannst du die Waffe bis zu 20 Fuß weit bewegen und den Angriff gegen eine Kreatur innerhalb von 5 Fuß um sie wiederholen.</p>
+        <p>Die Waffe kann jede Form annehmen, die du wählst. Kleriker von Gottheiten, die mit einer bestimmten Waffe assoziiert sind (wie St. Cuthbert für seine Keule und Thor für seinen Hammer), lassen den Effekt dieses Zaubers wie diese Waffe aussehen.</p>
+        <p><b>Auf höheren Graden:</b> Wirkst du diesen Zauber mit einem Zauberplatz des 3. Grades oder höher, erhöht sich der Schaden um 1W8 für jeden zweiten Grad über dem 2.</p>
+      `,
+      description_en: `
+        <p>You create a floating, spectral weapon within range that lasts for the duration or until you cast this spell again. When you cast the spell, you can make a melee spell attack against a creature within 5 feet of the weapon. On a hit, the target takes force damage equal to 1d8 + your spellcasting ability modifier. As a bonus action on your turn, you can move the weapon up to 20 feet and repeat the attack against a creature within 5 feet of it. The weapon can take whatever form you choose. Clerics of deities who are associated with a particular weapon (as St. Cuthbert is known for his mace and Thor for his hammer) make this spell’s effect resemble that weapon.</p>
+        <p><b>At higher levels:</b> When you cast this spell using a spell slot of 3rd level or higher, the damage increases by 1d8 for every two slot levels above 2nd.</p>
+      `,
+      school: 'Evocation',
       isRanged: true,
-      range: 30,
+      range: 60,
       hasAreaOfEffect: false,
       areaOfEffectType: '',
-      radius: 0,
+      diameter: 0,
     },
-
-    // Level 2
   ];
 }

+ 1 - 0
src/services/translator/translator.service.ts

@@ -69,6 +69,7 @@ export class TranslatorService {
     Sorcerer: { display: 'Zauberer', value: 'Sorcerer' },
     Warlock: { display: 'Hexenmeister', value: 'Warlock' },
     Wizard: { display: 'Magier', value: 'Wizard' },
+    Test: { display: 'Test', value: 'Test' },
   };
 
   public genders: any = {

+ 21 - 0
src/styles.scss

@@ -212,6 +212,13 @@
     }
 }
 
+.suffix {
+    text-align: right;
+    padding-right: 0.5rem;
+    color: grey;
+    font-size: 0.75rem;
+}
+
 // Line styles
 
 .centered-line {
@@ -346,6 +353,7 @@ input[type="checkbox"] {
 .ProseMirror {
     padding-left: 1rem !important;
     height: 8rem;
+    overflow: auto;
 }
 
 // Used to remove the empty space under form fields
@@ -386,3 +394,16 @@ body {
 .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing {
     border-color: var(--primary) !important;
 }
+
+.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input {
+    caret-color: var(--primary) !important;
+}
+
+.mat-mdc-form-field.mat-focused .mat-mdc-select-arrow {
+    color: var(--primary) !important;
+}
+
+.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-floating-label,
+.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-floating-label--float-above {
+    color: var(--primary) !important;
+}