@@ -103,4 +104,7 @@
-
\ No newline at end of file
+
+} @else {
+
Kein Document
+}
\ No newline at end of file
diff --git a/projects/aas-portal/src/app/aas/aas.component.ts b/projects/aas-portal/src/app/aas/aas.component.ts
index 38252b4d..b7f58d7e 100644
--- a/projects/aas-portal/src/app/aas/aas.component.ts
+++ b/projects/aas-portal/src/app/aas/aas.component.ts
@@ -153,10 +153,12 @@ export class AASComponent implements OnInit, OnDestroy, AfterViewInit {
if (params) {
const document: AASDocument = this.clipboard.get('AASDocument');
- if (!document || !document.content) {
+ if (!document) {
this.store.dispatch(AASActions.getDocument({ id: params.id, name: params.endpoint }));
+ } else if (!document.content) {
+ this.store.dispatch(AASActions.getDocumentContent({ document: document }));
} else {
- this.store.dispatch(AASActions.setDocument({ document: document }));
+ this.store.dispatch(AASActions.setDocument({ document }));
}
}
}),
diff --git a/projects/aas-portal/src/app/aas/aas.effects.ts b/projects/aas-portal/src/app/aas/aas.effects.ts
index 3c176f87..58ecaf22 100644
--- a/projects/aas-portal/src/app/aas/aas.effects.ts
+++ b/projects/aas-portal/src/app/aas/aas.effects.ts
@@ -8,7 +8,7 @@
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
-import { exhaustMap, map } from 'rxjs';
+import { catchError, exhaustMap, map, of } from 'rxjs';
import * as AASActions from './aas.actions';
import { AASApiService } from './aas-api.service';
@@ -24,9 +24,22 @@ export class AASEffects {
return this.actions.pipe(
ofType
(AASActions.AASActionType.GET_DOCUMENT),
exhaustMap(action =>
- this.api
- .getDocument(action.id, action.name)
- .pipe(map(document => AASActions.setDocument({ document }))),
+ this.api.getDocument(action.id, action.name).pipe(
+ map(document => AASActions.setDocument({ document })),
+ catchError(() => of(AASActions.setDocument({ document: null }))),
+ ),
+ ),
+ );
+ });
+
+ public getDocumentContent = createEffect(() => {
+ return this.actions.pipe(
+ ofType(AASActions.AASActionType.GET_DOCUMENT_CONTENT),
+ exhaustMap(action =>
+ this.api.getContent(action.document.id, action.document.endpoint).pipe(
+ map(content => AASActions.setDocument({ document: { ...action.document, content } })),
+ catchError(() => of(AASActions.setDocument({ document: action.document }))),
+ ),
),
);
});
diff --git a/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.html b/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.html
index 4d1609d4..7540fe65 100644
--- a/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.html
+++ b/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.html
@@ -29,20 +29,23 @@
autocomplete="false" (change)="selected($event.target, item)" [checked]="item.selected">
-
+ @if(item.selected && text) {
+
{{text}}
+ }
}
\ No newline at end of file
diff --git a/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.ts b/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.ts
index cac72d4d..7e16f29e 100644
--- a/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.ts
+++ b/projects/aas-portal/src/app/start/favorites-form/favorites-form.component.ts
@@ -8,7 +8,7 @@
import { Component } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
-import { AASDocument, ApplicationError } from 'common';
+import { AASDocument, ApplicationError, stringFormat } from 'common';
import { FavoritesService } from '../favorites.service';
import { first, from, map, mergeMap, of, tap } from 'rxjs';
import { messageToString } from 'aas-lib';
@@ -80,6 +80,18 @@ export class FavoritesFormComponent {
return this._items.filter(item => item.delete === false);
}
+ public get text(): string {
+ if (this.documents.length === 0) {
+ return '';
+ }
+
+ if (this.documents.length === 1) {
+ return this.translate.instant('TEXT_ADD_FAVORITE');
+ }
+
+ return stringFormat(this.translate.instant('TEXT_ADD_FAVORITES'), this.documents.length);
+ }
+
public delete(item: FavoritesItem): void {
if (item.added) {
this._items.splice(this._items.indexOf(item), 1);
@@ -88,12 +100,13 @@ export class FavoritesFormComponent {
}
}
- public add(sibling: FavoritesItem): void {
+ public addNew(): void {
const name = this.uniqueName();
- this._items.splice(this.items.indexOf(sibling) + 1, 0, {
+ this._items.forEach(i => (i.selected = false));
+ this._items.push({
name: name,
id: name,
- selected: false,
+ selected: true,
active: false,
added: true,
delete: false,
diff --git a/projects/aas-portal/src/app/start/start-api.service.ts b/projects/aas-portal/src/app/start/start-api.service.ts
index fa161988..3861b37e 100644
--- a/projects/aas-portal/src/app/start/start-api.service.ts
+++ b/projects/aas-portal/src/app/start/start-api.service.ts
@@ -79,13 +79,13 @@ export class StartApiService {
/**
* Loads the element structure of the specified document.
- * @param endpointName The URL of the container.
+ * @param endpoint The endpoint name.
* @param id The identification of the AAS document.
* @returns The root of the element structure.
*/
- public getContent(endpointName: string, id: string): Observable
{
+ public getContent(endpoint: string, id: string): Observable {
return this.http.get(
- `/api/v1/containers/${encodeBase64Url(endpointName)}/documents/${encodeBase64Url(id)}/content`,
+ `/api/v1/containers/${encodeBase64Url(endpoint)}/documents/${encodeBase64Url(id)}/content`,
);
}
diff --git a/projects/aas-portal/src/app/start/start.component.html b/projects/aas-portal/src/app/start/start.component.html
index 7a0706d2..35c44079 100644
--- a/projects/aas-portal/src/app/start/start.component.html
+++ b/projects/aas-portal/src/app/start/start.component.html
@@ -16,8 +16,8 @@
-
+
+
+
+
+
+
+
+
@@ -78,12 +85,12 @@
+ (change)="setViewMode('list').subscribe()" [checked]="(viewMode | async) === 'list'">
+ (change)="setViewMode('tree').subscribe()" [checked]="(viewMode | async) === 'tree'">
diff --git a/projects/aas-portal/src/app/start/start.component.ts b/projects/aas-portal/src/app/start/start.component.ts
index 5d1b92f0..7eb7e49b 100644
--- a/projects/aas-portal/src/app/start/start.component.ts
+++ b/projects/aas-portal/src/app/start/start.component.ts
@@ -50,7 +50,6 @@ export class StartComponent implements OnDestroy, AfterViewInit {
private readonly subscription = new Subscription();
private readonly someSelectedDocuments = new BehaviorSubject(true);
private _selected: AASDocument[] = [];
- private _currentFavorites = '';
public constructor(
store: Store,
@@ -75,6 +74,7 @@ export class StartComponent implements OnDestroy, AfterViewInit {
this.isLastPage = this.store.select(StartSelectors.selectIsLastPage);
this.documents = this.store.select(StartSelectors.selectDocuments);
this.viewMode = this.store.select(StartSelectors.selectViewMode);
+ this.currentFavorites = this.store.select(StartSelectors.selectCurrentFavorites);
this.endpoints = this.api.getEndpoints();
this.store
@@ -89,37 +89,12 @@ export class StartComponent implements OnDestroy, AfterViewInit {
next: () => this.store.dispatch(StartActions.getFirstPage({})),
error: error => this.notify.error(error),
});
-
- this.subscription.add(
- this.store
- .select(StartSelectors.selectCurrentFavorites)
- .pipe()
- .subscribe(value => (this._currentFavorites = value)),
- );
}
@ViewChild('startToolbar', { read: TemplateRef })
public startToolbar: TemplateRef | null = null;
- public get currentFavorites(): string {
- return this._currentFavorites;
- }
-
- public set currentFavorites(value: string) {
- if (value !== this._currentFavorites) {
- const currentFavorites = this.favorites.get(value);
- if (currentFavorites) {
- this.store.dispatch(
- StartActions.getFavorites({
- name: currentFavorites.name,
- documents: currentFavorites.documents,
- }),
- );
- } else {
- this.store.dispatch(StartActions.getFirstPage({}));
- }
- }
- }
+ public readonly currentFavorites: Observable;
public readonly favoritesLists: Observable = this.favorites.lists.pipe(
map(lists => ['', ...lists.map(list => list.name)]),
@@ -179,26 +154,45 @@ export class StartComponent implements OnDestroy, AfterViewInit {
this.subscription.unsubscribe();
}
- public setViewMode(viewMode: string | ViewMode): void {
- if (viewMode === ViewMode.List) {
- if (!this._currentFavorites) {
- this.store.dispatch(StartActions.setListView());
- } else {
- const favoritesList = this.favorites.get(this._currentFavorites);
- if (favoritesList) {
- this.store.dispatch(
- StartActions.getFavorites({
- name: favoritesList.name,
- documents: favoritesList.documents,
- }),
- );
- }
- }
+ public setCurrentFavorites(value: string): void {
+ const currentFavorites = this.favorites.get(value);
+ if (currentFavorites) {
+ this.store.dispatch(
+ StartActions.getFavorites({
+ name: currentFavorites.name,
+ documents: currentFavorites.documents,
+ }),
+ );
} else {
- this.store.dispatch(StartActions.setTreeView({ documents: this._selected }));
+ this.store.dispatch(StartActions.getFirstPage({}));
}
}
+ public setViewMode(viewMode: string | ViewMode): Observable {
+ return this.currentFavorites.pipe(
+ first(),
+ map(currentFavorites => {
+ if (viewMode === ViewMode.List) {
+ if (!currentFavorites) {
+ this.store.dispatch(StartActions.setListView());
+ } else {
+ const favoritesList = this.favorites.get(currentFavorites);
+ if (favoritesList) {
+ this.store.dispatch(
+ StartActions.getFavorites({
+ name: favoritesList.name,
+ documents: favoritesList.documents,
+ }),
+ );
+ }
+ }
+ } else {
+ this.store.dispatch(StartActions.setTreeView({ documents: this._selected }));
+ }
+ }),
+ );
+ }
+
public addEndpoint(): Observable {
return this.auth.ensureAuthorized('editor').pipe(
mergeMap(() => this.api.getEndpoints()),
@@ -284,26 +278,28 @@ export class StartComponent implements OnDestroy, AfterViewInit {
return EMPTY;
}
- if (!this._currentFavorites) {
- return this.auth.ensureAuthorized('editor').pipe(
- map(() =>
- this.window.confirm(
- stringFormat(
- this.translate.instant('CONFIRM_DELETE_DOCUMENT'),
- this._selected.map(item => item.idShort).join(', '),
+ return this.currentFavorites.pipe(
+ first(),
+ mergeMap(currentFavorites => {
+ if (currentFavorites) {
+ this.favorites.remove(this._selected, currentFavorites);
+ this.store.dispatch(StartActions.removeFavorites({ favorites: [...this._selected] }));
+ return of(void 0);
+ } else {
+ return this.auth.ensureAuthorized('editor').pipe(
+ map(() =>
+ this.window.confirm(
+ stringFormat(
+ this.translate.instant('CONFIRM_DELETE_DOCUMENT'),
+ this._selected.map(item => item.idShort).join(', '),
+ ),
+ ),
),
- ),
- ),
- mergeMap(result => from(result ? this._selected : [])),
- mergeMap(document => this.api.delete(document.id, document.endpoint)),
- catchError(error => this.notify.error(error)),
- );
- }
-
- return of(this._currentFavorites).pipe(
- map(list => {
- this.favorites.remove(this._selected, list);
- this.store.dispatch(StartActions.removeFavorites({ favorites: [...this._selected] }));
+ mergeMap(result => from(result ? this._selected : [])),
+ mergeMap(document => this.api.delete(document.id, document.endpoint)),
+ catchError(error => this.notify.error(error)),
+ );
+ }
}),
);
}
@@ -373,8 +369,8 @@ export class StartComponent implements OnDestroy, AfterViewInit {
}
}
- public setLimit(limit: number): void {
- this.store.dispatch(StartActions.getFirstPage({ limit }));
+ public setLimit(value: string | number): void {
+ this.store.dispatch(StartActions.getFirstPage({ limit: Number(value) }));
}
public firstPage(): void {
diff --git a/projects/aas-portal/src/assets/i18n/de-de.json b/projects/aas-portal/src/assets/i18n/de-de.json
index 1826ebdf..8ea3af01 100644
--- a/projects/aas-portal/src/assets/i18n/de-de.json
+++ b/projects/aas-portal/src/assets/i18n/de-de.json
@@ -51,6 +51,7 @@
"CMD_DELETE_USER": "Benutzerkonto löschen...",
"CMD_VIEW_USER_FEEDBACK": "Nutzer-Feedback",
"CMD_VIEW_NAMEPLATE": "Typenschild",
+ "CMD_ADD_NEW_FAVORITES_LIST": "Neue Favoritenliste",
"COLUMN_VARIANT": "Variante",
"COLUMN_NAME": "Name",
"COLUMN_MODEL_TYPE": "Modeltyp",
@@ -165,6 +166,8 @@
"OPTION_TIMELINE_CHART": "Zeitdiagramm",
"OPTION_BAR_VERTICAL_CHART": "Balkendiagramm vertikal",
"OPTION_BAR_HORIZONTAL_CHART": "Balkendiagramm horizontal",
+ "TEXT_ADD_FAVORITE": "1 Favorit hinzufügen",
+ "TEXT_ADD_FAVORITES": "{0} Favoriten hinzufügen",
"AASEndpointType": {
"FileSystem": "Verzeichnis",
"AASServer": "AAS-Server",
diff --git a/projects/aas-portal/src/assets/i18n/en-us.json b/projects/aas-portal/src/assets/i18n/en-us.json
index 8f631932..e055aa0b 100644
--- a/projects/aas-portal/src/assets/i18n/en-us.json
+++ b/projects/aas-portal/src/assets/i18n/en-us.json
@@ -51,6 +51,7 @@
"CMD_DELETE_USER": "Delete user account...",
"CMD_VIEW_USER_FEEDBACK": "User feedback",
"CMD_VIEW_NAMEPLATE": "Nameplate",
+ "CMD_ADD_NEW_FAVORITES_LIST": "New favorites list",
"COLUMN_NAME": "Name",
"COLUMN_MODEL_TYPE": "Model type",
"COLUMN_SIZE": "Size",
@@ -165,6 +166,8 @@
"OPTION_TIMELINE_CHART": "Timeline chart",
"OPTION_BAR_VERTICAL_CHART": "Vertical bar chart",
"OPTION_BAR_HORIZONTAL_CHART": "Horizontal bar chart",
+ "TEXT_ADD_FAVORITE": "Add 1 favorite",
+ "TEXT_ADD_FAVORITES": "Add {0} favorites",
"AASEndpointType": {
"FileSystem": "File system",
"AASServer": "AAS server",
diff --git a/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts b/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts
index bc051de8..1baf66a0 100644
--- a/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts
+++ b/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts
@@ -14,22 +14,16 @@ import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-tran
import { RemoveEndpointFormComponent } from '../../app/start/remove-endpoint-form/remove-endpoint-form.component';
-
describe('RemoveEndpointFormComponent', () => {
let component: RemoveEndpointFormComponent;
let fixture: ComponentFixture;
- let submitButton: HTMLButtonElement;
let modal: NgbActiveModal;
let form: HTMLFormElement;
beforeEach(() => {
TestBed.configureTestingModule({
- declarations: [
- RemoveEndpointFormComponent
- ],
- providers: [
- NgbActiveModal
- ],
+ declarations: [RemoveEndpointFormComponent],
+ providers: [NgbActiveModal],
imports: [
CommonModule,
FormsModule,
@@ -37,11 +31,10 @@ describe('RemoveEndpointFormComponent', () => {
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
- useClass: TranslateFakeLoader
- }
- })
-
- ]
+ useClass: TranslateFakeLoader,
+ },
+ }),
+ ],
});
fixture = TestBed.createComponent(RemoveEndpointFormComponent);
@@ -49,14 +42,13 @@ describe('RemoveEndpointFormComponent', () => {
component.endpoints = [
{ name: 'Samples', url: 'http://localhost:1234', selected: false },
{ name: 'I4AAS Server', url: 'http://localhost:1235', selected: false },
- { name: 'AAS Registry', url: 'http://localhost:1236', selected: false }
+ { name: 'AAS Registry', url: 'http://localhost:1236', selected: false },
];
fixture.detectChanges();
modal = TestBed.inject(NgbActiveModal);
form = fixture.debugElement.nativeElement.querySelector('form');
- submitButton = fixture.debugElement.nativeElement.querySelector('button[type="submit"]');
});
it('should create', () => {
@@ -78,10 +70,10 @@ describe('RemoveEndpointFormComponent', () => {
expect(modal.close).toHaveBeenCalled();
});
- it('allows deleting the "Samples" registry', function () {
+ it('?allows deleting the "Samples" registry', function () {
spyOn(modal, 'close');
form.dispatchEvent(new Event('submit'));
expect(modal.close).toHaveBeenCalledTimes(0);
expect(component.messages.length > 0).toBeTrue();
});
-});
\ No newline at end of file
+});