Skip to content

Commit

Permalink
fix: dashboard updated
Browse files Browse the repository at this point in the history
  • Loading branch information
ralfaron committed Nov 24, 2024
1 parent 6fd0ca7 commit f0844b8
Show file tree
Hide file tree
Showing 30 changed files with 700 additions and 769 deletions.
7 changes: 3 additions & 4 deletions projects/aas-portal/src/app/aas/aas.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@
</button>
</div>
<div class="input-group me-2 my-1">
<select #select class="form-select" [value]="dashboardPage()"
(change)="setDashboardPage(dashboardPages()[select.selectedIndex])">
@for (page of dashboardPages(); track page.name) {
<option [ngValue]="page">{{page.name}}</option>
<select class="form-select" [(ngModel)]="dashboardPage">
@for (page of dashboardPages(); track page) {
<option [ngValue]="page">{{page}}</option>
}
</select>
<button type="button" class="btn btn-primary" (click)="addToDashboard('Line')"
Expand Down
131 changes: 76 additions & 55 deletions projects/aas-portal/src/app/aas/aas.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
*
*****************************************************************************/

import head from 'lodash-es/head';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { FormsModule } from '@angular/forms';
import { EMPTY, map, mergeMap, Observable, from, of, catchError, first } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {
AfterViewInit,
ChangeDetectionStrategy,
Expand All @@ -15,13 +21,10 @@ import {
TemplateRef,
ViewChild,
computed,
signal,
effect,
model,
} from '@angular/core';

import { ActivatedRoute, Router } from '@angular/router';
import { EMPTY, map, mergeMap, Observable, from, of, catchError, first } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import head from 'lodash-es/head';
import { aas, isProperty, isNumberType, isBlob, AASDocument } from 'aas-core';
import {
AASTreeComponent,
Expand All @@ -39,12 +42,11 @@ import { DeleteCommand } from './commands/delete-command';
import { NewElementCommand } from './commands/new-element-command';
import { AASApiService } from './aas-api.service';
import { NewElementFormComponent } from './new-element-form/new-element-form.component';
import { DashboardChartType, DashboardPage, DashboardService } from '../dashboard/dashboard.service';
import { DashboardService } from '../dashboard/dashboard.service';
import { DashboardQuery } from '../types/dashboard-query-params';
import { ToolbarService } from '../toolbar.service';
import { AASStore } from './aas.store';
import { TranslateModule } from '@ngx-translate/core';
import { FormsModule } from '@angular/forms';
import { DashboardChartType } from '../dashboard/dashboard.store';

@Component({
selector: 'fhg-aas',
Expand All @@ -68,55 +70,65 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
private readonly toolbar: ToolbarService,
private readonly auth: AuthService,
private readonly clipboard: ClipboardService,
) {}
) {
effect(
() => {
const value = this.dashboardPage();
if (value !== this.dashboard.activePage()) {
this.dashboard.setPage(value);
}
},
{ allowSignalWrites: true },
);
}

@ViewChild('aasToolbar', { read: TemplateRef })
public aasToolbar: TemplateRef<unknown> | null = null;

public readonly document = this.store.document;
public readonly dashboardPage = model<string>(this.dashboard.activePage());

public readonly address = computed(() => this.store.document()?.address ?? '-');
public readonly address = computed(() => this.store.document$()?.address ?? '-');

public readonly idShort = computed(() => this.store.document()?.idShort ?? '-');
public readonly idShort = computed(() => this.store.document$()?.idShort ?? '-');

public readonly id = computed(() => this.store.document()?.id ?? '-');
public readonly id = computed(() => this.store.document$()?.id ?? '-');

public readonly assetId = computed(() => this.store.document()?.assetId ?? '-');
public readonly assetId = computed(() => this.store.document$()?.assetId ?? '-');

public readonly thumbnail = computed(() => this.store.document()?.thumbnail ?? '-');
public readonly thumbnail = computed(() => this.store.document$()?.thumbnail ?? '-');

public readonly readOnly = computed(() => this.store.document()?.readonly ?? false);
public readonly readOnly = computed(() => this.store.document$()?.readonly ?? false);

public readonly version = computed(() =>
this.versionToString(head(this.store.document()?.content?.assetAdministrationShells)?.administration),
this.versionToString(head(this.store.document$()?.content?.assetAdministrationShells)?.administration),
);

public readonly state = this.store.state;
public readonly document = this.store.document$;

public readonly searchExpression = this.store.searchExpression;
public readonly state = this.store.state$;

public readonly dashboardPages = this.dashboard.pages;
public readonly searchExpression = this.store.searchExpression$;

public readonly dashboardPage = this.dashboard.activePage;
public readonly dashboardPages = this.dashboard.pages;

public readonly selectedElements = signal<aas.Referable[]>([]);
public readonly selectedElements = this.store.selectedElements$;

public readonly canUndo = this.commandHandler.canUndo;

public readonly canRedo = this.commandHandler.canRedo;

public readonly canPlay = computed(() => {
const state = this.store.state();
return (this.store.document()?.onlineReady ?? false) && state === 'offline';
const state = this.store.state$();
return (this.store.document$()?.onlineReady ?? false) && state === 'offline';
});

public readonly canStop = computed(() => {
const state = this.store.state();
return (this.store.document()?.onlineReady ?? false) && state === 'online';
const state = this.store.state$();
return (this.store.document$()?.onlineReady ?? false) && state === 'online';
});

public readonly canSynchronize = computed(() => {
const document = this.store.document();
const document = this.store.document$();
return document != null && !document.readonly && document.modified ? document.modified : false;
});

Expand All @@ -142,17 +154,17 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
public ngOnInit(): void {
this.route.queryParams.pipe(first()).subscribe(params => {
if (params?.search) {
this.store.searchExpression.set(params.search);
this.store.searchExpression$.set(params.search);
}

if (params) {
const document: AASDocument = this.clipboard.get('AASDocument');
if (!document) {
this.store.getDocument(params.id, params.endpoint);
this.getDocument(params.id, params.endpoint);
} else if (!document.content) {
this.store.getDocumentContent(document);
this.getDocumentContent(document);
} else {
this.store.setDocument(document);
this.store.document$.set(document);
}
}
});
Expand All @@ -169,32 +181,28 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
}

public play(): void {
this.store.state.set('online');
this.store.state$.set('online');
}

public stop(): void {
this.store.state.set('offline');
}

public setDashboardPage(page: DashboardPage): void {
this.dashboard.setPage(page);
this.store.state$.set('offline');
}

public addToDashboard(chartType: string): void {
const document = this.store.document();
const document = this.store.document;
const page = this.dashboard.activePage();
if (!document || !page) {
return;
}

this.dashboard.add(page, document, this.selectedElements(), chartType as DashboardChartType);
this.clipboard.set('DashboardQuery', { page: this.dashboardPage().name } as DashboardQuery);
this.dashboard.add(page, document, this.store.selectedElements, chartType as DashboardChartType);
this.clipboard.set('DashboardQuery', { page: this.dashboardPage() } as DashboardQuery);
this.router.navigateByUrl('/dashboard?format=DashboardQuery', { skipLocationChange: true });
}

public synchronize(): Observable<void> {
return this.auth.ensureAuthorized('editor').pipe(
map(() => this.store.document()),
map(() => this.store.document),
mergeMap(document => {
if (!document) {
return EMPTY;
Expand All @@ -206,7 +214,7 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
this.notify.info(messages.join('\r\n'));
}

this.store.resetModified(document);
this.store.document$.set({ ...document, modified: false });
}),
);
}),
Expand All @@ -224,21 +232,21 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {

public newElement(): Observable<void> {
return this.auth.ensureAuthorized('editor').pipe(
map(() => this.store.document()),
map(() => this.store.document),
mergeMap(document => {
if (!document || this.selectedElements().length !== 1) {
if (!document || this.store.selectedElements.length !== 1) {
return EMPTY;
}

return of(this.modal.open(NewElementFormComponent, { backdrop: 'static' })).pipe(
mergeMap(modalRef => {
modalRef.componentInstance.initialize(document.content, this.selectedElements()[0]);
modalRef.componentInstance.initialize(document.content, this.store.selectedElements[0]);
return from<Promise<aas.Referable | undefined>>(modalRef.result);
}),
map(result => {
if (result) {
this.commandHandler.execute(
new NewElementCommand(this.store, document, this.selectedElements()[0], result),
new NewElementCommand(this.store, document, this.store.selectedElements[0], result),
);
}
}),
Expand All @@ -250,21 +258,21 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {

public editElement(): Observable<void> {
return this.auth.ensureAuthorized('editor').pipe(
map(() => this.store.document()),
map(() => this.store.document$()),
mergeMap(document => {
if (!document || this.selectedElements().length !== 1) {
if (!document || this.store.selectedElements.length !== 1) {
return EMPTY;
}

return of(this.modal.open(EditElementFormComponent, { backdrop: 'static' })).pipe(
mergeMap(modalRef => {
modalRef.componentInstance.initialize(this.selectedElements()[0]);
modalRef.componentInstance.initialize(this.store.selectedElements[0]);
return from<Promise<aas.SubmodelElement | undefined>>(modalRef.result);
}),
map(result => {
if (result) {
this.commandHandler.execute(
new UpdateElementCommand(this.store, document, this.selectedElements()[0], result),
new UpdateElementCommand(this.store, document, this.store.selectedElements[0], result),
);
}
}),
Expand All @@ -276,18 +284,18 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {

public deleteElement(): Observable<void> {
return this.auth.ensureAuthorized('editor').pipe(
map(() => this.store.document()),
map(() => this.store.document),
map(document => {
if (document && this.selectedElements().length > 0) {
this.commandHandler.execute(new DeleteCommand(this.store, document, this.selectedElements()));
if (document && this.store.selectedElements.length > 0) {
this.commandHandler.execute(new DeleteCommand(this.store, document, this.store.selectedElements));
}
}),
catchError(error => this.notify.error(error)),
);
}

public downloadDocument(): Observable<void> {
return of(this.store.document()).pipe(
return of(this.store.document).pipe(
mergeMap(document => {
if (!document) {
return EMPTY;
Expand All @@ -300,7 +308,7 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
}

public searchExpressionChange(value: string): void {
this.store.searchExpression.set(value);
this.store.searchExpression$.set(value);
}

private isNumberProperty(element: aas.Referable): boolean {
Expand All @@ -321,6 +329,19 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
);
}

private getDocumentContent(document: AASDocument): void {
this.api.getContent(document.id, document.endpoint).subscribe({
next: content => this.store.document$.set({ ...document, content }),
error: () => this.store.document$.set(document),
});
}

private getDocument(id: string, endpoint: string): void {
this.api.getDocument(id, endpoint).subscribe({
next: document => this.store.document$.set(document),
});
}

private versionToString(administration?: aas.AdministrativeInformation): string {
let version: string = administration?.version ?? '';
const revision: string = administration?.revision ?? '';
Expand Down
40 changes: 14 additions & 26 deletions projects/aas-portal/src/app/aas/aas.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,35 @@
*
*****************************************************************************/

import { Injectable, signal } from '@angular/core';
import { Injectable, signal, untracked } from '@angular/core';
import { OnlineState } from 'aas-lib';
import { AASDocument } from 'aas-core';
import { AASApiService } from './aas-api.service';
import { aas, AASDocument } from 'aas-core';

@Injectable({
providedIn: 'root',
})
export class AASStore {
private readonly _document = signal<AASDocument | null>(null);
public readonly document$ = signal<AASDocument | null>(null);

public constructor(private readonly api: AASApiService) {}
public readonly state$ = signal<OnlineState>('offline');

public readonly document = this._document.asReadonly();
public readonly searchExpression$ = signal('');

public readonly state = signal<OnlineState>('offline');
public readonly selectedElements$ = signal<aas.Referable[]>([]);

public readonly searchExpression = signal('');

public getDocumentContent(document: AASDocument): void {
this.api.getContent(document.id, document.endpoint).subscribe({
next: content => this._document.set({ ...document, content }),
error: () => this._document.set(document),
});
}

public getDocument(id: string, endpoint: string): void {
this.api.getDocument(id, endpoint).subscribe({
next: document => this._document.set(document),
});
public get document(): AASDocument | null {
return untracked(this.document$);
}

public setDocument(document: AASDocument | null): void {
this._document.set(document);
public get state(): OnlineState {
return untracked(this.state$);
}

public applyDocument(document: AASDocument): void {
this._document.set({ ...document, modified: true });
public get searchExpression(): string {
return untracked(this.searchExpression$);
}

public resetModified(document: AASDocument): void {
this._document.set({ ...document, modified: false });
public get selectedElements(): aas.Referable[] {
return untracked(this.selectedElements$);
}
}
Loading

0 comments on commit f0844b8

Please sign in to comment.