Procházet zdrojové kódy

Merge branch 'release/0.11.1'

Warafear před 9 měsíci
rodič
revize
3d1c0d73a7

+ 1 - 3
package.json

@@ -1,6 +1,6 @@
 {
   "name": "dndtools",
-  "version": "0.11.0",
+  "version": "0.11.1",
   "scripts": {
     "ng": "ng",
     "start": "nx serve",
@@ -27,9 +27,7 @@
     "@popperjs/core": "^2.11.6",
     "bootstrap": "^5.2.3",
     "localbase": "^0.7.5",
-    "marked": "^9.1.6",
     "ngx-editor": "^16.0.1",
-    "ngx-markdown": "^17.1.1",
     "prettier": "^3.2.5",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",

+ 13 - 17
src/app/journal/journal-spellbook/custom-spells-modal/custom-spells-modal.component.html

@@ -9,28 +9,24 @@
           [ngClass]="{ selected: indexList.includes(index) }"
           (click)="toggleSpellSelection(index)"
         >
-          @if (translate.getDefaultLang() == "de") {
-            {{ spell.german }}
-          } @else {
-            {{ spell.english }}
-          }
+          <div class="spell-name">
+            @if (translate.getDefaultLang() == "de") {
+              {{ spell.german }}
+            } @else {
+              {{ spell.english }}
+            }
+          </div>
+          <div class="spell-level">
+            {{ "spellbook.favorites.levels." + spell.level | translate }}
+          </div>
+          <div class="spell-school">
+            {{ "schools." + spell.school | translate }}
+          </div>
         </div>
       }
     </div>
   </div>
   <div class="button-container">
-    <!-- <ui-button
-      [color]="'red'"
-      [width]="'w15'"
-      [type]="'deleteSelected'"
-      (click)="delete()"
-    ></ui-button> -->
-    <!-- <ui-button
-      [color]="'red'"
-      [width]="'w15'"
-      [type]="'cancel'"
-      (click)="cancel()"
-    ></ui-button> -->
     <button
       [class]="indexList.length === 0 ? 'disabled' : ''"
       (click)="indexList.length !== 0 ? delete() : ''"

+ 13 - 1
src/app/journal/journal-spellbook/custom-spells-modal/custom-spells-modal.component.scss

@@ -32,7 +32,7 @@
   color: rgba(0, 0, 0, 0.87);
   display: flex;
   align-items: center;
-  justify-content: space-between;
+  // justify-content: space-between;
   background-image: url("/assets/images/texture.png");
   border-radius: 10px;
   font-size: 1rem;
@@ -48,6 +48,18 @@
   }
 }
 
