diff --git a/projects/aas-portal/src/app/aas/aas.component.html b/projects/aas-portal/src/app/aas/aas.component.html
index cfebf37a..5c2dcc56 100644
--- a/projects/aas-portal/src/app/aas/aas.component.html
+++ b/projects/aas-portal/src/app/aas/aas.component.html
@@ -76,10 +76,10 @@
-
diff --git a/projects/aas-portal/src/app/aas/aas.component.ts b/projects/aas-portal/src/app/aas/aas.component.ts
index b9c2ac4a..b4109c58 100644
--- a/projects/aas-portal/src/app/aas/aas.component.ts
+++ b/projects/aas-portal/src/app/aas/aas.component.ts
@@ -90,13 +90,9 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
public readonly selectedElements = signal([]);
- public get canUndo(): boolean {
- return this.commandHandler.canUndo;
- }
+ public readonly canUndo = this.commandHandler.canUndo;
- public get canRedo(): boolean {
- return this.commandHandler.canRedo;
- }
+ public readonly canRedo = this.commandHandler.canRedo;
public readonly canPlay = computed(() => {
const state = this.store.state();
diff --git a/projects/aas-portal/src/app/aas/command-handler.service.ts b/projects/aas-portal/src/app/aas/command-handler.service.ts
index 261df29b..25399bc7 100644
--- a/projects/aas-portal/src/app/aas/command-handler.service.ts
+++ b/projects/aas-portal/src/app/aas/command-handler.service.ts
@@ -6,7 +6,7 @@
*
*****************************************************************************/
-import { Injectable } from '@angular/core';
+import { Injectable, computed, signal } from '@angular/core';
import { NotifyService } from 'aas-lib';
import { Command } from '../types/command';
@@ -14,8 +14,8 @@ import { Command } from '../types/command';
providedIn: 'root',
})
export class CommandHandlerService {
- private commands: Array = [];
- private position = -1;
+ private readonly commands = signal([]);
+ private readonly position = signal(-1);
public constructor(private notify: NotifyService) {}
@@ -27,30 +27,26 @@ export class CommandHandlerService {
try {
command.execute();
- if (this.commands.length > 0 && this.position < this.commands.length - 1) {
- this.commands.splice(this.position + 1);
+ if (this.commands().length > 0 && this.position() < this.commands().length - 1) {
+ this.commands.update(values => values.filter((_, i) => i <= this.position()));
}
- this.commands.push(command);
- ++this.position;
+ this.commands.update(values => [...values, command]);
+ this.position.update(value => value + 1);
} catch (error) {
command.abort();
throw error;
}
}
- public get canUndo(): boolean {
- return this.position >= 0;
- }
+ public readonly canUndo = computed(() => this.position() >= 0);
- public get canRedo(): boolean {
- return this.position + 1 < this.commands.length;
- }
+ public readonly canRedo = computed(() => this.position() + 1 < this.commands().length);
public undo(): void {
try {
- this.commands[this.position].undo();
- --this.position;
+ this.commands()[this.position()].undo();
+ this.position.update(value => value - 1);
} catch (error) {
this.notify.error(error);
}
@@ -58,15 +54,15 @@ export class CommandHandlerService {
public redo(): void {
try {
- ++this.position;
- this.commands[this.position].redo();
+ this.position.update(value => value + 1);
+ this.commands()[this.position()].redo();
} catch (error) {
this.notify.error(error);
}
}
public clear(): void {
- this.commands = [];
- this.position = -1;
+ this.commands.set([]);
+ this.position.set(-1);
}
}
diff --git a/projects/aas-portal/src/app/dashboard/dashboard.component.ts b/projects/aas-portal/src/app/dashboard/dashboard.component.ts
index 5f9abcf1..3ab47d39 100644
--- a/projects/aas-portal/src/app/dashboard/dashboard.component.ts
+++ b/projects/aas-portal/src/app/dashboard/dashboard.component.ts
@@ -175,6 +175,10 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit, Aft
public readonly selectionMode = this.dashboard.selectionMode.asReadonly();
+ public readonly canUndo = computed(() => this.editMode() && this.commandHandler.canUndo());
+
+ public readonly canRedo = computed(() => this.editMode() && this.commandHandler.canRedo());
+
public ngOnInit(): void {
this.commandHandler.clear();
@@ -455,20 +459,12 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit, Aft
}
}
- public canUndo(): boolean {
- return this.editMode() && this.commandHandler.canUndo;
- }
-
public undo(): void {
if (this.canUndo()) {
this.commandHandler.undo();
}
}
- public canRedo(): boolean {
- return this.editMode() && this.commandHandler.canRedo;
- }
-
public redo(): void {
if (this.canRedo()) {
this.commandHandler.redo();
diff --git a/projects/aas-portal/src/test/aas/aas.component.spec.ts b/projects/aas-portal/src/test/aas/aas.component.spec.ts
index 1d48184c..2cfe41d5 100644
--- a/projects/aas-portal/src/test/aas/aas.component.spec.ts
+++ b/projects/aas-portal/src/test/aas/aas.component.spec.ts
@@ -24,7 +24,7 @@ import { provideHttpClientTesting } from '@angular/common/http/testing';
import { DashboardPage, DashboardService } from '../../app/dashboard/dashboard.service';
import { DashboardChartType } from '../../app/dashboard/dashboard.service';
import { Router, provideRouter } from '@angular/router';
-import { Component, Input, input, output, signal } from '@angular/core';
+import { Component, input, output, signal } from '@angular/core';
import { AASApiService } from '../../app/aas/aas-api.service';
import { ToolbarService } from '../../app/toolbar.service';
import { AASStore } from '../../app/aas/aas.store';
@@ -58,16 +58,11 @@ class TestAASTreeComponent {
standalone: true,
})
class TestSecureImageComponent {
- @Input()
- public src = '';
- @Input()
- public alt?: string;
- @Input()
- public classname?: string;
- @Input()
- public width = -1;
- @Input()
- public height = -1;
+ public readonly src = input.required();
+ public readonly alt = input();
+ public readonly classname = input();
+ public readonly width = input();
+ public readonly height = input();
}
describe('AASComponent', () => {
diff --git a/projects/aas-portal/src/test/aas/command-handler.service.spec.ts b/projects/aas-portal/src/test/aas/command-handler.service.spec.ts
index 3c022b55..b1634bf1 100644
--- a/projects/aas-portal/src/test/aas/command-handler.service.spec.ts
+++ b/projects/aas-portal/src/test/aas/command-handler.service.spec.ts
@@ -88,41 +88,41 @@ describe('CommandHandlerService', () => {
expect(service).toBeTruthy();
});
- it('indicates that undo is not possible', function () {
- expect(service.canUndo).toBeFalse();
+ it('indicates that undo is not possible', () => {
+ expect(service.canUndo()).toBeFalse();
});
- it('indicates that redo is not possible', function () {
- expect(service.canRedo).toBeFalse();
+ it('indicates that redo is not possible', () => {
+ expect(service.canRedo()).toBeFalse();
});
- it('can execute a command', function () {
+ it('can execute a command', () => {
const spy = jasmine.createSpy('execute');
service.execute(new TestCommand(spy));
expect(spy).toHaveBeenCalled();
});
- it('can undo/redo a command', function () {
+ it('can undo/redo a command', () => {
const undoSpy = jasmine.createSpy('undo');
const redoSpy = jasmine.createSpy('redo');
service.execute(new TestCommand(undefined, undoSpy, redoSpy));
- expect(service.canUndo).toBeTrue();
+ expect(service.canUndo()).toBeTrue();
service.undo();
expect(undoSpy).toHaveBeenCalled();
- expect(service.canRedo).toBeTrue();
+ expect(service.canRedo()).toBeTrue();
service.redo();
expect(redoSpy).toHaveBeenCalled();
});
- it('clears the undo/redo stack', function () {
+ it('clears the undo/redo stack', () => {
service.execute(new TestCommand());
service.execute(new TestCommand());
service.clear();
- expect(service.canUndo).toBeFalse();
- expect(service.canRedo).toBeFalse();
+ expect(service.canUndo()).toBeFalse();
+ expect(service.canRedo()).toBeFalse();
});
- it('aborts a failed command', function () {
+ it('aborts a failed command', () => {
const abortSpy = jasmine.createSpy('abort');
expect(() => service.execute(new FailCommand(abortSpy))).toThrowError();
expect(abortSpy).toHaveBeenCalled();