issue-5-product-gamesystems #11
@ -54,6 +54,14 @@ import {MatOption, MatSelect} from "@angular/material/select";
|
||||
import {
|
||||
ProductGamesystemEditorComponent
|
||||
} from "./editor/gamesystem-editor/product-gamesystem-editor/product-gamesystem-editor.component";
|
||||
import {
|
||||
ProductTransitionEditorComponent
|
||||
} from "./editor/gamesystem-editor/transition-editor/product-transition-editor/product-transition-editor.component";
|
||||
import {
|
||||
ProductStateEditorComponent
|
||||
} from "./editor/gamesystem-editor/state-editor/product-state-editor/product-state-editor.component";
|
||||
import {MatTooltip} from "@angular/material/tooltip";
|
||||
import {MatCard, MatCardContent} from "@angular/material/card";
|
||||
|
||||
// AoT requires an exported function for factories
|
||||
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||
@ -70,7 +78,10 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
|
||||
GamesystemEditorComponent,
|
||||
SimpleGamesystemEditorComponent,
|
||||
SimpleStateEditorComponent,
|
||||
SimpleTransitionEditorComponent
|
||||
SimpleTransitionEditorComponent,
|
||||
ProductTransitionEditorComponent,
|
||||
ProductStateEditorComponent,
|
||||
ProductGamesystemEditorComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -125,7 +136,9 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
|
||||
MatSelect,
|
||||
MatOption,
|
||||
MatHint,
|
||||
ProductGamesystemEditorComponent
|
||||
MatTooltip,
|
||||
MatCard,
|
||||
MatCardContent
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
@ -1,2 +1,4 @@
|
||||
<app-product-state-editor [gamesystem]="gamesystem" (onOpenGamesystemEditor)="onOpenGamesystemEditor($event)"></app-product-state-editor>
|
||||
<app-product-transition-editor [gamesystem]="gamesystem" (onOpenGamesystem)="onOpenGamesystemEditor($event)"></app-product-transition-editor>
|
||||
<div id="productStateEditor">
|
||||
<app-product-transition-editor [gamesystem]="gamesystem" (onOpenGamesystem)="onOpenGamesystemEditor($event)"></app-product-transition-editor>
|
||||
</div>
|
||||
|
@ -0,0 +1,3 @@
|
||||
#productStateEditor {
|
||||
margin-top: 20px;
|
||||
}
|
@ -10,11 +10,6 @@ import {
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-gamesystem-editor',
|
||||
standalone: true,
|
||||
imports: [
|
||||
ProductStateEditorComponent,
|
||||
ProductTransitionEditorComponent
|
||||
],
|
||||
templateUrl: './product-gamesystem-editor.component.html',
|
||||
styleUrl: './product-gamesystem-editor.component.scss'
|
||||
})
|
||||
|
@ -1,2 +1,4 @@
|
||||
<app-simple-state-editor [states]="simpleGamesystem!.states" [gamesystem]="simpleGamesystem"></app-simple-state-editor>
|
||||
<app-simple-transition-editor class="transition-editor" [gamesystem]="simpleGamesystem"></app-simple-transition-editor>
|
||||
<div id="transition-editor">
|
||||
<app-simple-transition-editor [gamesystem]="simpleGamesystem"></app-simple-transition-editor>
|
||||
</div>
|
||||
|
@ -1,3 +1,4 @@
|
||||
.transition-editor {
|
||||
margin-top: 15px;
|
||||
#transition-editor {
|
||||
margin-top: 20px !important;
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,22 @@
|
||||
<table mat-table [dataSource]="datasource" class="mat-elevation-z8">
|
||||
<ng-container *ngFor="let col of displayedColumns; let i = index" [matColumnDef]="col">
|
||||
<th mat-header-cell *matHeaderCellDef>{{col}}</th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<a *ngIf="i < displayedColumns.length-1" role="button" (click)="clickOnInnerState(i)" [matTooltip]="getLeafState(state, i).stateDescription">{{getLeafState(state, i).stateLabel}}</a>
|
||||
<mat-icon *ngIf="i == displayedColumns.length-1">
|
||||
{{state.initial? 'done':'close'}}
|
||||
</mat-icon>
|
||||
</td>
|
||||
</ng-container>
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-form-field appearance="fill" class="long-form">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Filter" #input>
|
||||
</mat-form-field>
|
||||
<table mat-table [dataSource]="datasource" class="mat-elevation-z8">
|
||||
<ng-container *ngFor="let col of displayedColumns; let i = index" [matColumnDef]="col">
|
||||
<th mat-header-cell *matHeaderCellDef>{{col}}</th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<a *ngIf="i < displayedColumns.length-1" role="button" (click)="clickOnInnerState(i)" [matTooltip]="getLeafState(state, i).stateDescription">{{getLeafState(state, i).stateLabel}}</a>
|
||||
<mat-icon *ngIf="i == displayedColumns.length-1">
|
||||
{{state.initial? 'done':'close'}}
|
||||
</mat-icon>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
@ -5,3 +5,7 @@ table {
|
||||
.mat-column-Initial {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.long-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -2,43 +2,16 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ProductGamesystem} from "../../../../game-model/gamesystems/ProductGamesystem";
|
||||
import {SimpleGamesystem} from "../../../../game-model/gamesystems/SimpleGamesystem";
|
||||
import {
|
||||
MatCell, MatCellDef,
|
||||
MatColumnDef, MatHeaderCell, MatHeaderCellDef,
|
||||
MatHeaderRow,
|
||||
MatHeaderRowDef,
|
||||
MatRow,
|
||||
MatRowDef,
|
||||
MatTable,
|
||||
MatTableDataSource
|
||||
} from "@angular/material/table";
|
||||
import {SimpleState} from "../../../../game-model/gamesystems/SimpleState";
|
||||
import {State} from "../../../../game-model/gamesystems/State";
|
||||
import {NgForOf, NgIf} from "@angular/common";
|
||||
import {ProductState} from "../../../../game-model/gamesystems/ProductState";
|
||||
import {MatIcon} from "@angular/material/icon";
|
||||
import {Gamesystem} from "../../../../game-model/gamesystems/Gamesystem";
|
||||
import {LeafGamesystemCalculator} from "../../product-gamesystem-editor/LeafGamesystemCalculator";
|
||||
import {MatTooltip} from "@angular/material/tooltip";
|
||||
import {ProductTransition} from "../../../../game-model/gamesystems/ProductTransition";
|
||||
import {ProductState} from "../../../../game-model/gamesystems/ProductState";
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-state-editor',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatTable,
|
||||
MatRow,
|
||||
MatRowDef,
|
||||
MatHeaderRow,
|
||||
MatHeaderRowDef,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatHeaderCellDef,
|
||||
MatCell,
|
||||
MatCellDef,
|
||||
NgForOf,
|
||||
NgIf,
|
||||
MatIcon,
|
||||
MatTooltip
|
||||
],
|
||||
templateUrl: './product-state-editor.component.html',
|
||||
styleUrl: './product-state-editor.component.scss'
|
||||
})
|
||||
@ -47,7 +20,7 @@ export class ProductStateEditorComponent implements OnInit{
|
||||
@Input() gamesystem: ProductGamesystem | undefined
|
||||
@Output('onOpenGamesystemEditor') openGamesystemEditorEmitter = new EventEmitter<SimpleGamesystem>();
|
||||
displayedColumns: string[] = [];
|
||||
datasource = new MatTableDataSource();
|
||||
datasource = new MatTableDataSource<ProductState>();
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
@ -55,6 +28,10 @@ export class ProductStateEditorComponent implements OnInit{
|
||||
this.generateColumnNamesRecursively(this.gamesystem!, "");
|
||||
this.displayedColumns.push('Initial');
|
||||
this.datasource.data = this.gamesystem!.states;
|
||||
this.datasource.filterPredicate = (data: ProductState, filter: string) => {
|
||||
const leaf_states = LeafGamesystemCalculator.calcLeafStates(data);
|
||||
return leaf_states.some((state) => state.stateLabel.toLowerCase().includes(filter))
|
||||
}
|
||||
}
|
||||
|
||||
generateColumnNamesRecursively(gamesystem: ProductGamesystem, nestedColumnName: string) {
|
||||
@ -79,4 +56,9 @@ export class ProductStateEditorComponent implements OnInit{
|
||||
this.openGamesystemEditorEmitter.emit(clicked_gamesystem);
|
||||
}
|
||||
|
||||
applyFilter(event: KeyboardEvent) {
|
||||
const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.datasource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,77 +1,86 @@
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" multiTemplateDataRows>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>Label</th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<span *ngIf="editedElement !== state"> {{state.stateLabel}}</span>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="editedElement === state">
|
||||
<input matInput [(ngModel)]="state.stateLabel" (ngModelChange)="onStateChange()">
|
||||
<mat-hint class="mat-error" *ngIf="editedStateLabelError"><mat-icon class="warning-icon">warning</mat-icon>Missing State-Label Information</mat-hint>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-form-field appearance="fill" class="long-form">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Filter" #input>
|
||||
</mat-form-field>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" multiTemplateDataRows>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>Label</th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<span *ngIf="editedElement !== state"> {{state.stateLabel}}</span>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="editedElement === state">
|
||||
<input matInput [(ngModel)]="state.stateLabel" (ngModelChange)="onStateChange()">
|
||||
<mat-hint class="mat-error" *ngIf="editedStateLabelError"><mat-icon class="warning-icon">warning</mat-icon>Missing State-Label Information</mat-hint>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
|
||||
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
|
||||
<p *ngIf="editedElement !== element">{{element.stateDescription}}</p>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="element === editedElement">
|
||||
<mat-label>Description</mat-label>
|
||||
<textarea matInput [(ngModel)]="element.stateDescription" rows="3" (ngModelChange)="onStateChange()"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
|
||||
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
|
||||
<p *ngIf="editedElement !== element">{{element.stateDescription}}</p>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="element === editedElement">
|
||||
<mat-label>Description</mat-label>
|
||||
<textarea matInput [(ngModel)]="element.stateDescription" rows="3" (ngModelChange)="onStateChange()"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
|
||||
<ng-container matColumnDef="initial">
|
||||
<th mat-header-cell *matHeaderCellDef>Initial</th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<div *ngIf="editedElement !== state">
|
||||
<mat-icon *ngIf="state.initial">done</mat-icon>
|
||||
<mat-icon *ngIf="!state.initial">close</mat-icon>
|
||||
</div>
|
||||
<mat-checkbox *ngIf="editedElement === state" [(ngModel)]="state.initial" (ngModelChange)="onStateChange()"></mat-checkbox>
|
||||
<ng-container matColumnDef="initial">
|
||||
<th mat-header-cell *matHeaderCellDef>Initial</th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<div *ngIf="editedElement !== state">
|
||||
<mat-icon *ngIf="state.initial">done</mat-icon>
|
||||
<mat-icon *ngIf="!state.initial">close</mat-icon>
|
||||
</div>
|
||||
<mat-checkbox *ngIf="editedElement === state" [(ngModel)]="state.initial" (ngModelChange)="onStateChange()"></mat-checkbox>
|
||||
|
||||
</td>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="edit">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<button mat-icon-button color="primary" *ngIf="editedElement !== state" (click)="editState(state)" [disabled]="editedElement !== null"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="primary" (click)="finishEditing()" *ngIf="editedElement === state"><mat-icon>done</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="edit">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<button mat-icon-button color="primary" *ngIf="editedElement !== state" (click)="editState(state)" [disabled]="editedElement !== null"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="primary" (click)="finishEditing()" *ngIf="editedElement === state"><mat-icon>done</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<button mat-icon-button color="warn" (click)="deleteState(state)"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let state">
|
||||
<button mat-icon-button color="warn" (click)="deleteState(state)"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="expand">
|
||||
<th mat-header-cell *matHeaderCellDef aria-label="row actions">
|
||||
<button mat-icon-button (click)="addState()"><mat-icon>add</mat-icon></button>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-icon-button aria-label="expand row" (click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
|
||||
@if (expandedElement === element) {
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
} @else {
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="expand">
|
||||
<th mat-header-cell *matHeaderCellDef aria-label="row actions">
|
||||
<button mat-icon-button (click)="addState()"><mat-icon>add</mat-icon></button>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-icon-button aria-label="expand row" (click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
|
||||
@if (expandedElement === element) {
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
} @else {
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
|
||||
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
|
||||
class="example-element-row"
|
||||
[class.example-expanded-row]="expandedElement === element"
|
||||
(click)="expandedElement = expandedElement === element ? null : element">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
|
||||
</table>
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
|
||||
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
|
||||
class="example-element-row"
|
||||
[class.example-expanded-row]="expandedElement === element"
|
||||
(click)="expandedElement = expandedElement === element ? null : element">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
|
||||
</table>
|
||||
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
@ -4,6 +4,8 @@ import {MatTableDataSource} from "@angular/material/table";
|
||||
import {animate, state, style, transition, trigger} from "@angular/animations";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {SimpleGamesystem} from "../../../../game-model/gamesystems/SimpleGamesystem";
|
||||
import {ProductState} from "../../../../game-model/gamesystems/ProductState";
|
||||
import {LeafGamesystemCalculator} from "../../product-gamesystem-editor/LeafGamesystemCalculator";
|
||||
|
||||
@Component({
|
||||
selector: 'app-simple-state-editor',
|
||||
@ -21,7 +23,7 @@ export class SimpleStateEditorComponent implements OnInit{
|
||||
|
||||
@Input() states: SimpleState[] = [];
|
||||
@Input() gamesystem: SimpleGamesystem | undefined
|
||||
dataSource = new MatTableDataSource();
|
||||
dataSource = new MatTableDataSource<SimpleState>();
|
||||
displayedColumns = ["name", "initial", "edit", "delete"];
|
||||
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
|
||||
expandedElement: SimpleState | null = null;
|
||||
@ -34,6 +36,9 @@ export class SimpleStateEditorComponent implements OnInit{
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.data = this.states;
|
||||
this.dataSource.filterPredicate = (data: SimpleState, filter: string) => {
|
||||
return data.stateLabel.toLowerCase().includes(filter);
|
||||
}
|
||||
}
|
||||
|
||||
editState(state: SimpleState) {
|
||||
@ -83,4 +88,9 @@ export class SimpleStateEditorComponent implements OnInit{
|
||||
onStateChange() {
|
||||
this.gamesystem!.onModifyContent();
|
||||
}
|
||||
|
||||
applyFilter(event: KeyboardEvent) {
|
||||
const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +1,54 @@
|
||||
<table mat-table [dataSource]="dataSource">
|
||||
<ng-container *ngFor="let col of displayedColumns; let i = index" [matColumnDef]="col.internalName">
|
||||
<th mat-header-cell *matHeaderCellDef (dblclick)="openGamesystemEditor(i)">{{col.displayedName}}</th>
|
||||
<td mat-cell *matCellDef="let transition" [matTooltip]="getLeafStateByIndex(transition, i).stateDescription" (dblclick)="openGamesystemEditor(i)">
|
||||
{{getLeafStateByIndex(transition, i).stateLabel}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-form-field class="long-form">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Filter" #input>
|
||||
</mat-form-field>
|
||||
<table mat-table [dataSource]="dataSource">
|
||||
<ng-container *ngFor="let col of displayedColumns; let i = index" [matColumnDef]="col.internalName">
|
||||
<th mat-header-cell *matHeaderCellDef (dblclick)="openGamesystemEditor(i)">{{col.displayedName}}</th>
|
||||
<td mat-cell *matCellDef="let transition" [matTooltip]="getLeafStateByIndex(transition, i).stateDescription" (dblclick)="openGamesystemEditor(i)">
|
||||
{{getLeafStateByIndex(transition, i).stateLabel}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="header-row-sec-group">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
[style.text-align]="'center'"
|
||||
[attr.colspan]="numberLeafSystems"
|
||||
class="start-end-col"
|
||||
>
|
||||
Starting State
|
||||
</th>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="header-row-third-group">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
[style.text-align]="'center'"
|
||||
[attr.colspan]="numberLeafSystems"
|
||||
>
|
||||
Ending State
|
||||
</th>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="header-row-sec-group">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
[style.text-align]="'center'"
|
||||
[attr.colspan]="numberLeafSystems"
|
||||
class="start-end-col"
|
||||
>
|
||||
Starting State
|
||||
</th>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="header-row-third-group">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
[style.text-align]="'center'"
|
||||
[attr.colspan]="numberLeafSystems"
|
||||
>
|
||||
Ending State
|
||||
</th>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="displayedColumns.length">
|
||||
<tr
|
||||
mat-header-row
|
||||
*matHeaderRowDef="['header-row-sec-group', 'header-row-third-group']"
|
||||
></tr>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="displayedColumns.length">
|
||||
<tr
|
||||
mat-header-row
|
||||
*matHeaderRowDef="['header-row-sec-group', 'header-row-third-group']"
|
||||
></tr>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columns;sticky:true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: columns;"></tr>
|
||||
<tr mat-header-row *matHeaderRowDef="columns;sticky:true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: columns;"></tr>
|
||||
|
||||
</table>
|
||||
<tr class="mat-row" *matNoDataRow>
|
||||
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
@ -0,0 +1,4 @@
|
||||
.long-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -2,19 +2,11 @@ import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ProductGamesystem} from "../../../../game-model/gamesystems/ProductGamesystem";
|
||||
import {SimpleGamesystem} from "../../../../game-model/gamesystems/SimpleGamesystem";
|
||||
import {
|
||||
MatCell, MatCellDef,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
|
||||
MatTable,
|
||||
MatTableDataSource
|
||||
} from "@angular/material/table";
|
||||
import {LeafGamesystemCalculator} from "../../product-gamesystem-editor/LeafGamesystemCalculator";
|
||||
import {NgForOf, NgIf} from "@angular/common";
|
||||
import {ProductTransition} from "../../../../game-model/gamesystems/ProductTransition";
|
||||
import {ProductState} from "../../../../game-model/gamesystems/ProductState";
|
||||
import {MatTooltip} from "@angular/material/tooltip";
|
||||
|
||||
class DisplayedColumnName {
|
||||
displayedName: string
|
||||
internalName: string
|
||||
@ -27,22 +19,6 @@ class DisplayedColumnName {
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-product-transition-editor',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatTable,
|
||||
NgForOf,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatHeaderCellDef,
|
||||
MatCell,
|
||||
MatCellDef,
|
||||
NgIf,
|
||||
MatHeaderRow,
|
||||
MatRow,
|
||||
MatHeaderRowDef,
|
||||
MatRowDef,
|
||||
MatTooltip
|
||||
],
|
||||
templateUrl: './product-transition-editor.component.html',
|
||||
styleUrl: './product-transition-editor.component.scss'
|
||||
})
|
||||
@ -51,7 +27,7 @@ export class ProductTransitionEditorComponent implements OnInit{
|
||||
@Input() gamesystem: ProductGamesystem | undefined
|
||||
@Output() onOpenGamesystem = new EventEmitter<SimpleGamesystem>();
|
||||
|
||||
dataSource = new MatTableDataSource();
|
||||
dataSource = new MatTableDataSource<ProductTransition>();
|
||||
displayedColumns: DisplayedColumnName[] = [];
|
||||
columns: string[] = [];
|
||||
numberLeafSystems: number = -1;
|
||||
@ -66,6 +42,14 @@ export class ProductTransitionEditorComponent implements OnInit{
|
||||
this.columns = this.displayedColumns.map(column => column.internalName)
|
||||
|
||||
this.dataSource.data = this.gamesystem.transitions;
|
||||
this.dataSource.filterPredicate = (data: ProductTransition, filter: string) => {
|
||||
const leaf_starting_states = LeafGamesystemCalculator.calcLeafStates(data.startingState);
|
||||
const leaf_ending_states = LeafGamesystemCalculator.calcLeafStates(data.endingState);
|
||||
|
||||
const combined_leaf_states = leaf_starting_states.concat(leaf_ending_states);
|
||||
|
||||
return combined_leaf_states.some((state) => state.stateLabel.toLowerCase().includes(filter))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,8 +63,6 @@ export class ProductTransitionEditorComponent implements OnInit{
|
||||
index = leafIndex - this.numberLeafSystems;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const leafStates = LeafGamesystemCalculator.calcLeafStates(state);
|
||||
console.log(leafStates)
|
||||
return leafStates[index];
|
||||
@ -94,4 +76,9 @@ export class ProductTransitionEditorComponent implements OnInit{
|
||||
this.onOpenGamesystem.emit(leafGamesystems[leafIndex - this.numberLeafSystems])
|
||||
}
|
||||
}
|
||||
|
||||
applyFilter(event: KeyboardEvent) {
|
||||
const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
@ -1,81 +1,91 @@
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" multiTemplateDataRows>
|
||||
<ng-container matColumnDef="starting-state">
|
||||
<th mat-header-cell *matHeaderCellDef>Starting State</th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<span *ngIf="editedTransition !== transition">{{transition.startingState.stateLabel}}</span>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="editedTransition == transition">
|
||||
<mat-select [(ngModel)]="editedTransition!.startingState" (ngModelChange)="validateEditedTransition()">
|
||||
<mat-option *ngFor="let state of gamesystem!.states" [value]="state"
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<mat-form-field class="long-form">
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Filter" #input>
|
||||
</mat-form-field>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" multiTemplateDataRows>
|
||||
<ng-container matColumnDef="starting-state">
|
||||
<th mat-header-cell *matHeaderCellDef>Starting State</th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<span *ngIf="editedTransition !== transition">{{transition.startingState.stateLabel}}</span>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="editedTransition == transition">
|
||||
<mat-select [(ngModel)]="editedTransition!.startingState" (ngModelChange)="validateEditedTransition()">
|
||||
<mat-option *ngFor="let state of gamesystem!.states" [value]="state"
|
||||
(onSelectionChange)="validateEditedTransition()">{{state.stateLabel}}</mat-option>
|
||||
</mat-select>
|
||||
<mat-hint class="mat-error" *ngIf="transitionError"><mat-icon class="warning-icon">warning</mat-icon> Starting and Ending State cannot be the same!</mat-hint>
|
||||
<mat-hint class="mat-error" *ngIf="!transitionError && transitionStartingStateError"><mat-icon class="warning-icon">warning</mat-icon> Select a valid Starting State!</mat-hint>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
</mat-select>
|
||||
<mat-hint class="mat-error" *ngIf="transitionError"><mat-icon class="warning-icon">warning</mat-icon> Starting and Ending State cannot be the same!</mat-hint>
|
||||
<mat-hint class="mat-error" *ngIf="!transitionError && transitionStartingStateError"><mat-icon class="warning-icon">warning</mat-icon> Select a valid Starting State!</mat-hint>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="ending-state">
|
||||
<th mat-header-cell *matHeaderCellDef>Ending State</th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<span *ngIf="editedTransition !== transition">{{transition.endingState.stateLabel}}</span>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="editedTransition == transition">
|
||||
<mat-select [(ngModel)]="editedTransition!.endingState" (ngModelChange)="validateEditedTransition()">
|
||||
<mat-option *ngFor="let state of gamesystem!.states" [value]="state"
|
||||
(onSelectionChange)="validateEditedTransition()">{{state.stateLabel}}</mat-option>
|
||||
</mat-select>
|
||||
<mat-hint class="mat-error" *ngIf="transitionError"><mat-icon class="warning-icon">warning</mat-icon> Starting and Ending State cannot be the same!</mat-hint>
|
||||
<mat-hint class="mat-error" *ngIf="!transitionError && transitionEndingStateError"> <mat-icon class="warning-icon">warning</mat-icon> Select a valid Ending State!</mat-hint>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="ending-state">
|
||||
<th mat-header-cell *matHeaderCellDef>Ending State</th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<span *ngIf="editedTransition !== transition">{{transition.endingState.stateLabel}}</span>
|
||||
<mat-form-field appearance="fill" class="long-form" *ngIf="editedTransition == transition">
|
||||
<mat-select [(ngModel)]="editedTransition!.endingState" (ngModelChange)="validateEditedTransition()">
|
||||
<mat-option *ngFor="let state of gamesystem!.states" [value]="state"
|
||||
(onSelectionChange)="validateEditedTransition()">{{state.stateLabel}}</mat-option>
|
||||
</mat-select>
|
||||
<mat-hint class="mat-error" *ngIf="transitionError"><mat-icon class="warning-icon">warning</mat-icon> Starting and Ending State cannot be the same!</mat-hint>
|
||||
<mat-hint class="mat-error" *ngIf="!transitionError && transitionEndingStateError"> <mat-icon class="warning-icon">warning</mat-icon> Select a valid Ending State!</mat-hint>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
|
||||
<div class="example-element-detail"
|
||||
[@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
|
||||
<p>Expanded Detail</p>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
|
||||
<div class="example-element-detail"
|
||||
[@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
|
||||
<p>Expanded Detail</p>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="edit">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<button mat-icon-button color="primary" *ngIf="editedTransition !== transition" [disabled]="editedTransition != undefined"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="primary" *ngIf="editedTransition === transition"
|
||||
[disabled]="transitionError || transitionStartingStateError || transitionEndingStateError" (click)="finishEditing()"
|
||||
><mat-icon>done</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="edit">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<button mat-icon-button color="primary" *ngIf="editedTransition !== transition" [disabled]="editedTransition != undefined"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="primary" *ngIf="editedTransition === transition"
|
||||
[disabled]="transitionError || transitionStartingStateError || transitionEndingStateError" (click)="finishEditing()"
|
||||
><mat-icon>done</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<button mat-icon-button color="warn" (click)="deleteTransition(transition)"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let transition">
|
||||
<button mat-icon-button color="warn" (click)="deleteTransition(transition)"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="expand">
|
||||
<th mat-header-cell *matHeaderCellDef aria-label="row actions">
|
||||
<button mat-icon-button (click)="addTransition()" [disabled]="editedTransition != undefined"><mat-icon>add</mat-icon></button>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-icon-button aria-label="expand row" (click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
|
||||
@if (expandedElement === element) {
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
} @else {
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="expand">
|
||||
<th mat-header-cell *matHeaderCellDef aria-label="row actions">
|
||||
<button mat-icon-button (click)="addTransition()" [disabled]="editedTransition != undefined"><mat-icon>add</mat-icon></button>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button mat-icon-button aria-label="expand row" (click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
|
||||
@if (expandedElement === element) {
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
} @else {
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
|
||||
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
|
||||
class="example-element-row"
|
||||
[class.example-expanded-row]="expandedElement === element"
|
||||
(click)="expandedElement = expandedElement === element ? null : element">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
|
||||
</table>
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
|
||||
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
|
||||
class="example-element-row"
|
||||
[class.example-expanded-row]="expandedElement === element"
|
||||
(click)="expandedElement = expandedElement === element ? null : element">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
|
||||
</table>
|
||||
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
@ -13,6 +13,8 @@ import {
|
||||
import {SimpleTransition} from "../../../../game-model/gamesystems/SimpleTransition";
|
||||
import {animate, state, style, transition, trigger} from "@angular/animations";
|
||||
import {SimpleState} from "../../../../game-model/gamesystems/SimpleState";
|
||||
import {ProductTransition} from "../../../../game-model/gamesystems/ProductTransition";
|
||||
import {LeafGamesystemCalculator} from "../../product-gamesystem-editor/LeafGamesystemCalculator";
|
||||
|
||||
@Component({
|
||||
selector: 'app-simple-transition-editor',
|
||||
@ -44,6 +46,9 @@ export class SimpleTransitionEditorComponent implements OnInit {
|
||||
transitionEndingStateError = true;
|
||||
ngOnInit() {
|
||||
this.dataSource.data = this.gamesystem!.transitions;
|
||||
this.dataSource.filterPredicate = (data: SimpleTransition, filter: string) => {
|
||||
return [data.startingState, data.endingState].some((state) => state.stateLabel.toLowerCase().includes(filter))
|
||||
}
|
||||
}
|
||||
|
||||
addTransition() {
|
||||
@ -83,4 +88,9 @@ export class SimpleTransitionEditorComponent implements OnInit {
|
||||
this.dataSource.data = this.gamesystem!.transitions;
|
||||
}
|
||||
}
|
||||
|
||||
applyFilter(event: KeyboardEvent) {
|
||||
const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
@ -38,5 +38,16 @@ export class ProductState extends State<ProductTransition> {
|
||||
return true;
|
||||
}
|
||||
|
||||
existsInnerStateByLowerCaseLabel(label: string): boolean {
|
||||
this.innerStates.forEach(innerState => {
|
||||
if(innerState instanceof SimpleState && innerState.stateLabel.toLowerCase() === label) {
|
||||
return true;
|
||||
} else if(innerState instanceof ProductState) {
|
||||
return innerState.existsInnerStateByLowerCaseLabel(label);
|
||||
}
|
||||
})
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,4 +3,7 @@ import {ProductState} from "./ProductState";
|
||||
|
||||
export class ProductTransition extends Transition<ProductState> {
|
||||
|
||||
containsInnerStateByLabel(label: string) {
|
||||
return this.startingState.existsInnerStateByLowerCaseLabel(label) || this.endingState.existsInnerStateByLowerCaseLabel(label);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user