+.spell-name {
+  width: 45%;
+}
+
+.spell-level {
+  width: 30%;
+}
+
+.spell-school {
+  width: 25%;
+}
+
 .selected {
   background-color: #58180d;
   box-sizing: border-box;

+ 2 - 3
src/app/journal/journal-spellbook/journal-spellbook.component.html

@@ -15,9 +15,8 @@
       </div>
     </div>
 
-    <!-- <hr /> -->
-    <div class="divider"></div>
-    <div class="class-picker">
+    <divider></divider>
+    <div class="class-picker t-075">
       @for (className of translator.magicClasses; track className) {
         <div class="class">
           <div

+ 0 - 8
src/app/journal/journal-spellbook/journal-spellbook.component.scss

@@ -15,14 +15,6 @@ h1 {
   font-size: 3.5rem;
   font-weight: 500;
   margin-bottom: 0;
-  // padding-left: 2rem;
-}
-
-.divider {
-  border-top: 2px solid #9b8559;
-  height: 1px;
-  width: 100%;
-  margin-bottom: 0.75rem;
 }
 
 .header-row {

+ 9 - 5
src/app/journal/journal-spellcards/add-card/add-card.component.html

@@ -7,15 +7,19 @@
     <div class="spell-selection">
       <div class="controll-row">
         <div class="toggle-row">
-          <span class="toggle-label" [class]="showAll ? 'inactive' : 'active'"
-            >Klasse</span
+          <span
+            class="toggle-label"
+            [class]="showAll ? 'inactive' : 'active'"
+            >{{ "spellcards.add.class" | translate }}</span
           >
           <mat-slide-toggle
             [hideIcon]="true"
             (change)="toggleShowAll()"
           ></mat-slide-toggle>
-          <span class="toggle-label" [class]="showAll ? 'active' : 'inactive'"
-            >Alle</span
+          <span
+            class="toggle-label"
+            [class]="showAll ? 'active' : 'inactive'"
+            >{{ "spellcards.add.all" | translate }}</span
           >
         </div>
         <icon-button [icon]="'cross'" (click)="resetThis()"></icon-button>
@@ -24,7 +28,7 @@
         type="text"
         class="spell-name"
         [(ngModel)]="newSpellName"
-        [placeholder]="'spellcards.add.official' | translate"
+        [placeholder]="'spellcards.add.search' | translate"
         (keyup)="filterSpellArray()"
       />
       <div class="available-spells">

+ 9 - 51
src/app/journal/journal-spellcards/add-card/add-card.component.scss

@@ -8,46 +8,17 @@
   overflow: hidden;
   transition: all 0.3s ease-in-out;
 
-  .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;
     cursor: pointer;
     transition: all 0.2s ease-in-out;
+    background-image: url("/assets/images/bg.jpg");
+    filter: brightness(0.8);
 
     &:hover {
-      background-color: var(--items);
+      filter: brightness(0.9);
     }
 
     .add-icon {
@@ -90,25 +61,12 @@
 .spell-selection {
   width: 100%;
   height: 100%;
-  background-color: var(--background-color);
+  // background-color: var(--background-color);
+  background-image: url("/assets/images/bg.jpg");
+  filter: brightness(0.9);
   padding-top: 0.375rem;
 }
 
-.add-button {
-  width: 90%;
-  margin: 0 0.5rem;
-  background-color: var(--primary);
-  border: var(--border);
-  border-radius: 10px;
-  box-shadow: var(--shadow);
-  font-weight: 600;
-  transition: all 0.25s ease-in-out;
-
-  &:hover {
-    background-color: var(--primary-dark);
-  }
-}
-
 .spell-name {
   width: 94%;
   margin: auto;
@@ -137,10 +95,10 @@
     width: 90%;
     box-shadow: var(--shadow);
     cursor: pointer;
-    transition: all 0.2s ease-in-out;
-    background-color: var(--items);
+    background-image: url("/assets/images/texture.png");
+    border: 1px solid var(--border-brown);
     &:hover {
-      background-color: var(--items-hover);
+      filter: brightness(0.9);
     }
   }
 }

+ 78 - 66
src/app/journal/journal-spellcards/journal-spellcards.component.html

@@ -1,74 +1,86 @@
 <div class="spellcards-container">
-  <!-- TODO: DELETE -->
-  <!-- <button class="manage-spells" (click)="openManageCustomSpellsModal()">
-    <img src="assets/icons/UIIcons/settings.svg" />
-    {{ "spellcards.manage" | translate }}
-  </button> -->
+  <div class="content">
+    <div class="header-row">
+      <h1>{{ "spellcards.prepared" | translate }}</h1>
+      <div class="button-container">
+        <button class="top-button" (click)="openFavoritesModal()">
+          <img src="assets/icons/UIIcons/favorites.svg" />
+          {{ "spellcards.favorites" | translate }}
+        </button>
 
-  <div cdkDropListGroup>
-    @for (
-      level of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
-      track level;
-      let index = $index
-    ) {
-      <div class="example-container">
-        <div
-          [class]="showSpellList[index] ? 'level-row' : 'level-row collapsed'"
-          (click)="toggleSpellList(index)"
-        >
-          <div class="level-flex">
-            <icon
-              [size]="'l'"
-              [type]="'UI'"
-              [icon]="showSpellList[index] ? 'visible' : 'hidden'"
-              [class]="'pointer'"
-              class="inline"
-            ></icon>
-            <div class="heading-2 inline">
-              @if (index === 0) {
-                {{ "spellcards.cantrips" | translate }}
-              } @else {
-                Level {{ index }}
-              }
+        <button class="top-button" (click)="navigateToSpellbook()">
+          <img src="assets/icons/UIIcons/book.svg" />
+          {{ "spellcards.spellbook" | translate }}
+        </button>
+      </div>
+    </div>
+
+    <divider class="t-075"></divider>
+    <div cdkDropListGroup class="t-075">
+      @for (
+        level of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+        track level;
+        let index = $index
+      ) {
+        <div class="example-container">
+          <div
+            [class]="showSpellList[index] ? 'level-row' : 'level-row collapsed'"
+            (click)="toggleSpellList(index)"
+          >
+            <div class="level-flex">
+              <icon
+                [size]="'l'"
+                [type]="'UI'"
+                [icon]="showSpellList[index] ? 'visible' : 'hidden'"
+                [class]="'pointer'"
+                class="inline"
+              ></icon>
+              <div class="heading-2 inline">
+                @if (index === 0) {
+                  {{ "spellcards.cantrips" | translate }}
+                } @else {
+                  Level {{ index }}
+                }
+              </div>
             </div>
           </div>
-        </div>
 
-        <div
-          cdkDropList
-          cdkDropListOrientation="horizontal"
-          [cdkDropListData]="getSpellList(index)"
-          class="spell-list"
-          (cdkDropListDropped)="drop($event)"
-          [class]="showSpellList[index] ? '' : 'hidden'"
-        >
-          @for (
-            spell of getSpellList(index);
-            let spellIndex = $index;
-            track spell
-          ) {
-            <spellcard
-              cdkDrag
-              [id]="spellIndex"
-              (cdkDragStarted)="dragStart(index)"
-              (cdkDragReleased)="dragEnd($event)"
-              [spell]="spell"
-              (click)="showFullSpellcard(spell, level, spellIndex)"
-            ></spellcard>
-          }
-          @if (draggingIndex === index) {
-            <div class="removal-card" [id]="'deletion' + index">
-              {{ "spellcards.delete" | translate }}
-            </div>
-          } @else {
-            <add-card
-              [level]="index"
-              [alreadyUsedSpells]="getUsedIDs(index)"
-              (onSpellSelected)="addSpell($event, index)"
-            ></add-card>
-          }
+          <div
+            cdkDropList
+            cdkDropListOrientation="horizontal"
+            [cdkDropListData]="getSpellList(index)"
+            class="spell-list"
+            (cdkDropListDropped)="drop($event)"
+            [class]="showSpellList[index] ? '' : 'hidden'"
+          >
+            @for (
+              spell of getSpellList(index);
+              let spellIndex = $index;
+              track spell
+            ) {
+              <spellcard
+                cdkDrag
+                [id]="spellIndex"
+                (cdkDragStarted)="dragStart(index)"
+                (cdkDragReleased)="dragEnd($event)"
+                [spell]="spell"
+                (click)="showFullSpellcard(spell, level, spellIndex)"
+              ></spellcard>
+            }
+            @if (draggingIndex === index) {
+              <div class="removal-card" [id]="'deletion' + index">
+                {{ "spellcards.delete" | translate }}
+              </div>
+            } @else {
+              <add-card
+                [level]="index"
+                [alreadyUsedSpells]="getUsedIDs(index)"
+                (onSpellSelected)="addSpell($event, index)"
+              ></add-card>
+            }
+          </div>
         </div>
-      </div>
-    }
+      }
+    </div>
   </div>
 </div>

+ 32 - 11
src/app/journal/journal-spellcards/journal-spellcards.component.scss

@@ -9,22 +9,45 @@
   background-image: url("/assets/images/bg.jpg");
 }
 
-.manage-spells {
-  position: absolute;
-  right: 2rem;
-  top: 1rem;
+.content {
+  width: 1300px;
+  margin: 0 auto;
+}
+
+.header-row {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  width: 100%;
+}
+
+h1 {
+  // color: #58180d;
+  // font-family: "Bookinsanity", serif;
+  font-size: 3.5rem;
+  font-weight: 500;
+  margin-bottom: 0;
+}
+
+.button-container {
+  display: flex;
+  flex-direction: row;
+  gap: 1rem;
+}
+
+.top-button {
   font-size: 1.25rem;
   font-weight: 600;
+  width: 16rem;
   display: flex;
   align-items: center;
   gap: 0.5rem;
   border-radius: 10px;
   padding: 0.5rem 1rem;
+  background-image: url("/assets/images/texture.png");
+  border: none;
   box-shadow: var(--shadow);
-  background: var(--edit);
-  &:hover {
-    background: var(--edit-hover);
-  }
 }
 
 .example-container {
@@ -35,7 +58,6 @@
   width: 16rem;
   gap: 1rem;
   padding: 0.25rem 1rem;
-  // background: white;
   background-image: url("/assets/images/texture.png");
   border: solid 1px var(--border-color);
   border-bottom: none;
@@ -88,13 +110,12 @@
 .spell-list {
   border: solid 1px var(--border-color);
   height: 22rem;
-  // background: white;
   background-image: url("/assets/images/texture.png");
   border-radius: 0 10px 10px 10px;
   display: flex;
   flex-direction: row;
   align-items: center;
-  gap: 1rem;
+  gap: 1.125rem;
   padding: 0 1rem;
   overflow-x: auto;
   overflow-y: hidden;

+ 33 - 3
src/app/journal/journal-spellcards/journal-spellcards.component.ts

@@ -8,10 +8,9 @@ import { Spell } from 'src/interfaces/spell';
 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 { FullSpellcardComponent } from 'src/app/shared-components/full-spellcard/full-spellcard.component';
-// import { CustomSpellsModalComponent } from '../journal-spellbook/custom-spells-modal/custom-spells-modal.component';
-
+import { Router } from '@angular/router';
+import { FavoriteSpellsModalComponent } from '../journal-stats/weapons-container/spell-table/favorite-spells-modal/favorite-spells-modal.component';
 @Component({
   selector: 'app-journal-spellcards',
   templateUrl: './journal-spellcards.component.html',
@@ -48,6 +47,7 @@ export class JournalSpellcardsComponent {
     private dataAccessor: DataService,
     private modalAccessor: ModalService,
     public spellsService: SpellsService,
+    private router: Router,
   ) {
     this.loadSpells();
     this.hideEmptySpelllists();
@@ -373,4 +373,34 @@ export class JournalSpellcardsComponent {
         break;
     }
   }
+
+  public navigateToSpellbook(): void {
+    this.router.navigate(['journal/spellbook']);
+  }
+
+  public openFavoritesModal(): void {
+    this.modalAccessor.openModal(FavoriteSpellsModalComponent, {
+      preparedSpells: [
+        ...this.level0,
+        ...this.level1,
+        ...this.level2,
+        ...this.level3,
+        ...this.level4,
+        ...this.level5,
+        ...this.level6,
+        ...this.level7,
+        ...this.level8,
+        ...this.level9,
+      ],
+      selectedSpells: this.dataAccessor.favoriteSpells,
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update') {
+          this.dataAccessor.favoriteSpells = result.data;
+        }
+        resultSubscription.unsubscribe();
+      },
+    );
+  }
 }

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

@@ -94,6 +94,7 @@ import { MatRippleModule } from '@angular/material/core';
 import { CustomSpellsModalComponent } from './journal-spellbook/custom-spells-modal/custom-spells-modal.component';
 import { DurationPipe } from '../../pipes/duration/duration.pipe';
 import { CombinedComponent } from './journal-character/combined/combined.component';
+import { DividerComponent } from '../shared-components/divider/divider.component';
 
 @NgModule({
   declarations: [
@@ -193,6 +194,7 @@ import { CombinedComponent } from './journal-character/combined/combined.compone
     MatRadioModule,
     MatDividerModule,
     DurationPipe,
+    DividerComponent,
   ],
 })
 export class JournalModule {}

+ 1 - 0
src/app/shared-components/divider/divider.component.html

@@ -0,0 +1 @@
+<div></div>

+ 5 - 0
src/app/shared-components/divider/divider.component.scss

@@ -0,0 +1,5 @@
+div {
+  border-top: 2px solid #9b8559;
+  height: 1px;
+  width: 100%;
+}

+ 23 - 0
src/app/shared-components/divider/divider.component.spec.ts

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

+ 11 - 0
src/app/shared-components/divider/divider.component.ts

@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+@Component({
+  selector: 'divider',
+  standalone: true,
+  imports: [CommonModule],
+  templateUrl: './divider.component.html',
+  styleUrl: './divider.component.scss',
+})
+export class DividerComponent {}

+ 22 - 7
src/assets/i18n/de.json

@@ -723,13 +723,14 @@
   "spellcards": {
     "cantrips": "Zaubertricks",
     "delete": "Zum Löschen hier ablegen",
+    "favorites": "Favoriten bearbeiten",
+    "spellbook": "Zauberbuch öffnen",
+    "prepared": "Vorbereitete Zauber",
     "add": {
-      "official": "Offizieller Zauber",
-      "custom": "Eigener Zauber",
-      "edit": "Offizieller Zauber bearbeiten",
-      "lookup": "Zauber durchsuchen",
       "empty": "Keine Zauber gefunden",
-      "cancel": "Abbrechen"
+      "class": "Klasse",
+      "all": "Alle",
+      "search": "Durchsuchen"
     }
   },
   "spellmodal": {
@@ -799,7 +800,21 @@
     "manage": "Eigene Zauber verwalten",
     "add": "Neuen Zauber erstellen",
     "noSpells": "Für diesen Filter gibt es keine Zauber",
-    "delete": "Ausgewählte Zauber löschen"
+    "delete": "Ausgewählte Zauber löschen",
+    "favorites": {
+      "levels": {
+        "0": "Zaubertrick",
+        "1": "1. Grad",
+        "2": "2. Grad",
+        "3": "3. Grad",
+        "4": "4. Grad",
+        "5": "5. Grad",
+        "6": "6. Grad",
+        "7": "7. Grad",
+        "8": "8. Grad",
+        "9": "9. Grad"
+      }
+    }
   },
 
   "creator": {
@@ -817,7 +832,7 @@
     "hint": "Die App befindet sich immer noch in einem Entwicklungsstadium und es können Fehler auftreten",
     "issues": "<p>Fehler und Anmerkungen bitte auf dem <a href='https://gogs.koljastrohm-games.com/Warafear/DNDTools/issues'>Git-Server in Issues</a> vermerken.<p>",
     "okay": "Verstanden",
-    "version": "0.11.0",
+    "version": "0.11.1",
     "test": "Test"
   }
 }

+ 22 - 7
src/assets/i18n/en.json

@@ -719,13 +719,14 @@
     "manage": "Manage Custom Spells",
     "cantrips": "Cantrips",
     "delete": "Drop here to delete",
+    "favorites": "Edit Favorites",
+    "spellbook": "Open Spellbook",
+    "prepared": "Prepared Spells",
     "add": {
-      "official": "Official Spells",
-      "custom": "Custom Spells",
-      "edit": "Edit Official Spells",
-      "lookup": "Search Spells",
       "empty": "No spells found",
-      "cancel": "Cancel"
+      "class": "Class",
+      "all": "All",
+      "search": "Search"
     }
   },
   "spellmodal": {
@@ -794,7 +795,21 @@
     "manage": "Manage custom spells",
     "add": "Create new spell",
     "noSpells": "No spells found for this filter",
-    "delete": "Delete selected spells"
+    "delete": "Delete selected spells",
+    "favorites": {
+      "levels": {
+        "0": "Cantrip",
+        "1": "1st Level",
+        "2": "2nd Level",
+        "3": "3rd Level",
+        "4": "4th Level",
+        "5": "5th Level",
+        "6": "6th Level",
+        "7": "7th Level",
+        "8": "8th Level",
+        "9": "9th Level"
+      }
+    }
   },
   "creator": {
     "new": "Create New Character",
@@ -811,7 +826,7 @@
     "hint": "The app is still in a development stage and errors may occur",
     "issues": "<p>Please note errors and comments on the <a href='https://gogs.koljastrohm-games.com/Warafear/DNDTools/issues'>Git server in Issues</a>.<p>",
     "okay": "Understood",
-    "version": "0.11.0",
+    "version": "0.11.1",
     "test": "Test"
   }
 }

+ 1 - 0
src/assets/icons/UIIcons/book.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M260-320q47 0 91.5 10.5T440-278v-394q-41-24-87-36t-93-12q-36 0-71.5 7T120-692v396q35-12 69.5-18t70.5-6Zm260 42q44-21 88.5-31.5T700-320q36 0 70.5 6t69.5 18v-396q-33-14-68.5-21t-71.5-7q-47 0-93 12t-87 36v394Zm-40 118q-48-38-104-59t-116-21q-42 0-82.5 11T100-198q-21 11-40.5-1T40-234v-482q0-11 5.5-21T62-752q46-24 96-36t102-12q58 0 113.5 15T480-740q51-30 106.5-45T700-800q52 0 102 12t96 36q11 5 16.5 15t5.5 21v482q0 23-19.5 35t-40.5 1q-37-20-77.5-31T700-240q-60 0-116 21t-104 59ZM280-494Z"/></svg>

+ 1 - 0
src/assets/icons/UIIcons/favorites.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m480-120-58-52q-101-91-167-157T150-447.5Q111-500 95.5-544T80-634q0-94 63-157t157-63q52 0 99 22t81 62q34-40 81-62t99-22q94 0 157 63t63 157q0 46-15.5 90T810-447.5Q771-395 705-329T538-172l-58 52Zm0-108q96-86 158-147.5t98-107q36-45.5 50-81t14-70.5q0-60-40-100t-100-40q-47 0-87 26.5T518-680h-76q-15-41-55-67.5T300-774q-60 0-100 40t-40 100q0 35 14 70.5t50 81q36 45.5 98 107T480-228Zm0-273Z"/></svg>

+ 1 - 0
src/colors.scss

@@ -55,6 +55,7 @@
   --background-color: #fff2e9;
   --field-background-color: #efc8af;
   --border-color: #8d8c8c;
+  --border-brown: #9b8559;
 
   --modal-background: antiquewhite;
   --header: #ffdec6;