From 4aa8cd56642be2af5c3a1c6aa33c6388fbcbd04b Mon Sep 17 00:00:00 2001 From: Kyle Kemp Date: Tue, 6 Aug 2024 13:59:05 -0500 Subject: [PATCH] add base editor component, stat input, item swap utilities --- angular.json | 1 + package-lock.json | 38 ++++ package.json | 1 + src/app/helpers/constants.ts | 25 ++- src/app/home/home.module.ts | 10 + .../editor-base/editor-base.component.html | 0 .../editor-base/editor-base.component.scss | 0 .../editor-base/editor-base.component.ts | 35 ++++ .../input-itemclass.component.html | 5 +- .../input-itemclass.component.ts | 3 +- .../input-stat/input-stat.component.html | 6 + .../input-stat/input-stat.component.scss | 0 .../input-stat/input-stat.component.ts | 18 ++ src/app/shared/shared.module.ts | 6 + .../items-editor/items-editor.component.html | 88 ++++++++- .../items-editor/items-editor.component.ts | 179 ++++++++++++++++-- src/app/tabs/items/items.component.ts | 6 + src/interfaces/building-blocks.ts | 2 + src/interfaces/item.ts | 2 +- src/styles.scss | 5 + 20 files changed, 392 insertions(+), 38 deletions(-) create mode 100644 src/app/shared/components/editor-base/editor-base.component.html create mode 100644 src/app/shared/components/editor-base/editor-base.component.scss create mode 100644 src/app/shared/components/editor-base/editor-base.component.ts create mode 100644 src/app/shared/components/input-stat/input-stat.component.html create mode 100644 src/app/shared/components/input-stat/input-stat.component.scss create mode 100644 src/app/shared/components/input-stat/input-stat.component.ts diff --git a/angular.json b/angular.json index 55886fb..f46fad7 100644 --- a/angular.json +++ b/angular.json @@ -34,6 +34,7 @@ "inlineStyleLanguage": "scss", "assets": ["src/favicon.ico", "src/assets"], "styles": [ + "node_modules/ngx-float-ui/css/theme-dark.css", "node_modules/@ng-select/ng-select/themes/default.theme.css", "node_modules/@ngxpert/hot-toast/src/styles/styles.scss", "node_modules/@sweetalert2/theme-dark/dark.scss", diff --git a/package-lock.json b/package-lock.json index 4d8a732..6fbdc3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@sweetalert2/theme-dark": "5.0.17", "ag-grid-angular": "32.0.2", "lodash": "4.17.21", + "ngx-float-ui": "18.0.1", "ngx-webstorage": "18.0.0", "rxjs": "7.8.1", "tslib": "2.6.2", @@ -4030,6 +4031,28 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.6.tgz", + "integrity": "sha512-Vkvsw6EcpMHjvZZdMkSY+djMGFbt7CRssW99Ne8tar2WLnZ/l3dbxeTShbLQj+/s35h+Qb4cmnob+EzwtjrXGQ==", + "dependencies": { + "@floating-ui/utils": "^0.2.6" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.9.tgz", + "integrity": "sha512-zB1PcI350t4tkm3rvUhSRKa9sT7vH5CrAbQxW+VaPYJXKAO0gsg4CTueL+6Ajp7XzAQC8CW4Jj1Wgqc0sB6oUQ==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.6" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.6.tgz", + "integrity": "sha512-0KI3zGxIUs1KDR/pjQPdJH4Z8nGBm0yJ5WRoRfdw1Kzeh45jkIfA0rmD0kBF6fKHH+xaH7g8y4jIXyAV5MGK3g==" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -19505,6 +19528,21 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/ngx-float-ui": { + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/ngx-float-ui/-/ngx-float-ui-18.0.1.tgz", + "integrity": "sha512-yBkmxkO0ixeDcJ4Mj3JdaBGO7cpXbjl6LrMwPp8L+ZOHdAYJl4rnCE6PaiWcLQJKD1qOsZcakJAfac+G5CPiVg==", + "hasInstallScript": true, + "dependencies": { + "@floating-ui/dom": "^1.6.6", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^18.0.0", + "@angular/core": "^18.0.0", + "rxjs": "^7.4.0" + } + }, "node_modules/ngx-webstorage": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/ngx-webstorage/-/ngx-webstorage-18.0.0.tgz", diff --git a/package.json b/package.json index ab27365..6b73b0c 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@sweetalert2/theme-dark": "5.0.17", "ag-grid-angular": "32.0.2", "lodash": "4.17.21", + "ngx-float-ui": "18.0.1", "ngx-webstorage": "18.0.0", "rxjs": "7.8.1", "tslib": "2.6.2", diff --git a/src/app/helpers/constants.ts b/src/app/helpers/constants.ts index 35fd9de..1da2c4e 100644 --- a/src/app/helpers/constants.ts +++ b/src/app/helpers/constants.ts @@ -1,4 +1,5 @@ import { sortBy } from 'lodash'; +import { StatBlock } from '../../interfaces'; export const coreStats = sortBy( [ @@ -257,7 +258,7 @@ export const itemTypes = [ 'Wand', ]; -export const typePropSets: Record = { +export const typePropSets: Record = { Arrow: ['shots', 'tier', 'damageClass'], Bottle: ['ounces'], Box: ['containedItems'], @@ -266,9 +267,13 @@ export const typePropSets: Record = { Book: ['bookPages', 'bookItemFilter', 'bookFindablePages'], Trap: ['trapUses'], Scroll: ['bookPage'], + Twig: ['type'], }; -export const typePropDefaults: Record = { +export const typePropDefaults: Record< + string, + Record> +> = { Arrow: { shots: 1000, tier: 1, damageClass: 'physical' }, Bottle: { ounces: 1 }, Food: { ounces: 1 }, @@ -278,7 +283,10 @@ export const typePropDefaults: Record = { Twig: { type: 'Staff' }, }; -const typePropPrimarySecondary: Record = { +export const typePropPrimarySecondary: Record< + string, + { p: string; s?: string } +> = { Axe: { p: 'Axe' }, Blunderbuss: { p: 'Ranged', s: 'Twohanded' }, Broadsword: { p: 'Sword' }, @@ -359,8 +367,9 @@ weaponClasses.forEach((weaponType) => { } if (['Shield', 'Saucer'].includes(weaponType)) { - typePropDefaults[weaponType].stats.accuracy = 0; - typePropDefaults[weaponType].stats.mitigation = 5; + typePropSets[weaponType].push('stats'); + (typePropDefaults[weaponType].stats as Partial).accuracy = 0; + (typePropDefaults[weaponType].stats as Partial).mitigation = 5; typePropDefaults[weaponType].tier = 1; } @@ -428,11 +437,13 @@ armorClasses.forEach((armorType) => { } if (['Tunic', 'Fur', 'Scaleplate'].includes(armorType)) { - typePropDefaults[armorType].stats.mitigation = 10; + typePropSets[armorType].push('stats'); + (typePropDefaults[armorType].stats as Partial).mitigation = 10; } if (['Fullplate', 'Breastplate'].includes(armorType)) { - typePropDefaults[armorType].stats.mitigation = 25; + typePropSets[armorType].push('stats'); + (typePropDefaults[armorType].stats as Partial).mitigation = 25; typePropDefaults[armorType].isHeavy = true; } diff --git a/src/app/home/home.module.ts b/src/app/home/home.module.ts index 0be560b..06dabc8 100644 --- a/src/app/home/home.module.ts +++ b/src/app/home/home.module.ts @@ -5,6 +5,11 @@ import { HomeRoutingModule } from './home-routing.module'; import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2'; import { AgGridModule } from 'ag-grid-angular'; +import { + NgxFloatUiModule, + NgxFloatUiPlacements, + NgxFloatUiTriggers, +} from 'ngx-float-ui'; import { SharedModule } from '../shared/shared.module'; import { DialogsComponent } from '../tabs/dialogs/dialogs.component'; import { DroptablesComponent } from '../tabs/droptables/droptables.component'; @@ -36,6 +41,11 @@ import { HomeComponent } from './home.component'; HomeRoutingModule, SweetAlert2Module, AgGridModule, + NgxFloatUiModule.forRoot({ + trigger: NgxFloatUiTriggers.hover, + showDelay: 500, + placement: NgxFloatUiPlacements.TOPEND, + }), ], }) export class HomeModule {} diff --git a/src/app/shared/components/editor-base/editor-base.component.html b/src/app/shared/components/editor-base/editor-base.component.html new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/components/editor-base/editor-base.component.scss b/src/app/shared/components/editor-base/editor-base.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/components/editor-base/editor-base.component.ts b/src/app/shared/components/editor-base/editor-base.component.ts new file mode 100644 index 0000000..6da30f5 --- /dev/null +++ b/src/app/shared/components/editor-base/editor-base.component.ts @@ -0,0 +1,35 @@ +import { Component, model, output, signal } from '@angular/core'; + +type Tab = { name: string }; + +@Component({ + selector: 'app-editor-base', + templateUrl: './editor-base.component.html', + styleUrl: './editor-base.component.scss', +}) +export class EditorBaseComponent { + public readonly tabs: Tab[] = []; + + public activeTab = signal(0); + + public editing = model.required(); + + public goBack = output(); + public save = output(); + + public changeTab(tab: number) { + this.activeTab.set(tab); + } + + public update(key: keyof T, value: any) { + this.editing.update((editing) => ({ ...editing, [key]: value })); + } + + doBack() { + this.goBack.emit(); + } + + doSave() { + this.save.emit(this.editing()); + } +} diff --git a/src/app/shared/components/input-itemclass/input-itemclass.component.html b/src/app/shared/components/input-itemclass/input-itemclass.component.html index cb2b827..91e5bc8 100644 --- a/src/app/shared/components/input-itemclass/input-itemclass.component.html +++ b/src/app/shared/components/input-itemclass/input-itemclass.component.html @@ -1,6 +1,7 @@
- + {{ label() }}
diff --git a/src/app/shared/components/input-itemclass/input-itemclass.component.ts b/src/app/shared/components/input-itemclass/input-itemclass.component.ts index 622bd2e..6612309 100644 --- a/src/app/shared/components/input-itemclass/input-itemclass.component.ts +++ b/src/app/shared/components/input-itemclass/input-itemclass.component.ts @@ -1,4 +1,4 @@ -import { Component, input, model } from '@angular/core'; +import { Component, input, model, output } from '@angular/core'; import { ArmorClass, ItemClassType, @@ -14,6 +14,7 @@ import { export class InputItemclassComponent { public itemClass = model.required(); public label = input('Type'); + public change = output(); public values = [ ...Object.values(WeaponClass).map((c) => ({ diff --git a/src/app/shared/components/input-stat/input-stat.component.html b/src/app/shared/components/input-stat/input-stat.component.html new file mode 100644 index 0000000..23c991d --- /dev/null +++ b/src/app/shared/components/input-stat/input-stat.component.html @@ -0,0 +1,6 @@ +
+ + + Stat +
diff --git a/src/app/shared/components/input-stat/input-stat.component.scss b/src/app/shared/components/input-stat/input-stat.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/components/input-stat/input-stat.component.ts b/src/app/shared/components/input-stat/input-stat.component.ts new file mode 100644 index 0000000..aa508c3 --- /dev/null +++ b/src/app/shared/components/input-stat/input-stat.component.ts @@ -0,0 +1,18 @@ +import { Component, model, output } from '@angular/core'; +import { ItemClassType, StatType } from '../../../../interfaces'; +import { coreStats, extraStats } from '../../../helpers'; + +@Component({ + selector: 'app-input-stat', + templateUrl: './input-stat.component.html', + styleUrl: './input-stat.component.scss', +}) +export class InputStatComponent { + public stat = model.required(); + public change = output(); + + public values = [ + ...coreStats.map((x) => x.stat), + ...extraStats.map((x) => x.stat), + ]; +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index cf71bb0..2b9430f 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -14,6 +14,8 @@ import { InputSpriteComponent } from './components/input-sprite/input-sprite.com import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component'; import { SpriteComponent } from './components/sprite/sprite.component'; import { WebviewDirective } from './directives/'; +import { InputStatComponent } from './components/input-stat/input-stat.component'; +import { EditorBaseComponent } from './components/editor-base/editor-base.component'; @NgModule({ declarations: [ @@ -27,6 +29,8 @@ import { WebviewDirective } from './directives/'; CellButtonsComponent, CellSpriteComponent, HeaderButtonsComponent, + InputStatComponent, + EditorBaseComponent, ], imports: [CommonModule, FormsModule, NgSelectModule, SweetAlert2Module], exports: [ @@ -40,6 +44,8 @@ import { WebviewDirective } from './directives/'; CellButtonsComponent, CellSpriteComponent, HeaderButtonsComponent, + InputStatComponent, + EditorBaseComponent, ], }) export class SharedModule {} diff --git a/src/app/tabs/items/items-editor/items-editor.component.html b/src/app/tabs/items/items-editor/items-editor.component.html index f733b6d..49ba1e6 100644 --- a/src/app/tabs/items/items-editor/items-editor.component.html +++ b/src/app/tabs/items/items-editor/items-editor.component.html @@ -17,7 +17,7 @@ @switch (activeTab()) { @case (0) { -
+
@@ -30,8 +30,8 @@
- +
@@ -82,7 +82,7 @@
-