From c0288ee445be094fefc15690edadc81e1f9f5b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 09:58:50 +0100 Subject: [PATCH 01/13] Implement ScriptAccount in Model --- .../scriptAccounts/ScriptAccountTest.spec.ts | 73 +++++++++++++++++++ src/app/game-model/GameModel.ts | 21 ++++++ src/app/game-model/ModelComponent.ts | 14 ++++ src/app/game-model/ModelComponentType.ts | 3 + .../scriptAccounts/ScriptAccount.ts | 10 +++ 5 files changed, 121 insertions(+) create mode 100644 e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts create mode 100644 src/app/game-model/ModelComponent.ts create mode 100644 src/app/game-model/ModelComponentType.ts create mode 100644 src/app/game-model/scriptAccounts/ScriptAccount.ts diff --git a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts new file mode 100644 index 0000000..a9048e3 --- /dev/null +++ b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts @@ -0,0 +1,73 @@ +import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright'; +import { test, expect } from '@playwright/test'; +import * as PATH from 'path'; +import {GameModel} from "../../../src/app/game-model/GameModel"; +import {Gamesystem} from "../../src/app/game-model/gamesystems/Gamesystem"; +import {ScriptAccount} from "../../../src/app/game-model/scriptAccounts/ScriptAccount"; +import {ModelComponentType} from "../../../src/app/game-model/ModelComponentType"; + +test.describe('Test ScriptAccounts', () => { + + test("Test ScriptAccount Creation", async () => { + const scriptAccunt = new ScriptAccount("ScriptAccount", "Description"); + + expect(scriptAccunt.componentName).toEqual("ScriptAccount"); + expect(scriptAccunt.componentDescription).toEqual("Description"); + expect(scriptAccunt.type).toEqual(ModelComponentType.SCRIPTACCOUNT); + expect(scriptAccunt.minValue).toEqual(0); + expect(scriptAccunt.maxValue).toEqual(100); + }) + + test("Test Adding ScriptAccounts", async () => { + const gameModel: GameModel = new GameModel("GameModel"); + + const scriptAccount = new ScriptAccount("ScriptAccount", "Description"); + gameModel.addScriptAccount(scriptAccount); + + expect(gameModel.scriptAccounts.length).toEqual(1); + expect(gameModel.scriptAccounts.includes(scriptAccount)).toBeTruthy(); + + //Test for duplicates + gameModel.addScriptAccount(scriptAccount); + expect(gameModel.scriptAccounts.length).toEqual(1); + + //Test for adding null value + gameModel.addScriptAccount(null); + expect(gameModel.scriptAccounts.length).toEqual(1); + gameModel.addScriptAccount(undefined); + expect(gameModel.scriptAccounts.length).toEqual(1); + + //Test adding scriptAccount with already existing name + const scriptAccount2 = new ScriptAccount("ScriptAccount", ""); + gameModel.addScriptAccount(scriptAccount2); + expect(gameModel.scriptAccounts.length).toEqual(1); + expect(gameModel.scriptAccounts.includes(scriptAccount2)).toBeFalsy(); + }) + + test("test Removing ScriptAccounts", async () => { + const gameModel: GameModel = new GameModel("GameModel"); + const scriptAccount = new ScriptAccount("ScriptAccount", "Description"); + const scriptAccount2 = new ScriptAccount("ScriptAccount 2", "Description"); + + gameModel.removeScriptAccount(scriptAccount); + expect(gameModel.scriptAccounts.length).toEqual(0); + + gameModel.addScriptAccount(scriptAccount); + gameModel.removeScriptAccount(scriptAccount); + expect(gameModel.scriptAccounts.length).toEqual(0); + + gameModel.removeScriptAccount(undefined); + expect(gameModel.scriptAccounts.length).toEqual(0); + + gameModel.removeScriptAccount(null); + expect(gameModel.scriptAccounts.length).toEqual(0); + + gameModel.addScriptAccount(scriptAccount); + gameModel.addScriptAccount(scriptAccount2); + + gameModel.removeScriptAccount(scriptAccount); + expect(gameModel.scriptAccounts.length).toEqual(1); + expect(gameModel.scriptAccounts.includes(scriptAccount2)).toBeTruthy(); + }) + +}); diff --git a/src/app/game-model/GameModel.ts b/src/app/game-model/GameModel.ts index 8bc7dbf..b27a223 100644 --- a/src/app/game-model/GameModel.ts +++ b/src/app/game-model/GameModel.ts @@ -1,9 +1,11 @@ import {Gamesystem} from "./gamesystems/Gamesystem"; +import {ScriptAccount} from "./scriptAccounts/ScriptAccount"; export class GameModel { private readonly _gameModelName: string private _gamesystems: Gamesystem[] = []; + private _scriptAccounts: ScriptAccount[] = []; constructor(gameModelName: string) { this._gameModelName = gameModelName; @@ -16,6 +18,9 @@ export class GameModel { get gamesystems(): Gamesystem[] { return this._gamesystems; } + get scriptAccounts(): ScriptAccount[] { + return this._scriptAccounts; + } addGamesystem(gamesystem: Gamesystem) { if(!this.gamesystems.includes(gamesystem)) { @@ -26,4 +31,20 @@ export class GameModel { removeGamesystem(gamesystem : Gamesystem) { this._gamesystems = this._gamesystems.filter(g => g !== gamesystem); } + + addScriptAccount(scriptAccount: ScriptAccount) { + if(scriptAccount != undefined && !this.scriptAccounts.includes(scriptAccount)) { + const searchedScriptAccount = this.scriptAccounts.find(s => s.componentName === scriptAccount.componentName); + if(searchedScriptAccount == undefined) { + this.scriptAccounts.push(scriptAccount); + } + } + } + + removeScriptAccount(scriptAccount: ScriptAccount) { + if(scriptAccount != undefined) { + this._scriptAccounts = this.scriptAccounts.filter(s => s != scriptAccount); + } + } + } diff --git a/src/app/game-model/ModelComponent.ts b/src/app/game-model/ModelComponent.ts new file mode 100644 index 0000000..5052ad3 --- /dev/null +++ b/src/app/game-model/ModelComponent.ts @@ -0,0 +1,14 @@ +import {ModelComponentType} from "./ModelComponentType"; + +export abstract class ModelComponent { + componentName: string + componentDescription: string + type: ModelComponentType + constructor(componentName: string, componentDescription: string, type: ModelComponentType) { + this.componentName = componentName; + this.componentDescription = componentDescription; + this.type = type; + } + + +} diff --git a/src/app/game-model/ModelComponentType.ts b/src/app/game-model/ModelComponentType.ts new file mode 100644 index 0000000..a3ceab2 --- /dev/null +++ b/src/app/game-model/ModelComponentType.ts @@ -0,0 +1,3 @@ +export enum ModelComponentType { + SCRIPTACCOUNT +} diff --git a/src/app/game-model/scriptAccounts/ScriptAccount.ts b/src/app/game-model/scriptAccounts/ScriptAccount.ts new file mode 100644 index 0000000..6de4790 --- /dev/null +++ b/src/app/game-model/scriptAccounts/ScriptAccount.ts @@ -0,0 +1,10 @@ +import {ModelComponent} from "../ModelComponent"; +import {ModelComponentType} from "../ModelComponentType"; + +export class ScriptAccount extends ModelComponent{ + minValue: number = 0; + maxValue: number = 100; + constructor(componentName: string, componentDescription: string) { + super(componentName, componentDescription, ModelComponentType.SCRIPTACCOUNT); + } +} From 9505f5a0a436b9dc90dca03704850bec8d00584b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 10:34:41 +0100 Subject: [PATCH 02/13] Implement menu container and mat-drawer for visualizing scriptaccount overview --- angular.json | 4 +- src/app/app.component.css | 102 +++++++++++++++++- src/app/app.component.html | 33 +++++- src/app/app.component.ts | 27 ++++- src/app/app.module.ts | 18 +++- src/app/game-model/ModelComponentType.ts | 2 + .../ModelComponentTypeUtillities.ts | 10 ++ src/styles.scss | 50 --------- 8 files changed, 188 insertions(+), 58 deletions(-) create mode 100644 src/app/game-model/ModelComponentTypeUtillities.ts delete mode 100644 src/styles.scss diff --git a/angular.json b/angular.json index a750f75..d7425fa 100644 --- a/angular.json +++ b/angular.json @@ -30,13 +30,13 @@ "main": "src/main.ts", "tsConfig": "src/tsconfig.app.json", "polyfills": "src/polyfills.ts", - "inlineStyleLanguage": "scss", + "inlineStyleLanguage": "css", "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ - "src/styles.scss" + "src/styles.css" ], "scripts": [], "customWebpackConfig": { diff --git a/src/app/app.component.css b/src/app/app.component.css index 6920c8c..d830d21 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -1,3 +1,103 @@ -.background { +.full-height-container { + height: 99vh; + background-color: #2b2d30; + width: 40px; + + border-right: #b9b9b9; + border-right-style: solid; + border-right-width: 1px; +} + +.small-icon-button { + width: 28px !important; + height: 28px !important; + padding: 0px !important; + display: inline-flex !important; + align-items: center; + justify-content: center; + margin-left: 5px; + margin-bottom: 10px; + + & > *[role=img] { + width: 20px; + height: 20px; + font-size: 20px; + + svg { + width: 20px; + height: 20px; + } + } + + .mat-mdc-button-touch-target { + width: 24px !important; + height: 24px !important; + } +} + +.small-icon-button mat-icon { + color: whitesmoke; +} + +.selected { + background-color: #4e5157; +} + +.example-container { + width: 100%; + height: 100vh; +} + +.example-sidenav-content { + display: flex; + height: 100%; +} + +.example-sidenav { + +} + +.container { + padding: 0; + display: flex; +} + +/* Adjust the vertical alignment of the icon within the button */ +.mat-button-wrapper { + display: flex; + flex-direction: row; + align-items: center; + border: none; + border-radius: 5px; + padding-right: 12px; +} + +.sidenav-header { + width: 100%; + display: flex; + justify-content: space-between; +} + +.close-sidenav-btn { + margin-top: 5px; + display: none; +} + +.sidenav-header:hover + .close-sidenav-btn { + display: block; color: red; } + +app-editor { + width: 100%; +} + +.example-form { + min-width: 150px; + max-width: 500px; + width: 100%; +} + +.example-full-width { + width: 100%; +} diff --git a/src/app/app.component.html b/src/app/app.component.html index 460cc78..7de60ed 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1 +1,32 @@ -add +
+
+ +
+ + + + +
+ + + + + + + + +
+
+ +
+ +
+ +
+ +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f7b3ba7..a98b573 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,9 @@ -import { Component } from '@angular/core'; -import { ElectronService } from './core/services'; -import { APP_CONFIG } from '../environments/environment'; +import {Component, ViewChild} from '@angular/core'; +import {ElectronService} from './core/services'; +import {APP_CONFIG} from '../environments/environment'; +import {ModelComponentType} from "./game-model/ModelComponentType"; +import {MatDrawerContainer} from "@angular/material/sidenav"; +import {ModelComponentTypeUtillities} from "./game-model/ModelComponentTypeUtillities"; @Component({ selector: 'app-root', @@ -8,6 +11,10 @@ import { APP_CONFIG } from '../environments/environment'; styleUrls: ['./app.component.css'] }) export class AppComponent { + + openContent : ModelComponentType | undefined = undefined; + @ViewChild('drawer') drawer: MatDrawerContainer|undefined + constructor( private electronService: ElectronService, ) { @@ -22,4 +29,18 @@ export class AppComponent { console.log('Run in browser'); } } + + openScriptAccountsOverview() { + this.openContent = ModelComponentType.SCRIPTACCOUNT + this.drawer!.open(); + } + + protected readonly ModelComponentType = ModelComponentType; + + closeContentOverview() { + this.drawer!.close(); + this.openContent = undefined; + } + + protected readonly ModelComponentTypeUtillities = ModelComponentTypeUtillities; } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2d75f4f..38a12cc 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -12,6 +12,12 @@ import {CoreModule} from "./core/core.module"; import {SharedModule} from "./shared/shared.module"; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import {MatIcon} from "@angular/material/icon"; +import {MatToolbar} from "@angular/material/toolbar"; +import {MatButton, MatIconButton} from "@angular/material/button"; +import {MatFormField} from "@angular/material/form-field"; +import {MatInput} from "@angular/material/input"; +import {MatDrawer, MatDrawerContainer} from "@angular/material/sidenav"; +import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -32,7 +38,17 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl } }), BrowserAnimationsModule, - MatIcon + MatIcon, + MatToolbar, + MatButton, + MatFormField, + MatInput, + MatDrawerContainer, + MatDrawer, + MatIconButton, + MatMenuTrigger, + MatMenu, + MatMenuItem ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/game-model/ModelComponentType.ts b/src/app/game-model/ModelComponentType.ts index a3ceab2..5218558 100644 --- a/src/app/game-model/ModelComponentType.ts +++ b/src/app/game-model/ModelComponentType.ts @@ -1,3 +1,5 @@ export enum ModelComponentType { SCRIPTACCOUNT + + } diff --git a/src/app/game-model/ModelComponentTypeUtillities.ts b/src/app/game-model/ModelComponentTypeUtillities.ts new file mode 100644 index 0000000..772ab30 --- /dev/null +++ b/src/app/game-model/ModelComponentTypeUtillities.ts @@ -0,0 +1,10 @@ +import {ModelComponentType} from "./ModelComponentType"; + +export class ModelComponentTypeUtillities { + static toString(modelComponentType: ModelComponentType | undefined): string { + switch (modelComponentType) { + case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccounts"; + default: return "Undefined"; + } + } +} diff --git a/src/styles.scss b/src/styles.scss deleted file mode 100644 index 4c1c4b2..0000000 --- a/src/styles.scss +++ /dev/null @@ -1,50 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ -html, body { - margin: 0; - padding: 0; - - height: 100%; - font-family: Arial, Helvetica, sans-serif; -} - -/* CAN (MUST) BE REMOVED ! Sample Global style */ -.container { - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - - background: url(./assets/background.jpg) no-repeat center fixed; - -webkit-background-size: cover; /* pour anciens Chrome et Safari */ - background-size: cover; /* version standardisée */ - - .title { - color: white; - margin: 0; - padding: 50px 20px; - } - - a { - color: #fff !important; - text-transform: uppercase; - text-decoration: none; - background: #ed3330; - padding: 20px; - border-radius: 5px; - display: inline-block; - border: none; - transition: all 0.4s ease 0s; - - &:hover { - background: #fff; - color: #ed3330 !important; - letter-spacing: 1px; - -webkit-box-shadow: 0px 5px 40px -10px rgba(0,0,0,0.57); - -moz-box-shadow: 0px 5px 40px -10px rgba(0,0,0,0.57); - box-shadow: 5px 40px -10px rgba(0,0,0,0.57); - transition: all 0.4s ease 0s; - } - } -} - From e9ca3c78c7ec35254afd7584d674b945c981e1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 10:35:18 +0100 Subject: [PATCH 03/13] Use css instead of scss --- src/styles.css | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/styles.css diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..6760b9b --- /dev/null +++ b/src/styles.css @@ -0,0 +1,10 @@ +/* You can add global styles to this file, and also import other style files */ +@import "@angular/material/prebuilt-themes/purple-green.css"; +body { + margin: 0; + padding: 0; + background: #2b2d30; +} + +html, body { height: 100%; margin: 0 } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } From 89fe9e1282ebcdf646476f69cb5f5f49a05d52fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 11:07:40 +0100 Subject: [PATCH 04/13] Basic ScriptAccountOverview and generate Editor Component --- src/app/app.component.html | 5 ++-- src/app/app.component.ts | 14 ++++++++-- src/app/app.module.ts | 15 +++++++++-- src/app/editor/editor.component.html | 1 + src/app/editor/editor.component.scss | 0 src/app/editor/editor.component.spec.ts | 23 ++++++++++++++++ src/app/editor/editor.component.ts | 10 +++++++ .../script-account-overview.component.css | 10 +++++++ .../script-account-overview.component.html | 6 +++++ .../script-account-overview.component.spec.ts | 23 ++++++++++++++++ .../script-account-overview.component.ts | 26 +++++++++++++++++++ src/styles.css | 1 - 12 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 src/app/editor/editor.component.html create mode 100644 src/app/editor/editor.component.scss create mode 100644 src/app/editor/editor.component.spec.ts create mode 100644 src/app/editor/editor.component.ts create mode 100644 src/app/side-overviews/script-account-overview/script-account-overview.component.css create mode 100644 src/app/side-overviews/script-account-overview/script-account-overview.component.html create mode 100644 src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts create mode 100644 src/app/side-overviews/script-account-overview/script-account-overview.component.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 7de60ed..c30a000 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -18,13 +18,12 @@ - - +
- +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a98b573..773847a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,20 +1,24 @@ -import {Component, ViewChild} from '@angular/core'; +import {Component, OnInit, ViewChild} from '@angular/core'; import {ElectronService} from './core/services'; import {APP_CONFIG} from '../environments/environment'; import {ModelComponentType} from "./game-model/ModelComponentType"; import {MatDrawerContainer} from "@angular/material/sidenav"; import {ModelComponentTypeUtillities} from "./game-model/ModelComponentTypeUtillities"; +import {GameModel} from "./game-model/GameModel"; +import {ScriptAccount} from "./game-model/scriptAccounts/ScriptAccount"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) -export class AppComponent { +export class AppComponent implements OnInit{ openContent : ModelComponentType | undefined = undefined; @ViewChild('drawer') drawer: MatDrawerContainer|undefined + gameModel: GameModel | undefined + constructor( private electronService: ElectronService, ) { @@ -30,6 +34,12 @@ export class AppComponent { } } + ngOnInit() { + this.gameModel = new GameModel("No More"); + this.gameModel.addScriptAccount(new ScriptAccount("Temperature", "")); + this.gameModel.addScriptAccount(new ScriptAccount("Luftfeuchtigkeit", "")); + } + openScriptAccountsOverview() { this.openContent = ModelComponentType.SCRIPTACCOUNT this.drawer!.open(); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 38a12cc..ff18a2f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -18,12 +18,21 @@ import {MatFormField} from "@angular/material/form-field"; import {MatInput} from "@angular/material/input"; import {MatDrawer, MatDrawerContainer} from "@angular/material/sidenav"; import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu"; +import { + ScriptAccountOverviewComponent +} from "./side-overviews/script-account-overview/script-account-overview.component"; +import {MatActionList, MatListItem} from "@angular/material/list"; +import {EditorComponent} from "./editor/editor.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @NgModule({ - declarations: [AppComponent], + declarations: [ + AppComponent, + ScriptAccountOverviewComponent, + EditorComponent + ], imports: [ BrowserModule, FormsModule, @@ -48,7 +57,9 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatIconButton, MatMenuTrigger, MatMenu, - MatMenuItem + MatMenuItem, + MatListItem, + MatActionList, ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html new file mode 100644 index 0000000..2899fdc --- /dev/null +++ b/src/app/editor/editor.component.html @@ -0,0 +1 @@ +

editor works!

diff --git a/src/app/editor/editor.component.scss b/src/app/editor/editor.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/editor/editor.component.spec.ts b/src/app/editor/editor.component.spec.ts new file mode 100644 index 0000000..fa7b8e3 --- /dev/null +++ b/src/app/editor/editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditorComponent } from './editor.component'; + +describe('EditorComponent', () => { + let component: EditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [EditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(EditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts new file mode 100644 index 0000000..7b48f3e --- /dev/null +++ b/src/app/editor/editor.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-editor', + templateUrl: './editor.component.html', + styleUrl: './editor.component.scss' +}) +export class EditorComponent { + +} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.css b/src/app/side-overviews/script-account-overview/script-account-overview.component.css new file mode 100644 index 0000000..0a8651a --- /dev/null +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.css @@ -0,0 +1,10 @@ +.scriptAccount-item { + min-height: 1.8em !important; + height: 1.8em !important; +} + +.scriptAccount-icon { + margin-right: 10px; + color: #ccffff; + align-content: baseline; +} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.html b/src/app/side-overviews/script-account-overview/script-account-overview.component.html new file mode 100644 index 0000000..d35d531 --- /dev/null +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.html @@ -0,0 +1,6 @@ + + + inventory_2{{scriptAccount.componentName}} + + diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts new file mode 100644 index 0000000..979d4b2 --- /dev/null +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScriptAccountOverviewComponent } from './script-account-overview.component'; + +describe('ScriptAccountOverviewComponent', () => { + let component: ScriptAccountOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ScriptAccountOverviewComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ScriptAccountOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts new file mode 100644 index 0000000..b5cea39 --- /dev/null +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts @@ -0,0 +1,26 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {GameModel} from "../../game-model/GameModel"; +import {ScriptAccount} from "../../game-model/scriptAccounts/ScriptAccount"; + +@Component({ + selector: 'app-script-account-overview', + templateUrl: './script-account-overview.component.html', + styleUrl: './script-account-overview.component.css' +}) +export class ScriptAccountOverviewComponent { + @Input("gameModel") gameModel: GameModel | undefined + @Output("onOpenScriptAccount") openScriptAccountEmitter: EventEmitter = new EventEmitter(); + + onOpenScriptAccount(scriptAccount: ScriptAccount) { + console.log("onOpenScriptAccount (overview)") + this.openScriptAccountEmitter.emit(scriptAccount); + } + + onCreateNewScriptAccount() { + const scriptAccount = new ScriptAccount("New ScriptAccount", ""); + this.gameModel?.addScriptAccount(scriptAccount); + return scriptAccount; + } + + +} diff --git a/src/styles.css b/src/styles.css index 6760b9b..c310536 100644 --- a/src/styles.css +++ b/src/styles.css @@ -3,7 +3,6 @@ body { margin: 0; padding: 0; - background: #2b2d30; } html, body { height: 100%; margin: 0 } From 89e430c17908f3cb10e18de2cdb3065feb972766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 11:25:02 +0100 Subject: [PATCH 05/13] Open and Close ScriptAccounts in Editor --- src/app/app.component.html | 4 +-- src/app/app.component.ts | 12 +++++++ src/app/app.module.ts | 4 +++ src/app/editor/editor.component.html | 10 +++++- src/app/editor/editor.component.spec.ts | 46 ++++++++++++++++++++----- src/app/editor/editor.component.ts | 15 +++++++- 6 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index c30a000..6384677 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -19,11 +19,11 @@ - +
- +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 773847a..e2f110d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -6,6 +6,8 @@ import {MatDrawerContainer} from "@angular/material/sidenav"; import {ModelComponentTypeUtillities} from "./game-model/ModelComponentTypeUtillities"; import {GameModel} from "./game-model/GameModel"; import {ScriptAccount} from "./game-model/scriptAccounts/ScriptAccount"; +import {EditorComponent} from "./editor/editor.component"; +import {ModelComponent} from "./game-model/ModelComponent"; @Component({ selector: 'app-root', @@ -16,6 +18,7 @@ export class AppComponent implements OnInit{ openContent : ModelComponentType | undefined = undefined; @ViewChild('drawer') drawer: MatDrawerContainer|undefined + @ViewChild('editor') editor: EditorComponent|undefined gameModel: GameModel | undefined @@ -53,4 +56,13 @@ export class AppComponent implements OnInit{ } protected readonly ModelComponentTypeUtillities = ModelComponentTypeUtillities; + + openModelComponent(modelComponent: ModelComponent) { + if(this.editor != undefined) { + this.editor.openGameModelComponent(modelComponent); + } else { + console.log("[WARN] [App.Component] Editor is undefined") + } + + } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ff18a2f..5dd8969 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -23,6 +23,7 @@ import { } from "./side-overviews/script-account-overview/script-account-overview.component"; import {MatActionList, MatListItem} from "@angular/material/list"; import {EditorComponent} from "./editor/editor.component"; +import {MatTab, MatTabGroup, MatTabLabel} from "@angular/material/tabs"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -60,6 +61,9 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatMenuItem, MatListItem, MatActionList, + MatTabGroup, + MatTab, + MatTabLabel, ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index 2899fdc..96e17d5 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -1 +1,9 @@ -

editor works!

+ + + + inventory_2 + {{modelComponent.componentName}} + + + + diff --git a/src/app/editor/editor.component.spec.ts b/src/app/editor/editor.component.spec.ts index fa7b8e3..d796501 100644 --- a/src/app/editor/editor.component.spec.ts +++ b/src/app/editor/editor.component.spec.ts @@ -1,23 +1,53 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; import { EditorComponent } from './editor.component'; +import {ScriptAccount} from "../game-model/scriptAccounts/ScriptAccount"; +import {TranslateModule} from "@ngx-translate/core"; +import {RouterTestingModule} from "@angular/router/testing"; describe('EditorComponent', () => { let component: EditorComponent; let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [EditorComponent] - }) - .compileComponents(); - + beforeEach(waitForAsync(() => { + void TestBed.configureTestingModule({ + declarations: [EditorComponent], + imports: [TranslateModule.forRoot(), RouterTestingModule] + }).compileComponents(); + fixture = TestBed.createComponent(EditorComponent); component = fixture.componentInstance; fixture.detectChanges(); - }); + })); it('should create', () => { expect(component).toBeTruthy(); }); + + + it("Test open ScriptAccount", waitForAsync (() => { + const scriptAccount = new ScriptAccount("ScriptAccount", ""); + component.openGameModelComponent(scriptAccount); + + expect(component.gameModelComponents.includes(scriptAccount)); + expect(component.gameModelComponents.length).toEqual(1); + + component.openGameModelComponent(scriptAccount); + expect(component.gameModelComponents.length).toEqual(1); + })); + + it("Test close ScriptAccount", waitForAsync(() => { + const scriptAccount = new ScriptAccount("ScriptAccount", ""); + const scriptAccount2 = new ScriptAccount("ScriptAccount 2", ""); + component.openGameModelComponent(scriptAccount); + + component.closeGameModelComponent(scriptAccount); + expect(component.gameModelComponents.length).toEqual(0); + + component.openGameModelComponent(scriptAccount); + component.openGameModelComponent(scriptAccount2); + component.closeGameModelComponent(scriptAccount); + expect(component.gameModelComponents.length).toEqual(1); + expect(component.gameModelComponents.includes(scriptAccount2)); + })) }); diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts index 7b48f3e..6a18a3c 100644 --- a/src/app/editor/editor.component.ts +++ b/src/app/editor/editor.component.ts @@ -1,4 +1,6 @@ -import { Component } from '@angular/core'; +import {Component, Input} from '@angular/core'; +import {GameModel} from "../game-model/GameModel"; +import {ModelComponent} from "../game-model/ModelComponent"; @Component({ selector: 'app-editor', @@ -6,5 +8,16 @@ import { Component } from '@angular/core'; styleUrl: './editor.component.scss' }) export class EditorComponent { + gameModelComponents: ModelComponent[] = []; + + openGameModelComponent(gameModelComponent: ModelComponent) { + if(!this.gameModelComponents.includes(gameModelComponent)) { + this.gameModelComponents.push(gameModelComponent); + } + } + + closeGameModelComponent(gameModelComponent: ModelComponent) { + this.gameModelComponents = this.gameModelComponents.filter(modelComponent => modelComponent !== gameModelComponent); + } } From 7a490d4c88de2fd2f63bce852a52ee4be5a6d814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 12:08:20 +0100 Subject: [PATCH 06/13] Edit ScriptAccountInformation --- src/app/app.module.ts | 12 +++-- src/app/editor/editor.component.html | 3 ++ src/app/editor/editor.component.spec.ts | 7 +++ src/app/editor/editor.component.ts | 9 ++++ .../script-account-editor.component.html | 13 +++++ .../script-account-editor.component.scss | 7 +++ .../script-account-editor.component.spec.ts | 23 +++++++++ .../script-account-editor.component.ts | 47 +++++++++++++++++++ src/app/game-model/ModelComponent.ts | 2 - 9 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 src/app/editor/script-account-editor/script-account-editor.component.html create mode 100644 src/app/editor/script-account-editor/script-account-editor.component.scss create mode 100644 src/app/editor/script-account-editor/script-account-editor.component.spec.ts create mode 100644 src/app/editor/script-account-editor/script-account-editor.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5dd8969..a8feb65 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,6 +1,6 @@ import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; -import { FormsModule } from '@angular/forms'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import { HttpClientModule, HttpClient } from '@angular/common/http'; // NG Translate @@ -14,7 +14,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import {MatIcon} from "@angular/material/icon"; import {MatToolbar} from "@angular/material/toolbar"; import {MatButton, MatIconButton} from "@angular/material/button"; -import {MatFormField} from "@angular/material/form-field"; +import {MatError, MatFormField, MatLabel} from "@angular/material/form-field"; import {MatInput} from "@angular/material/input"; import {MatDrawer, MatDrawerContainer} from "@angular/material/sidenav"; import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu"; @@ -24,6 +24,7 @@ import { import {MatActionList, MatListItem} from "@angular/material/list"; import {EditorComponent} from "./editor/editor.component"; import {MatTab, MatTabGroup, MatTabLabel} from "@angular/material/tabs"; +import {ScriptAccountEditorComponent} from "./editor/script-account-editor/script-account-editor.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -32,7 +33,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl declarations: [ AppComponent, ScriptAccountOverviewComponent, - EditorComponent + EditorComponent, + ScriptAccountEditorComponent ], imports: [ BrowserModule, @@ -64,6 +66,10 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatTabGroup, MatTab, MatTabLabel, + MatLabel, + MatFormField, + ReactiveFormsModule, + MatError ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index 96e17d5..bd6467f 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -5,5 +5,8 @@ {{modelComponent.componentName}} + + diff --git a/src/app/editor/editor.component.spec.ts b/src/app/editor/editor.component.spec.ts index d796501..33d9525 100644 --- a/src/app/editor/editor.component.spec.ts +++ b/src/app/editor/editor.component.spec.ts @@ -50,4 +50,11 @@ describe('EditorComponent', () => { expect(component.gameModelComponents.length).toEqual(1); expect(component.gameModelComponents.includes(scriptAccount2)); })) + + it("Test convert ModelComponent to ScriptAccount", waitForAsync(() => { + const modelComponent = new ScriptAccount("test", ""); + const scriptAccount = component.convertModelComponentToScriptAccount(modelComponent); + + expect(scriptAccount).toBeInstanceOf(ScriptAccount); + })) }); diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts index 6a18a3c..6b222fe 100644 --- a/src/app/editor/editor.component.ts +++ b/src/app/editor/editor.component.ts @@ -1,6 +1,8 @@ import {Component, Input} from '@angular/core'; import {GameModel} from "../game-model/GameModel"; import {ModelComponent} from "../game-model/ModelComponent"; +import {ModelComponentType} from "../game-model/ModelComponentType"; +import {ScriptAccount} from "../game-model/scriptAccounts/ScriptAccount"; @Component({ selector: 'app-editor', @@ -20,4 +22,11 @@ export class EditorComponent { this.gameModelComponents = this.gameModelComponents.filter(modelComponent => modelComponent !== gameModelComponent); } + convertModelComponentToScriptAccount(modelComponent: ModelComponent) { + if(modelComponent instanceof ScriptAccount) { + return modelComponent as ScriptAccount; + } + } + + protected readonly ModelComponentType = ModelComponentType; } diff --git a/src/app/editor/script-account-editor/script-account-editor.component.html b/src/app/editor/script-account-editor/script-account-editor.component.html new file mode 100644 index 0000000..2b36b86 --- /dev/null +++ b/src/app/editor/script-account-editor/script-account-editor.component.html @@ -0,0 +1,13 @@ +
+ + MinValue + + Please enter a valid number! + + + + MaxValue + + Please enter a valid number! + +
diff --git a/src/app/editor/script-account-editor/script-account-editor.component.scss b/src/app/editor/script-account-editor/script-account-editor.component.scss new file mode 100644 index 0000000..b3a1960 --- /dev/null +++ b/src/app/editor/script-account-editor/script-account-editor.component.scss @@ -0,0 +1,7 @@ +.example-form { + width: 100%; +} + +.example-full-width { + width: 100%; +} diff --git a/src/app/editor/script-account-editor/script-account-editor.component.spec.ts b/src/app/editor/script-account-editor/script-account-editor.component.spec.ts new file mode 100644 index 0000000..076be6c --- /dev/null +++ b/src/app/editor/script-account-editor/script-account-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScriptAccountEditorComponent } from './script-account-editor.component'; + +describe('ScriptAccountEditorComponent', () => { + let component: ScriptAccountEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ScriptAccountEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ScriptAccountEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/script-account-editor/script-account-editor.component.ts b/src/app/editor/script-account-editor/script-account-editor.component.ts new file mode 100644 index 0000000..5e0bf15 --- /dev/null +++ b/src/app/editor/script-account-editor/script-account-editor.component.ts @@ -0,0 +1,47 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {ScriptAccount} from "../../game-model/scriptAccounts/ScriptAccount"; +import {ModelComponent} from "../../game-model/ModelComponent"; +import {MatFormField} from "@angular/material/form-field"; +import {MatInput} from "@angular/material/input"; +import {FormControl, FormGroupDirective, FormsModule, NgForm, Validators} from "@angular/forms"; +import {NgIf} from "@angular/common"; +import {ErrorStateMatcher} from "@angular/material/core"; + +export class MyErrorStateMatcher implements ErrorStateMatcher { + isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const isSubmitted = form && form.submitted; + return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted)); + } +} +@Component({ + selector: 'app-script-account-editor', + templateUrl: './script-account-editor.component.html', + styleUrl: './script-account-editor.component.scss' +}) +export class ScriptAccountEditorComponent implements OnInit{ + @Input("scriptAccount") scriptAccount : ScriptAccount | undefined + + minCtrl: FormControl = new FormControl(0, [Validators.required, Validators.pattern('^[0-9]*$')]); + maxCtrl: FormControl = new FormControl(100, [Validators.required, Validators.pattern('^[0-9]*$')]); + matcher = new MyErrorStateMatcher(); + ngOnInit() { + this.minCtrl.setValue(this.scriptAccount!.minValue); + this.maxCtrl.setValue(this.scriptAccount!.maxValue); + } + + onKeyPress(event: KeyboardEvent) { + const input = event.key; + const isDigit = /^\d+$/.test(input); + if (!isDigit) { + event.preventDefault(); + } + } + + onUpdateMinValue() { + this.scriptAccount!.minValue = Number(this.minCtrl.value); + } + + onUpdateMaxValue() { + this.scriptAccount!.maxValue = Number(this.maxCtrl.value); + } +} diff --git a/src/app/game-model/ModelComponent.ts b/src/app/game-model/ModelComponent.ts index 5052ad3..f1eec26 100644 --- a/src/app/game-model/ModelComponent.ts +++ b/src/app/game-model/ModelComponent.ts @@ -9,6 +9,4 @@ export abstract class ModelComponent { this.componentDescription = componentDescription; this.type = type; } - - } From 7680cd7edda70470a6255c072468eef4f2a2d69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 12:17:43 +0100 Subject: [PATCH 07/13] Edit abstract ModelComponent Information --- src/app/app.module.ts | 7 +++-- src/app/editor/editor.component.html | 1 + .../model-component-editor.component.html | 9 ++++++ .../model-component-editor.component.scss | 3 ++ .../model-component-editor.component.spec.ts | 23 ++++++++++++++ .../model-component-editor.component.ts | 30 +++++++++++++++++++ 6 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/app/editor/model-component-editor/model-component-editor.component.html create mode 100644 src/app/editor/model-component-editor/model-component-editor.component.scss create mode 100644 src/app/editor/model-component-editor/model-component-editor.component.spec.ts create mode 100644 src/app/editor/model-component-editor/model-component-editor.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a8feb65..95f920e 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -25,6 +25,7 @@ import {MatActionList, MatListItem} from "@angular/material/list"; import {EditorComponent} from "./editor/editor.component"; import {MatTab, MatTabGroup, MatTabLabel} from "@angular/material/tabs"; import {ScriptAccountEditorComponent} from "./editor/script-account-editor/script-account-editor.component"; +import {ModelComponentEditorComponent} from "./editor/model-component-editor/model-component-editor.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -34,7 +35,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl AppComponent, ScriptAccountOverviewComponent, EditorComponent, - ScriptAccountEditorComponent + ScriptAccountEditorComponent, + ModelComponentEditorComponent ], imports: [ BrowserModule, @@ -69,7 +71,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatLabel, MatFormField, ReactiveFormsModule, - MatError + MatError, + ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index bd6467f..1c9a6a5 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -5,6 +5,7 @@ {{modelComponent.componentName}} + diff --git a/src/app/editor/model-component-editor/model-component-editor.component.html b/src/app/editor/model-component-editor/model-component-editor.component.html new file mode 100644 index 0000000..a9b59a0 --- /dev/null +++ b/src/app/editor/model-component-editor/model-component-editor.component.html @@ -0,0 +1,9 @@ + + Name + + Please enter a valid number! + + + Description + + diff --git a/src/app/editor/model-component-editor/model-component-editor.component.scss b/src/app/editor/model-component-editor/model-component-editor.component.scss new file mode 100644 index 0000000..4e80027 --- /dev/null +++ b/src/app/editor/model-component-editor/model-component-editor.component.scss @@ -0,0 +1,3 @@ +.long-form { + width: 100%; +} diff --git a/src/app/editor/model-component-editor/model-component-editor.component.spec.ts b/src/app/editor/model-component-editor/model-component-editor.component.spec.ts new file mode 100644 index 0000000..5b6dadf --- /dev/null +++ b/src/app/editor/model-component-editor/model-component-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ModelComponentEditorComponent } from './model-component-editor.component'; + +describe('ModelComponentEditorComponent', () => { + let component: ModelComponentEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ModelComponentEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ModelComponentEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/model-component-editor/model-component-editor.component.ts b/src/app/editor/model-component-editor/model-component-editor.component.ts new file mode 100644 index 0000000..89ab57f --- /dev/null +++ b/src/app/editor/model-component-editor/model-component-editor.component.ts @@ -0,0 +1,30 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {ModelComponent} from "../../game-model/ModelComponent"; +import {FormControl, Validators} from "@angular/forms"; + +@Component({ + selector: 'app-model-component-editor', + templateUrl: './model-component-editor.component.html', + styleUrl: './model-component-editor.component.scss' +}) +export class ModelComponentEditorComponent implements OnInit{ + @Input('modelComponent') modelComponent: ModelComponent | undefined + + nameCtrl: FormControl = new FormControl('', [Validators.required]); + descriptionCtrl: FormControl = new FormControl('' ); + + ngOnInit() { + this.nameCtrl.setValue(this.modelComponent!.componentName); + this.descriptionCtrl.setValue(this.modelComponent!.componentDescription); + } + + onUpdateName() { + this.modelComponent!.componentName = this.nameCtrl.value; + } + + onUpdateDescription() { + this.modelComponent!.componentDescription = this.descriptionCtrl.value; + } + + protected readonly name = name; +} From 35a323e97a904a4ac41d7bffa220a0f1348d27ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 12:41:36 +0100 Subject: [PATCH 08/13] Show context menu --- app/main.ts | 37 ++++++++++++++++++- .../script-account-overview.component.html | 2 +- .../script-account-overview.component.ts | 11 ++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/app/main.ts b/app/main.ts index 17c3f2a..ffbea7c 100644 --- a/app/main.ts +++ b/app/main.ts @@ -1,4 +1,4 @@ -import {app, BrowserWindow, screen} from 'electron'; +import {app, BrowserWindow, screen, Menu, ipcMain} from 'electron'; import * as path from 'path'; import * as fs from 'fs'; @@ -50,6 +50,41 @@ function createWindow(): BrowserWindow { win = null; }); + const contextMenuTemplate = [ + { + label: 'New', + submenu: [ + { + label: "Gamesystem", + click: () => { + win!.webContents.send('context-menu', "new-location"); + } + }, + { + label: "ScriptAccount", + click: () => { + win!.webContents.send('context-menu', "new-scriptaccount"); + } + } + ] + + }, + { + label: 'Edit...' + }, + { + label: 'Delete...' + } + ] + + const contextMenu = Menu.buildFromTemplate(contextMenuTemplate); + + win.webContents.on('context-menu', (e, params) => { + console.log("Electron: Context menu showing") + contextMenu.popup({ window: win!, x: params.x, y: params.y }); + }) + + return win; } diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.html b/src/app/side-overviews/script-account-overview/script-account-overview.component.html index d35d531..c1b8260 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.html +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.html @@ -1,6 +1,6 @@ + (dblclick)="onOpenScriptAccount(scriptAccount)" (contextmenu)="onContextMenu($event)"> inventory_2{{scriptAccount.componentName}} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts index b5cea39..f6672ad 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts @@ -1,6 +1,7 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; import {GameModel} from "../../game-model/GameModel"; import {ScriptAccount} from "../../game-model/scriptAccounts/ScriptAccount"; +import {ElectronService} from "../../core/services"; @Component({ selector: 'app-script-account-overview', @@ -11,6 +12,9 @@ export class ScriptAccountOverviewComponent { @Input("gameModel") gameModel: GameModel | undefined @Output("onOpenScriptAccount") openScriptAccountEmitter: EventEmitter = new EventEmitter(); + constructor(private electronService: ElectronService) { + } + onOpenScriptAccount(scriptAccount: ScriptAccount) { console.log("onOpenScriptAccount (overview)") this.openScriptAccountEmitter.emit(scriptAccount); @@ -22,5 +26,12 @@ export class ScriptAccountOverviewComponent { return scriptAccount; } + onContextMenu(event: MouseEvent) { + if(this.electronService.isElectron) { + console.log("[DEBUG] [ScriptAccountOverviewComponent] App is executed in electron") + } else { + console.log("[DEBUG] [ScriptAccountOverviewComponent] App is not executed in electron") + } + } } From a6711cc2ba00857a2effc3f97e12355e375312ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 13:00:32 +0100 Subject: [PATCH 09/13] Create New ScriptAccount --- .../script-account-overview.component.html | 2 +- .../script-account-overview.component.spec.ts | 40 ++++++++++++++----- .../script-account-overview.component.ts | 27 +++++++------ 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.html b/src/app/side-overviews/script-account-overview/script-account-overview.component.html index c1b8260..d35d531 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.html +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.html @@ -1,6 +1,6 @@ + (dblclick)="onOpenScriptAccount(scriptAccount)"> inventory_2{{scriptAccount.componentName}} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts index 979d4b2..fce1a6e 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts @@ -1,23 +1,43 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; -import { ScriptAccountOverviewComponent } from './script-account-overview.component'; +import {TranslateModule} from "@ngx-translate/core"; +import {RouterTestingModule} from "@angular/router/testing"; +import {ScriptAccountOverviewComponent} from "./script-account-overview.component"; +import exp from "node:constants"; +import {GameModel} from "../../game-model/GameModel"; -describe('ScriptAccountOverviewComponent', () => { +describe('ScriptAccountOverview', () => { let component: ScriptAccountOverviewComponent; let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ScriptAccountOverviewComponent] - }) - .compileComponents(); - + beforeEach(waitForAsync(() => { + void TestBed.configureTestingModule({ + declarations: [ScriptAccountOverviewComponent], + imports: [TranslateModule.forRoot(), RouterTestingModule] + }).compileComponents(); + fixture = TestBed.createComponent(ScriptAccountOverviewComponent); component = fixture.componentInstance; + component.gameModel = new GameModel("GameModel") fixture.detectChanges(); - }); + })); it('should create', () => { expect(component).toBeTruthy(); }); + + it("Test ScriptAccount Creation", waitForAsync(() => { + component.onCreateNewScriptAccount(); + expect(component.gameModel!.scriptAccounts.length).toEqual(1) + component.gameModel!.removeScriptAccount(component.gameModel!.scriptAccounts[0]); + + jest.spyOn(component.openScriptAccountEmitter, 'emit'); + component.onCreateNewScriptAccount(); + fixture.detectChanges(); + + expect(component.openScriptAccountEmitter.emit).toHaveBeenCalledWith(component.gameModel!.scriptAccounts[0]); + + })) + + }); diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts index f6672ad..496be51 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {Component, EventEmitter, Input, NgZone, Output} from '@angular/core'; import {GameModel} from "../../game-model/GameModel"; import {ScriptAccount} from "../../game-model/scriptAccounts/ScriptAccount"; import {ElectronService} from "../../core/services"; @@ -12,7 +12,17 @@ export class ScriptAccountOverviewComponent { @Input("gameModel") gameModel: GameModel | undefined @Output("onOpenScriptAccount") openScriptAccountEmitter: EventEmitter = new EventEmitter(); - constructor(private electronService: ElectronService) { + constructor(private electronService: ElectronService, + private zone: NgZone) { + if(electronService.isElectron) { + this.electronService.ipcRenderer.on('context-menu', (event: any, message: string) => { + this.zone.run(() => { + if(message == "new-scriptaccount") { + this.onCreateNewScriptAccount() + } + }) + }) + } } onOpenScriptAccount(scriptAccount: ScriptAccount) { @@ -22,16 +32,7 @@ export class ScriptAccountOverviewComponent { onCreateNewScriptAccount() { const scriptAccount = new ScriptAccount("New ScriptAccount", ""); - this.gameModel?.addScriptAccount(scriptAccount); - return scriptAccount; - } - - onContextMenu(event: MouseEvent) { - if(this.electronService.isElectron) { - console.log("[DEBUG] [ScriptAccountOverviewComponent] App is executed in electron") - - } else { - console.log("[DEBUG] [ScriptAccountOverviewComponent] App is not executed in electron") - } + this.gameModel!.addScriptAccount(scriptAccount); + this.openScriptAccountEmitter.emit(scriptAccount); } } From 288b6ed220239afa5268b7dc197aa07abd70f80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 13:19:46 +0100 Subject: [PATCH 10/13] Ensure that not two modelcomponents with the same name can be created --- .../scriptAccounts/ScriptAccountTest.spec.ts | 40 +++++++++---------- src/app/app.component.ts | 4 +- src/app/game-model/GameModel.ts | 7 +++- .../script-account-overview.component.spec.ts | 5 +++ .../script-account-overview.component.ts | 7 ++-- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts index a9048e3..c7eb65b 100644 --- a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts +++ b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts @@ -21,38 +21,36 @@ test.describe('Test ScriptAccounts', () => { test("Test Adding ScriptAccounts", async () => { const gameModel: GameModel = new GameModel("GameModel"); - const scriptAccount = new ScriptAccount("ScriptAccount", "Description"); - gameModel.addScriptAccount(scriptAccount); - + let scriptAccount =gameModel.addScriptAccount("ScriptAccount"); + expect(scriptAccount).toBeDefined(); expect(gameModel.scriptAccounts.length).toEqual(1); expect(gameModel.scriptAccounts.includes(scriptAccount)).toBeTruthy(); - //Test for duplicates - gameModel.addScriptAccount(scriptAccount); - expect(gameModel.scriptAccounts.length).toEqual(1); - - //Test for adding null value - gameModel.addScriptAccount(null); - expect(gameModel.scriptAccounts.length).toEqual(1); - gameModel.addScriptAccount(undefined); - expect(gameModel.scriptAccounts.length).toEqual(1); - //Test adding scriptAccount with already existing name - const scriptAccount2 = new ScriptAccount("ScriptAccount", ""); - gameModel.addScriptAccount(scriptAccount2); + const scriptAccount2 = gameModel.addScriptAccount("ScriptAccount") + expect(scriptAccount2).toBeUndefined(); + expect(gameModel.scriptAccounts.length).toEqual(1); + + //Test for adding invalid names as scriptaccount names (null/undefined/empty) + let result = gameModel.addScriptAccount(null); + expect(result).toBeUndefined(); + expect(gameModel.scriptAccounts.length).toEqual(1); + result = gameModel.addScriptAccount(undefined); + expect(result).toBeUndefined(); + expect(gameModel.scriptAccounts.length).toEqual(1); + result = gameModel.addScriptAccount(""); + expect(result).toBeUndefined(); expect(gameModel.scriptAccounts.length).toEqual(1); - expect(gameModel.scriptAccounts.includes(scriptAccount2)).toBeFalsy(); }) test("test Removing ScriptAccounts", async () => { const gameModel: GameModel = new GameModel("GameModel"); - const scriptAccount = new ScriptAccount("ScriptAccount", "Description"); - const scriptAccount2 = new ScriptAccount("ScriptAccount 2", "Description"); + let scriptAccount = new ScriptAccount("test", "") gameModel.removeScriptAccount(scriptAccount); expect(gameModel.scriptAccounts.length).toEqual(0); - gameModel.addScriptAccount(scriptAccount); + scriptAccount = gameModel.addScriptAccount("ScriptAccount"); gameModel.removeScriptAccount(scriptAccount); expect(gameModel.scriptAccounts.length).toEqual(0); @@ -62,8 +60,8 @@ test.describe('Test ScriptAccounts', () => { gameModel.removeScriptAccount(null); expect(gameModel.scriptAccounts.length).toEqual(0); - gameModel.addScriptAccount(scriptAccount); - gameModel.addScriptAccount(scriptAccount2); + scriptAccount = gameModel.addScriptAccount(scriptAccount); + let scriptAccount2 = gameModel.addScriptAccount("ScriptAccount 2"); gameModel.removeScriptAccount(scriptAccount); expect(gameModel.scriptAccounts.length).toEqual(1); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e2f110d..85775ad 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -39,8 +39,8 @@ export class AppComponent implements OnInit{ ngOnInit() { this.gameModel = new GameModel("No More"); - this.gameModel.addScriptAccount(new ScriptAccount("Temperature", "")); - this.gameModel.addScriptAccount(new ScriptAccount("Luftfeuchtigkeit", "")); + this.gameModel.addScriptAccount("Temperature"); + this.gameModel.addScriptAccount("Luftfeuchtigkeit"); } openScriptAccountsOverview() { diff --git a/src/app/game-model/GameModel.ts b/src/app/game-model/GameModel.ts index b27a223..a061db3 100644 --- a/src/app/game-model/GameModel.ts +++ b/src/app/game-model/GameModel.ts @@ -32,13 +32,16 @@ export class GameModel { this._gamesystems = this._gamesystems.filter(g => g !== gamesystem); } - addScriptAccount(scriptAccount: ScriptAccount) { - if(scriptAccount != undefined && !this.scriptAccounts.includes(scriptAccount)) { + addScriptAccount(scriptAccountName: string) { + if(scriptAccountName != undefined && scriptAccountName.length > 0) { + const scriptAccount = new ScriptAccount(scriptAccountName, ""); const searchedScriptAccount = this.scriptAccounts.find(s => s.componentName === scriptAccount.componentName); if(searchedScriptAccount == undefined) { this.scriptAccounts.push(scriptAccount); + return scriptAccount; } } + return undefined; } removeScriptAccount(scriptAccount: ScriptAccount) { diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts index fce1a6e..09f3d6f 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts @@ -37,6 +37,11 @@ describe('ScriptAccountOverview', () => { expect(component.openScriptAccountEmitter.emit).toHaveBeenCalledWith(component.gameModel!.scriptAccounts[0]); + component.onCreateNewScriptAccount(); + fixture.detectChanges() + expect(component.openScriptAccountEmitter.emit).toBeCalledTimes(1); + + })) diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts index 496be51..e57d45a 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts @@ -31,8 +31,9 @@ export class ScriptAccountOverviewComponent { } onCreateNewScriptAccount() { - const scriptAccount = new ScriptAccount("New ScriptAccount", ""); - this.gameModel!.addScriptAccount(scriptAccount); - this.openScriptAccountEmitter.emit(scriptAccount); + const scriptAccount = this.gameModel!.addScriptAccount("New ScriptAccount"); + if(scriptAccount != undefined) { + this.openScriptAccountEmitter.emit(scriptAccount); + } } } From 388fcb044c3de2f23bcf52765e658289cd9d192d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 13:36:12 +0100 Subject: [PATCH 11/13] Open ScriptAccount from ContextMenu for adding --- app/main.ts | 5 ++++- src/app/app.component.html | 2 +- src/app/app.component.ts | 22 +++++++++++++++---- .../script-account-overview.component.css | 4 ++++ .../script-account-overview.component.html | 4 +++- .../script-account-overview.component.spec.ts | 2 -- .../script-account-overview.component.ts | 7 ++++++ 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/app/main.ts b/app/main.ts index ffbea7c..d51d319 100644 --- a/app/main.ts +++ b/app/main.ts @@ -70,7 +70,10 @@ function createWindow(): BrowserWindow { }, { - label: 'Edit...' + label: 'Edit...', + click: () => { + win!.webContents.send('context-menu', "edit"); + } }, { label: 'Delete...' diff --git a/src/app/app.component.html b/src/app/app.component.html index 6384677..2beb7f6 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -19,7 +19,7 @@ - +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 85775ad..e818360 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,13 +1,15 @@ -import {Component, OnInit, ViewChild} from '@angular/core'; +import {Component, NgZone, OnInit, ViewChild} from '@angular/core'; import {ElectronService} from './core/services'; import {APP_CONFIG} from '../environments/environment'; import {ModelComponentType} from "./game-model/ModelComponentType"; import {MatDrawerContainer} from "@angular/material/sidenav"; import {ModelComponentTypeUtillities} from "./game-model/ModelComponentTypeUtillities"; import {GameModel} from "./game-model/GameModel"; -import {ScriptAccount} from "./game-model/scriptAccounts/ScriptAccount"; import {EditorComponent} from "./editor/editor.component"; import {ModelComponent} from "./game-model/ModelComponent"; +import { + ScriptAccountOverviewComponent +} from "./side-overviews/script-account-overview/script-account-overview.component"; @Component({ selector: 'app-root', @@ -19,11 +21,12 @@ export class AppComponent implements OnInit{ openContent : ModelComponentType | undefined = undefined; @ViewChild('drawer') drawer: MatDrawerContainer|undefined @ViewChild('editor') editor: EditorComponent|undefined + @ViewChild('scriptAccountOverview') scriptAccountOverview: ScriptAccountOverviewComponent | undefined gameModel: GameModel | undefined - constructor( - private electronService: ElectronService, + constructor(private electronService: ElectronService, + private zone: NgZone ) { console.log('APP_CONFIG', APP_CONFIG); @@ -32,6 +35,17 @@ export class AppComponent implements OnInit{ console.log('Run in electron'); console.log('Electron ipcRenderer', this.electronService.ipcRenderer); console.log('NodeJS childProcess', this.electronService.childProcess); + + electronService.ipcRenderer.on('context-menu', (event: any, message: string) => { + this.zone.run(() => { + if(message == "edit") { + console.log("Edit!") + if(this.openContent == ModelComponentType.SCRIPTACCOUNT && this.scriptAccountOverview != undefined && this.scriptAccountOverview.selectedScriptAccount != undefined) { + this.editor!.openGameModelComponent(this.scriptAccountOverview.selectedScriptAccount!); + } + } + }) + }) } else { console.log('Run in browser'); } diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.css b/src/app/side-overviews/script-account-overview/script-account-overview.component.css index 0a8651a..0dde805 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.css +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.css @@ -8,3 +8,7 @@ color: #ccffff; align-content: baseline; } + +.selected-item { + background-color: #8696b6; +} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.html b/src/app/side-overviews/script-account-overview/script-account-overview.component.html index d35d531..797174b 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.html +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.html @@ -1,6 +1,8 @@ + (dblclick)="onOpenScriptAccount(scriptAccount)" (click)="selectScriptAccount(scriptAccount)" + [ngClass]="selectedScriptAccount === scriptAccount ?'selected-item':''" + (contextmenu)="selectScriptAccount(scriptAccount)"> inventory_2{{scriptAccount.componentName}} diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts index 09f3d6f..991dc2e 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.spec.ts @@ -40,8 +40,6 @@ describe('ScriptAccountOverview', () => { component.onCreateNewScriptAccount(); fixture.detectChanges() expect(component.openScriptAccountEmitter.emit).toBeCalledTimes(1); - - })) diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts index e57d45a..f8621ee 100644 --- a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts +++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts @@ -12,6 +12,8 @@ export class ScriptAccountOverviewComponent { @Input("gameModel") gameModel: GameModel | undefined @Output("onOpenScriptAccount") openScriptAccountEmitter: EventEmitter = new EventEmitter(); + selectedScriptAccount: ScriptAccount | undefined + constructor(private electronService: ElectronService, private zone: NgZone) { if(electronService.isElectron) { @@ -36,4 +38,9 @@ export class ScriptAccountOverviewComponent { this.openScriptAccountEmitter.emit(scriptAccount); } } + + + selectScriptAccount(scriptAccount: ScriptAccount) { + this.selectedScriptAccount = scriptAccount; + } } From 36391326eab66014d9e92ac6f961827627fe0d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 27 Jan 2024 15:25:32 +0100 Subject: [PATCH 12/13] Delete ScriptAccounts --- app/main.ts | 5 ++- src/app/app.component.ts | 29 ++++++++++++- src/app/app.module.ts | 12 ++++-- .../delete-confirmation-dialog.component.html | 12 ++++++ .../delete-confirmation-dialog.component.scss | 41 +++++++++++++++++++ ...lete-confirmation-dialog.component.spec.ts | 23 +++++++++++ .../delete-confirmation-dialog.component.ts | 25 +++++++++++ .../ModelComponentTypeUtillities.ts | 8 ++++ src/styles.css | 10 +++++ 9 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.html create mode 100644 src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.scss create mode 100644 src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.spec.ts create mode 100644 src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.ts diff --git a/app/main.ts b/app/main.ts index d51d319..7f9f75d 100644 --- a/app/main.ts +++ b/app/main.ts @@ -76,7 +76,10 @@ function createWindow(): BrowserWindow { } }, { - label: 'Delete...' + label: 'Delete...', + click: () => { + win!.webContents.send('context-menu', "delete"); + } } ] diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e818360..325cbac 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -10,6 +10,9 @@ import {ModelComponent} from "./game-model/ModelComponent"; import { ScriptAccountOverviewComponent } from "./side-overviews/script-account-overview/script-account-overview.component"; +import {MatDialog} from "@angular/material/dialog"; +import {DeleteConfirmationDialogComponent} from "./delete-confirmation-dialog/delete-confirmation-dialog.component"; +import {ScriptAccount} from "./game-model/scriptAccounts/ScriptAccount"; @Component({ selector: 'app-root', @@ -26,7 +29,8 @@ export class AppComponent implements OnInit{ gameModel: GameModel | undefined constructor(private electronService: ElectronService, - private zone: NgZone + private zone: NgZone, + private dialog: MatDialog ) { console.log('APP_CONFIG', APP_CONFIG); @@ -39,10 +43,20 @@ export class AppComponent implements OnInit{ electronService.ipcRenderer.on('context-menu', (event: any, message: string) => { this.zone.run(() => { if(message == "edit") { - console.log("Edit!") if(this.openContent == ModelComponentType.SCRIPTACCOUNT && this.scriptAccountOverview != undefined && this.scriptAccountOverview.selectedScriptAccount != undefined) { this.editor!.openGameModelComponent(this.scriptAccountOverview.selectedScriptAccount!); } + } else if(message == "delete") { + const affectedModelComponent = this.getSelectedModelComponent(); + const dialogRef = this.dialog.open(DeleteConfirmationDialogComponent, {data: affectedModelComponent, minWidth: "400px"}); + + dialogRef.afterClosed().subscribe(res => { + if(res != undefined && res) { + if(affectedModelComponent instanceof ScriptAccount) { + this.gameModel!.removeScriptAccount(affectedModelComponent); + } + } + }) } }) }) @@ -51,6 +65,17 @@ export class AppComponent implements OnInit{ } } + private getSelectedModelComponent(): ModelComponent | undefined { + if(this.openContent == ModelComponentType.SCRIPTACCOUNT) { + if(this.scriptAccountOverview != undefined) { + return this.scriptAccountOverview!.selectedScriptAccount; + } else { + console.log("[WARN] [App.component] ScriptAccountOverview is undefined") + } + } + return undefined; + } + ngOnInit() { this.gameModel = new GameModel("No More"); this.gameModel.addScriptAccount("Temperature"); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 95f920e..c3edf21 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -13,7 +13,7 @@ import {SharedModule} from "./shared/shared.module"; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import {MatIcon} from "@angular/material/icon"; import {MatToolbar} from "@angular/material/toolbar"; -import {MatButton, MatIconButton} from "@angular/material/button"; +import {MatButton, MatIconButton, MatMiniFabButton} from "@angular/material/button"; import {MatError, MatFormField, MatLabel} from "@angular/material/form-field"; import {MatInput} from "@angular/material/input"; import {MatDrawer, MatDrawerContainer} from "@angular/material/sidenav"; @@ -26,6 +26,8 @@ import {EditorComponent} from "./editor/editor.component"; import {MatTab, MatTabGroup, MatTabLabel} from "@angular/material/tabs"; import {ScriptAccountEditorComponent} from "./editor/script-account-editor/script-account-editor.component"; import {ModelComponentEditorComponent} from "./editor/model-component-editor/model-component-editor.component"; +import {DeleteConfirmationDialogComponent} from "./delete-confirmation-dialog/delete-confirmation-dialog.component"; +import {MatDialogActions, MatDialogContent, MatDialogTitle} from "@angular/material/dialog"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -36,7 +38,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl ScriptAccountOverviewComponent, EditorComponent, ScriptAccountEditorComponent, - ModelComponentEditorComponent + ModelComponentEditorComponent, + DeleteConfirmationDialogComponent ], imports: [ BrowserModule, @@ -72,7 +75,10 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatFormField, ReactiveFormsModule, MatError, - + MatDialogTitle, + MatDialogContent, + MatDialogActions, + MatMiniFabButton, ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.html b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.html new file mode 100644 index 0000000..33297a2 --- /dev/null +++ b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.html @@ -0,0 +1,12 @@ +

+ Delete + +

+
+

Delete {{ModelComponentTypeUtillities.toSingleString(deleteModelComponent.type)}}"{{deleteModelComponent.componentName}}"?

+
+
+ + +
+ diff --git a/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.scss b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.scss new file mode 100644 index 0000000..9a8eca7 --- /dev/null +++ b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.scss @@ -0,0 +1,41 @@ +.dialog-title { + background-color: #272727; + text-align: center; + align-items: center; + display: flex; + justify-content: space-between; + height: 50px !important; + padding-right: 10px; +} + +.small-icon-button { + width: 28px !important; + height: 28px !important; + padding: 0px !important; + display: inline-flex !important; + align-items: center; + justify-content: center; + margin-left: 10px; + margin-bottom: 5px; + background-color: black; + + & > *[role=img] { + width: 20px; + height: 20px; + font-size: 20px; + + svg { + width: 20px; + height: 20px; + } + } + + .mat-mdc-button-touch-target { + width: 24px !important; + height: 24px !important; + } +} + +.small-icon-button mat-icon { + color: whitesmoke; +} diff --git a/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.spec.ts b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.spec.ts new file mode 100644 index 0000000..74c7c4a --- /dev/null +++ b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeleteConfirmationDialogComponent } from './delete-confirmation-dialog.component'; + +describe('DeleteConfirmationDialogComponent', () => { + let component: DeleteConfirmationDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [DeleteConfirmationDialogComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(DeleteConfirmationDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.ts b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.ts new file mode 100644 index 0000000..8eacb90 --- /dev/null +++ b/src/app/delete-confirmation-dialog/delete-confirmation-dialog.component.ts @@ -0,0 +1,25 @@ +import {Component, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {ModelComponentTypeUtillities} from "../game-model/ModelComponentTypeUtillities"; +import {ModelComponent} from "../game-model/ModelComponent"; + +@Component({ + selector: 'app-delete-confirmation-dialog', + templateUrl: './delete-confirmation-dialog.component.html', + styleUrl: './delete-confirmation-dialog.component.scss' +}) +export class DeleteConfirmationDialogComponent { + + constructor(private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public deleteModelComponent: ModelComponent) { + } + protected readonly ModelComponentTypeUtillities = ModelComponentTypeUtillities; + + cancel() { + this.dialogRef.close(false); + } + + confirmDelete() { + this.dialogRef.close(true); + } +} diff --git a/src/app/game-model/ModelComponentTypeUtillities.ts b/src/app/game-model/ModelComponentTypeUtillities.ts index 772ab30..c92fce9 100644 --- a/src/app/game-model/ModelComponentTypeUtillities.ts +++ b/src/app/game-model/ModelComponentTypeUtillities.ts @@ -1,4 +1,5 @@ import {ModelComponentType} from "./ModelComponentType"; +import {ModelComponent} from "./ModelComponent"; export class ModelComponentTypeUtillities { static toString(modelComponentType: ModelComponentType | undefined): string { @@ -7,4 +8,11 @@ export class ModelComponentTypeUtillities { default: return "Undefined"; } } + + static toSingleString(modelComponentType: ModelComponentType | undefined): string { + switch (modelComponentType) { + case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccount"; + default: return "Undefined"; + } + } } diff --git a/src/styles.css b/src/styles.css index c310536..2fd855a 100644 --- a/src/styles.css +++ b/src/styles.css @@ -7,3 +7,13 @@ body { html, body { height: 100%; margin: 0 } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } + +.btn-primary { + background-color: #3c95f8 !important; + color: white; +} + +.btn-secondary { + background-color: #4f5459 !important; + color: white; +} From 4bf897e85babc82bf63c073160330553318d9f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Mon, 5 Feb 2024 17:59:20 +0100 Subject: [PATCH 13/13] Visualize Save/Unsaved Status in Tabs (Editor) --- src/app/editor/editor.component.html | 6 +++--- src/app/editor/editor.component.scss | 11 +++++++++++ .../model-component-editor.component.ts | 2 ++ .../script-account-editor.component.ts | 2 ++ src/app/game-model/ModelComponent.ts | 4 +++- src/app/game-model/SaveComponent.ts | 13 +++++++++++++ src/app/game-model/scriptAccounts/ScriptAccount.ts | 4 ++++ 7 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/app/game-model/SaveComponent.ts diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index 1c9a6a5..ef4276b 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -1,9 +1,9 @@ - inventory_2 - {{modelComponent.componentName}} - + inventory_2 + {{modelComponent.componentName}} +