From be0f81cf51f71ba2dd83e5b5acb2e88b77210024 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 15 Dec 2020 17:38:34 +0100 Subject: [PATCH] Feature/nav improvement (#611) * feature improvement * Routing improvements. * Run all tests. * Many simplifications. * Binding fix. * Grid fix. * Build fixes. --- .../pages/cluster/cluster-page.component.ts | 5 - .../event-consumer.component.ts | 2 +- .../pages/users/users-page.component.html | 4 +- .../pages/users/users-page.component.ts | 11 +- .../administration/state/users.state.spec.ts | 17 -- .../administration/state/users.state.ts | 15 +- .../pages/graphql/graphql-page.component.ts | 4 +- .../pages/assets-filters-page.component.ts | 8 +- .../assets/pages/assets-page.component.ts | 13 +- .../content/content-history-page.component.ts | 36 +-- .../pages/content/content-page.component.html | 44 ++- .../pages/content/content-page.component.ts | 33 +- .../content-references.component.ts | 20 +- .../contents-filters-page.component.html | 48 +-- .../contents-filters-page.component.ts | 22 +- .../contents/contents-page.component.html | 15 +- .../pages/contents/contents-page.component.ts | 123 ++++---- .../pages/sidebar/sidebar-page.component.ts | 4 +- .../shared/forms/field-editor.component.html | 1 + .../shared/list/content.component.html | 2 +- .../content/shared/list/content.component.ts | 2 +- .../references/content-creator.component.html | 6 +- .../references/content-creator.component.ts | 24 +- .../content-selector.component.html | 8 +- .../references/content-selector.component.ts | 6 +- .../references-editor.component.html | 1 + .../references/references-editor.component.ts | 3 + .../pages/dashboard-page.component.html | 16 +- .../pages/dashboard-page.component.ts | 22 +- .../events/rule-events-page.component.ts | 9 +- .../schema/fields/field-wizard.component.html | 2 +- .../fields/forms/field-form.component.html | 12 +- .../fields/schema-fields.component.html | 2 +- .../pages/schema/schema-page.component.html | 44 ++- .../pages/schema/schema-page.component.ts | 21 +- .../schema-scripts-form.component.html | 4 +- .../schema/ui/schema-ui-form.component.html | 14 +- .../schema/ui/schema-ui-form.component.ts | 10 +- .../contributors-page.component.ts | 9 +- .../pages/more/more-page.component.ts | 4 +- .../pages/workflows/workflow.component.html | 8 +- .../settings/settings-area.component.html | 2 +- .../settings/settings-area.component.ts | 6 +- .../angular/language-selector.component.ts | 4 +- .../angular/routers/can-deactivate.guard.ts | 6 +- .../angular/routers/router-2-state.spec.ts | 288 +++++------------- .../angular/routers/router-2-state.ts | 259 ++++++---------- .../assets/asset-dialog.component.html | 87 +++--- .../assets/asset-dialog.component.ts | 33 +- .../assets/asset-uploader.component.html | 2 +- .../queries/filter-comparison.component.html | 3 +- .../search/search-form.component.html | 5 +- .../schema-must-not-be-singleton.guard.ts | 2 + frontend/app/shared/state/_test-helpers.ts | 60 +--- frontend/app/shared/state/apps.state.ts | 11 +- .../app/shared/state/assets.state.spec.ts | 15 - frontend/app/shared/state/assets.state.ts | 18 +- frontend/app/shared/state/contents.state.ts | 25 +- .../shared/state/contributors.state.spec.ts | 14 - .../app/shared/state/contributors.state.ts | 14 +- frontend/app/shared/state/languages.state.ts | 9 +- frontend/app/shared/state/query.spec.ts | 80 +++-- frontend/app/shared/state/query.ts | 31 +- .../shared/state/rule-events.state.spec.ts | 20 +- .../app/shared/state/rule-events.state.ts | 16 +- frontend/app/shared/state/schemas.state.ts | 11 +- frontend/app/shared/state/ui.state.ts | 9 +- .../shell/pages/app/app-area.component.html | 20 +- .../app/shell/pages/app/app-area.component.ts | 6 +- .../shell/pages/app/left-menu.component.html | 2 +- .../shell/pages/app/left-menu.component.ts | 10 +- .../pages/internal/apps-menu.component.html | 4 +- .../pages/internal/profile-menu.component.ts | 1 - .../pages/internal/search-menu.component.html | 2 +- .../pages/internal/search-menu.component.ts | 2 +- 75 files changed, 701 insertions(+), 1030 deletions(-) diff --git a/frontend/app/features/administration/pages/cluster/cluster-page.component.ts b/frontend/app/features/administration/pages/cluster/cluster-page.component.ts index cc13a9700..73cfc022e 100644 --- a/frontend/app/features/administration/pages/cluster/cluster-page.component.ts +++ b/frontend/app/features/administration/pages/cluster/cluster-page.component.ts @@ -6,7 +6,6 @@ */ import { Component } from '@angular/core'; -import { UIState } from '@app/shared'; @Component({ selector: 'sqx-cluster-area', @@ -14,8 +13,4 @@ import { UIState } from '@app/shared'; templateUrl: './cluster-page.component.html' }) export class ClusterPageComponent { - constructor( - public readonly uiState: UIState - ) { - } } \ No newline at end of file diff --git a/frontend/app/features/administration/pages/event-consumers/event-consumer.component.ts b/frontend/app/features/administration/pages/event-consumers/event-consumer.component.ts index 740b3e1e0..73178a1e0 100644 --- a/frontend/app/features/administration/pages/event-consumers/event-consumer.component.ts +++ b/frontend/app/features/administration/pages/event-consumers/event-consumer.component.ts @@ -24,7 +24,7 @@ export class EventConsumerComponent { public eventConsumer: EventConsumerDto; constructor( - public readonly eventConsumersState: EventConsumersState + private readonly eventConsumersState: EventConsumersState ) { } diff --git a/frontend/app/features/administration/pages/users/users-page.component.html b/frontend/app/features/administration/pages/users/users-page.component.html index 4db957e2d..310c64065 100644 --- a/frontend/app/features/administration/pages/users/users-page.component.html +++ b/frontend/app/features/administration/pages/users/users-page.component.html @@ -51,9 +51,7 @@
- - +
diff --git a/frontend/app/features/administration/pages/users/users-page.component.ts b/frontend/app/features/administration/pages/users/users-page.component.ts index ba0f33629..ffead1698 100644 --- a/frontend/app/features/administration/pages/users/users-page.component.ts +++ b/frontend/app/features/administration/pages/users/users-page.component.ts @@ -33,7 +33,14 @@ export class UsersPageComponent extends ResourceOwner implements OnInit { } public ngOnInit() { - this.usersState.loadAndListen(this.usersRoute); + const initial = + this.usersRoute.mapTo(this.usersState) + .withPaging('users', 10) + .withString('query') + .getInitial(); + + this.usersState.load(false, initial); + this.usersRoute.listen(); } public reload() { @@ -44,7 +51,7 @@ export class UsersPageComponent extends ResourceOwner implements OnInit { this.usersState.search(this.usersFilter.value); } - public trackByUser(_ndex: number, user: UserDto) { + public trackByUser(_index: number, user: UserDto) { return user.id; } } \ No newline at end of file diff --git a/frontend/app/features/administration/state/users.state.spec.ts b/frontend/app/features/administration/state/users.state.spec.ts index 24a3a1419..d45ec152b 100644 --- a/frontend/app/features/administration/state/users.state.spec.ts +++ b/frontend/app/features/administration/state/users.state.spec.ts @@ -10,13 +10,10 @@ import { DialogService } from '@app/shared'; import { of, throwError } from 'rxjs'; import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, It, Mock, Times } from 'typemoq'; -import { TestValues } from './../../../shared/state/_test-helpers'; import { createUser } from './../services/users.service.spec'; import { UsersState } from './users.state'; describe('UsersState', () => { - const { buildDummyStateSynchronizer } = TestValues; - const user1 = createUser(1); const user2 = createUser(2); @@ -110,20 +107,6 @@ describe('UsersState', () => { expect(usersState.snapshot.query).toEqual('my-query'); }); - - it('should load when synchronizer triggered', () => { - const { synchronizer, trigger } = buildDummyStateSynchronizer(); - - usersService.setup(x => x.getUsers(10, 0, undefined)) - .returns(() => of(oldUsers)).verifiable(Times.exactly(2)); - - usersState.loadAndListen(synchronizer); - - trigger(); - trigger(); - - expect().nothing(); - }); }); describe('Updates', () => { diff --git a/frontend/app/features/administration/state/users.state.ts b/frontend/app/features/administration/state/users.state.ts index aea22a04e..9c02f5cec 100644 --- a/frontend/app/features/administration/state/users.state.ts +++ b/frontend/app/features/administration/state/users.state.ts @@ -7,7 +7,7 @@ import { Injectable } from '@angular/core'; import '@app/framework/utils/rxjs-extensions'; -import { DialogService, getPagingInfo, ListState, shareSubscribed, State, StateSynchronizer } from '@app/shared'; +import { DialogService, getPagingInfo, ListState, shareSubscribed, State } from '@app/shared'; import { Observable, of } from 'rxjs'; import { catchError, finalize, tap } from 'rxjs/operators'; import { CreateUserDto, UpdateUserDto, UserDto, UsersService } from './../services/users.service'; @@ -83,18 +83,9 @@ export class UsersState extends State { return this.usersService.getUser(id).pipe(catchError(() => of(null))); } - public loadAndListen(synchronizer: StateSynchronizer) { - synchronizer.mapTo(this) - .keep('selectedUser') - .withPaging('users', 10) - .withString('query', 'q') - .whenSynced(() => this.loadInternal(false)) - .build(); - } - - public load(isReload = false): Observable { + public load(isReload = false, update: Partial = {}): Observable { if (!isReload) { - this.resetState({ selectedUser: this.snapshot.selectedUser }); + this.resetState({ selectedUser: this.snapshot.selectedUser, ...update }); } return this.loadInternal(isReload); diff --git a/frontend/app/features/api/pages/graphql/graphql-page.component.ts b/frontend/app/features/api/pages/graphql/graphql-page.component.ts index 8afc0a1b2..e4327e287 100644 --- a/frontend/app/features/api/pages/graphql/graphql-page.component.ts +++ b/frontend/app/features/api/pages/graphql/graphql-page.component.ts @@ -40,6 +40,8 @@ export class GraphQLPageComponent implements AfterViewInit { } private request(params: any) { - return this.graphQlService.query(this.appsState.appName, params).pipe(catchError(response => of(response.error))).toPromise(); + return this.graphQlService.query(this.appsState.appName, params).pipe( + catchError(response => of(response.error))) + .toPromise(); } } \ No newline at end of file diff --git a/frontend/app/features/assets/pages/assets-filters-page.component.ts b/frontend/app/features/assets/pages/assets-filters-page.component.ts index bcd9c5f05..4474ed255 100644 --- a/frontend/app/features/assets/pages/assets-filters-page.component.ts +++ b/frontend/app/features/assets/pages/assets-filters-page.component.ts @@ -14,12 +14,12 @@ import { AssetsState, Queries, Query, UIState } from '@app/shared'; templateUrl: './assets-filters-page.component.html' }) export class AssetsFiltersPageComponent { - public assetsQueries = new Queries(this.uiState, 'assets'); + public assetsQueries: Queries; - constructor( - public readonly assetsState: AssetsState, - private readonly uiState: UIState + constructor(uiState: UIState, + public readonly assetsState: AssetsState ) { + this.assetsQueries = new Queries(uiState, 'assets'); } public search(query: Query) { diff --git a/frontend/app/features/assets/pages/assets-page.component.ts b/frontend/app/features/assets/pages/assets-page.component.ts index 3b5152c4e..4527eda35 100644 --- a/frontend/app/features/assets/pages/assets-page.component.ts +++ b/frontend/app/features/assets/pages/assets-page.component.ts @@ -6,7 +6,7 @@ */ import { Component, OnInit } from '@angular/core'; -import { AssetsState, DialogModel, LocalStoreService, Queries, Query, ResourceOwner, Router2State, UIState } from '@app/shared'; +import { AssetsState, DialogModel, LocalStoreService, Queries, Query, QueryFullTextSynchronizer, ResourceOwner, Router2State, UIState } from '@app/shared'; import { Settings } from '@app/shared/state/settings'; @Component({ @@ -36,7 +36,16 @@ export class AssetsPageComponent extends ResourceOwner implements OnInit { } public ngOnInit() { - this.assetsState.loadAndListen(this.assetsRoute); + const initial = + this.assetsRoute.mapTo(this.assetsState) + .withPaging('assets', 30) + .withString('parentId') + .withStrings('tagsSelected') + .withSynchronizer(QueryFullTextSynchronizer.INSTANCE) + .getInitial(); + + this.assetsState.load(false, initial); + this.assetsRoute.listen(); } public reload() { diff --git a/frontend/app/features/content/pages/content/content-history-page.component.ts b/frontend/app/features/content/pages/content/content-history-page.component.ts index 4ea83adeb..2ac4228ee 100644 --- a/frontend/app/features/content/pages/content/content-history-page.component.ts +++ b/frontend/app/features/content/pages/content/content-history-page.component.ts @@ -8,9 +8,9 @@ // tslint:disable: triple-equals import { Component, OnInit, ViewChild } from '@angular/core'; -import { AppsState, ContentDto, ContentsState, fadeAnimation, HistoryEventDto, HistoryService, ModalModel, ResourceOwner, SchemaDetailsDto, SchemasState, switchSafe } from '@app/shared'; +import { AppsState, ContentDto, ContentsState, defined, fadeAnimation, HistoryEventDto, HistoryService, ModalModel, ResourceOwner, SchemasState, switchSafe } from '@app/shared'; import { Observable, timer } from 'rxjs'; -import { filter, map, onErrorResumeNext, switchMap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { DueTimeSelectorComponent } from './../../shared/due-time-selector.component'; import { ContentPageComponent } from './content-page.component'; @@ -26,8 +26,6 @@ export class ContentHistoryPageComponent extends ResourceOwner implements OnInit @ViewChild('dueTimeSelector', { static: false }) public dueTimeSelector: DueTimeSelectorComponent; - public schema: SchemaDetailsDto; - public content: ContentDto; public contentEvents: Observable>; @@ -46,43 +44,31 @@ export class ContentHistoryPageComponent extends ResourceOwner implements OnInit public ngOnInit() { this.own( - this.schemasState.selectedSchema - .subscribe(schema => { - if (schema) { - this.schema = schema; - } - })); - - this.own( - this.contentsState.selectedContent + this.contentsState.selectedContent.pipe(defined()) .subscribe(content => { - if (content) { - this.content = content; - } + this.content = content; })); this.contentEvents = this.contentsState.selectedContent.pipe( - filter(x => !!x), - map(content => `schemas.${this.schemasState.schemaId}.contents.${content?.id}`), + defined(), + map(content => `schemas.${this.schemasState.schemaId}.contents.${content.id}`), switchSafe(channel => timer(0, 5000).pipe(map(() => channel))), switchSafe(channel => this.historyService.getHistory(this.appsState.appName, channel))); } public changeStatus(status: string) { this.contentPage.checkPendingChangesBeforeChangingStatus().pipe( - filter(x => !!x), - switchMap(_ => this.dueTimeSelector.selectDueTime(status)), - switchMap(d => this.contentsState.changeManyStatus([this.content], status, d)), - onErrorResumeNext()) + defined(), + switchSafe(_ => this.dueTimeSelector.selectDueTime(status)), + switchSafe(d => this.contentsState.changeManyStatus([this.content], status, d))) .subscribe(); } public createDraft() { this.contentPage.checkPendingChangesBeforeChangingStatus().pipe( - filter(x => !!x), - switchMap(d => this.contentsState.createDraft(this.content)), - onErrorResumeNext()) + defined(), + switchSafe(() => this.contentsState.createDraft(this.content))) .subscribe(); } diff --git a/frontend/app/features/content/pages/content/content-page.component.html b/frontend/app/features/content/pages/content/content-page.component.html index 1ea1aa459..90779b4d1 100644 --- a/frontend/app/features/content/pages/content/content-page.component.html +++ b/frontend/app/features/content/pages/content/content-page.component.html @@ -18,9 +18,21 @@ -