From 92b893db4bc98260cdb39bf81f250bd489e56cc5 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 11 Jan 2021 12:45:00 +0100 Subject: [PATCH] Dev tools. (#617) * Dev tools. * Build fix. * Another attempt. --- .../state/event-consumers.state.ts | 12 +-- .../administration/state/users.state.ts | 28 ++++--- .../content-references.component.ts | 6 +- .../shared/forms/assets-editor.component.ts | 4 +- .../references/content-creator.component.ts | 6 +- .../references/content-selector.component.ts | 6 +- .../forms/editors/autocomplete.component.ts | 5 +- .../forms/editors/dropdown.component.html | 4 +- .../forms/editors/dropdown.component.ts | 35 ++++---- .../forms/editors/tag-editor.component.ts | 5 +- frontend/app/framework/state.ts | 33 ++++++-- .../assets/assets-selector.component.ts | 7 +- frontend/app/shared/module.ts | 5 +- frontend/app/shared/state/apps.state.ts | 16 ++-- .../app/shared/state/asset-uploader.state.ts | 10 +-- frontend/app/shared/state/assets.state.ts | 83 +++++++++++-------- frontend/app/shared/state/backups.state.ts | 10 +-- frontend/app/shared/state/clients.state.ts | 8 +- frontend/app/shared/state/comments.state.ts | 10 +-- frontend/app/shared/state/contents.state.ts | 34 ++++---- .../app/shared/state/contributors.state.ts | 14 ++-- frontend/app/shared/state/languages.state.ts | 10 +-- frontend/app/shared/state/patterns.state.ts | 10 +-- frontend/app/shared/state/plans.state.ts | 12 +-- frontend/app/shared/state/roles.state.ts | 10 +-- .../app/shared/state/rule-events.state.ts | 33 ++++---- frontend/app/shared/state/rules.state.ts | 16 ++-- frontend/app/shared/state/schemas.state.ts | 24 +++--- frontend/app/shared/state/ui.state.ts | 23 +++-- frontend/app/shared/state/workflows.state.ts | 8 +- .../pages/internal/profile-menu.component.ts | 5 +- 31 files changed, 261 insertions(+), 231 deletions(-) diff --git a/frontend/app/features/administration/state/event-consumers.state.ts b/frontend/app/features/administration/state/event-consumers.state.ts index 54d56a2cc..954eef91a 100644 --- a/frontend/app/features/administration/state/event-consumers.state.ts +++ b/frontend/app/features/administration/state/event-consumers.state.ts @@ -39,12 +39,12 @@ export class EventConsumersState extends State { private readonly dialogs: DialogService, private readonly eventConsumersService: EventConsumersService ) { - super({ eventConsumers: [] }); + super({ eventConsumers: [] }, 'EventConsumers'); } public load(isReload = false, silent = false): Observable { if (isReload && !silent) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload, silent); @@ -52,7 +52,7 @@ export class EventConsumersState extends State { private loadInternal(isReload: boolean, silent: boolean): Observable { if (!silent) { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); } return this.eventConsumersService.getEventConsumers().pipe( @@ -65,10 +65,10 @@ export class EventConsumersState extends State { eventConsumers, isLoaded: true, isLoading: false - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs, { silent })); } @@ -102,6 +102,6 @@ export class EventConsumersState extends State { const eventConsumers = s.eventConsumers.replaceBy('name', eventConsumer); return { ...s, eventConsumers }; - }); + }, 'Updated'); } } \ No newline at end of file diff --git a/frontend/app/features/administration/state/users.state.ts b/frontend/app/features/administration/state/users.state.ts index 9c02f5cec..cd5c2673e 100644 --- a/frontend/app/features/administration/state/users.state.ts +++ b/frontend/app/features/administration/state/users.state.ts @@ -8,7 +8,7 @@ import { Injectable } from '@angular/core'; import '@app/framework/utils/rxjs-extensions'; import { DialogService, getPagingInfo, ListState, shareSubscribed, State } from '@app/shared'; -import { Observable, of } from 'rxjs'; +import { EMPTY, Observable, of } from 'rxjs'; import { catchError, finalize, tap } from 'rxjs/operators'; import { CreateUserDto, UpdateUserDto, UserDto, UsersService } from './../services/users.service'; @@ -58,13 +58,13 @@ export class UsersState extends State { page: 0, pageSize: 10, total: 0 - }); + }, 'Users'); } public select(id: string | null): Observable { return this.loadUser(id).pipe( tap(selectedUser => { - this.next({ selectedUser }); + this.next({ selectedUser }, 'Selected'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -85,14 +85,14 @@ export class UsersState extends State { public load(isReload = false, update: Partial = {}): Observable { if (!isReload) { - this.resetState({ selectedUser: this.snapshot.selectedUser, ...update }); + this.resetState({ selectedUser: this.snapshot.selectedUser, ...update }, 'Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); const { page, pageSize, query } = this.snapshot; @@ -120,10 +120,10 @@ export class UsersState extends State { selectedUser, total }; - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -135,7 +135,7 @@ export class UsersState extends State { const users = [created, ...s.users].slice(0, s.pageSize); return { ...s, users, total: s.total + 1 }; - }); + }, 'Created'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -164,14 +164,18 @@ export class UsersState extends State { shareSubscribed(this.dialogs)); } - public search(query: string): Observable { - this.next({ query, page: 0 }); + public search(query: string) { + if (!this.next({ query, page: 0 }, 'Loading Search')) { + return EMPTY; + } return this.loadInternal(false); } public page(paging: { page: number, pageSize: number }) { - this.next(paging); + if (!this.next(paging, 'Loading Paged')) { + return EMPTY; + } return this.loadInternal(false); } @@ -186,6 +190,6 @@ export class UsersState extends State { users.find(x => x.id === user.id); return { ...s, users, selectedUser }; - }); + }, 'Updated'); } } \ No newline at end of file diff --git a/frontend/app/features/content/pages/content/references/content-references.component.ts b/frontend/app/features/content/pages/content/references/content-references.component.ts index bc23a204d..5f58367e3 100644 --- a/frontend/app/features/content/pages/content/references/content-references.component.ts +++ b/frontend/app/features/content/pages/content/references/content-references.component.ts @@ -6,7 +6,7 @@ */ import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; -import { AppLanguageDto, ContentDto, ManualContentsState, QuerySynchronizer, Router2State } from '@app/shared'; +import { AppLanguageDto, ComponentContentsState, ContentDto, QuerySynchronizer, Router2State } from '@app/shared'; @Component({ selector: 'sqx-content-references', @@ -14,7 +14,7 @@ import { AppLanguageDto, ContentDto, ManualContentsState, QuerySynchronizer, Rou templateUrl: './content-references.component.html', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ - Router2State, ManualContentsState + Router2State, ComponentContentsState ] }) export class ContentReferencesComponent implements OnChanges { @@ -29,7 +29,7 @@ export class ContentReferencesComponent implements OnChanges { constructor( public readonly contentsRoute: Router2State, - public readonly contentsState: ManualContentsState + public readonly contentsState: ComponentContentsState ) { } diff --git a/frontend/app/features/content/shared/forms/assets-editor.component.ts b/frontend/app/features/content/shared/forms/assets-editor.component.ts index 4c6ee2399..e40df6f36 100644 --- a/frontend/app/features/content/shared/forms/assets-editor.component.ts +++ b/frontend/app/features/content/shared/forms/assets-editor.component.ts @@ -153,8 +153,8 @@ export class AssetsEditorComponent extends StatefulControlComponent ({ - ...s, assetFiles: - s.assetFiles.removed(file) + ...s, + assetFiles: s.assetFiles.removed(file) })); } diff --git a/frontend/app/features/content/shared/references/content-creator.component.ts b/frontend/app/features/content/shared/references/content-creator.component.ts index 396e3c192..e0c3d10df 100644 --- a/frontend/app/features/content/shared/references/content-creator.component.ts +++ b/frontend/app/features/content/shared/references/content-creator.component.ts @@ -6,14 +6,14 @@ */ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { AppLanguageDto, ContentDto, EditContentForm, LanguageDto, ManualContentsState, ResourceOwner, SchemaDetailsDto, SchemaDto, SchemasState, Types } from '@app/shared'; +import { AppLanguageDto, ComponentContentsState, ContentDto, EditContentForm, LanguageDto, ResourceOwner, SchemaDetailsDto, SchemaDto, SchemasState, Types } from '@app/shared'; @Component({ selector: 'sqx-content-creator', styleUrls: ['./content-creator.component.scss'], templateUrl: './content-creator.component.html', providers: [ - ManualContentsState + ComponentContentsState ] }) export class ContentCreatorComponent extends ResourceOwner implements OnInit { @@ -38,7 +38,7 @@ export class ContentCreatorComponent extends ResourceOwner implements OnInit { public contentForm: EditContentForm; constructor( - private readonly contentsState: ManualContentsState, + private readonly contentsState: ComponentContentsState, private readonly schemasState: SchemasState, private readonly changeDetector: ChangeDetectorRef ) { diff --git a/frontend/app/features/content/shared/references/content-selector.component.ts b/frontend/app/features/content/shared/references/content-selector.component.ts index 3ac164e75..a3ee10382 100644 --- a/frontend/app/features/content/shared/references/content-selector.component.ts +++ b/frontend/app/features/content/shared/references/content-selector.component.ts @@ -6,14 +6,14 @@ */ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { ApiUrlConfig, AppsState, ContentDto, LanguageDto, ManualContentsState, Query, QueryModel, queryModelFromSchema, ResourceOwner, SchemaDetailsDto, SchemaDto, SchemasState, Types } from '@app/shared'; +import { ApiUrlConfig, AppsState, ComponentContentsState, ContentDto, LanguageDto, Query, QueryModel, queryModelFromSchema, ResourceOwner, SchemaDetailsDto, SchemaDto, SchemasState, Types } from '@app/shared'; @Component({ selector: 'sqx-content-selector', styleUrls: ['./content-selector.component.scss'], templateUrl: './content-selector.component.html', providers: [ - ManualContentsState + ComponentContentsState ] }) export class ContentSelectorComponent extends ResourceOwner implements OnInit { @@ -47,7 +47,7 @@ export class ContentSelectorComponent extends ResourceOwner implements OnInit { constructor( public readonly appsState: AppsState, public readonly apiUrl: ApiUrlConfig, - public readonly contentsState: ManualContentsState, + public readonly contentsState: ComponentContentsState, public readonly schemasState: SchemasState, private readonly changeDetector: ChangeDetectorRef ) { diff --git a/frontend/app/framework/angular/forms/editors/autocomplete.component.ts b/frontend/app/framework/angular/forms/editors/autocomplete.component.ts index 290dd01f9..3df2f87e7 100644 --- a/frontend/app/framework/angular/forms/editors/autocomplete.component.ts +++ b/frontend/app/framework/angular/forms/editors/autocomplete.component.ts @@ -126,12 +126,11 @@ export class AutocompleteComponent extends StatefulControlComponent { - this.next(s => ({ - ...s, + this.next({ suggestedIndex: -1, suggestedItems: items || [], isSearching: false - })); + }); })); } diff --git a/frontend/app/framework/angular/forms/editors/dropdown.component.html b/frontend/app/framework/angular/forms/editors/dropdown.component.html index 8a19ba142..494d2f268 100644 --- a/frontend/app/framework/angular/forms/editors/dropdown.component.html +++ b/frontend/app/framework/angular/forms/editors/dropdown.component.html @@ -20,10 +20,10 @@
{{item}} diff --git a/frontend/app/framework/angular/forms/editors/dropdown.component.ts b/frontend/app/framework/angular/forms/editors/dropdown.component.ts index 768c92e54..7a79067f8 100644 --- a/frontend/app/framework/angular/forms/editors/dropdown.component.ts +++ b/frontend/app/framework/angular/forms/editors/dropdown.component.ts @@ -23,7 +23,7 @@ interface State { suggestedItems: ReadonlyArray; // The selected suggested index. - selectedIndex: number; + suggestedIndex: number; // The selected item. selectedItem?: number; @@ -71,8 +71,8 @@ export class DropdownComponent extends StatefulControlComponent { - this.next(s => ({ - ...s, - suggestedIndex: 0, + this.next({ suggestedItems: items || [], query - })); + }); })); } @@ -113,11 +111,10 @@ export class DropdownComponent extends StatefulControlComponent ({ - ...s, + this.next({ suggestedIndex: this.getSelectedIndex(this.value), suggestedItems: this.items || [] - })); + }); } } @@ -159,7 +156,7 @@ export class DropdownComponent extends StatefulControlComponent= items.length) { - selectedIndex = items.length - 1; + if (suggestedIndex >= items.length) { + suggestedIndex = items.length - 1; } - const selectedItem = items[selectedIndex]; + const selectedItem = items[suggestedIndex]; if (fromUserAction) { let selectedValue = selectedItem; @@ -229,7 +226,7 @@ export class DropdownComponent extends StatefulControlComponent { - this.next(s => ({ - ...s, + this.next({ suggestedIndex: -1, suggestedItems: items || [] - })); + }); })); } diff --git a/frontend/app/framework/state.ts b/frontend/app/framework/state.ts index 00bf7bd4b..3a7afbbd0 100644 --- a/frontend/app/framework/state.ts +++ b/frontend/app/framework/state.ts @@ -100,8 +100,11 @@ export interface ListState { query?: TQuery; } +const devToolsExtension = window['__REDUX_DEVTOOLS_EXTENSION__']; + export class State { private readonly state: BehaviorSubject>; + private readonly devTools?: any; public get changes(): Observable> { return this.state; @@ -127,20 +130,32 @@ export class State { } constructor( - private readonly initialState: Readonly + private readonly initialState: Readonly, + private readonly debugName?: string ) { this.state = new BehaviorSubject(initialState); + + if (debugName && devToolsExtension) { + const name = `[Squidex] ${debugName}`; + + this.devTools = devToolsExtension.connect({ name, features: {} }); + this.devTools.init(initialState); + } } - public resetState(update?: ((v: T) => Readonly) | Partial) { - return this.updateState(this.initialState, update); + public resetState(update?: ((v: T) => Readonly) | Partial | string, action = 'Reset') { + if (Types.isString(update)) { + return this.updateState(this.initialState, {}, update); + } else { + return this.updateState(this.initialState, update, action); + } } - public next(update: ((v: T) => Readonly) | Partial) { - return this.updateState(this.state.value, update); + public next(update: ((v: T) => Readonly) | Partial, action = 'Update') { + return this.updateState(this.state.value, update, action); } - private updateState(state: T, update?: ((v: T) => Readonly) | Partial) { + private updateState(state: T, update?: ((v: T) => Readonly) | Partial, action?: string) { let newState = state; if (update) { @@ -167,6 +182,12 @@ export class State { } if (isChanged) { + if (action && this.devTools) { + const name = `[${this.debugName}] ${action}`; + + this.devTools?.send(name, newState); + } + this.state.next(newState); } diff --git a/frontend/app/shared/components/assets/assets-selector.component.ts b/frontend/app/shared/components/assets/assets-selector.component.ts index b3171087c..b937113b8 100644 --- a/frontend/app/shared/components/assets/assets-selector.component.ts +++ b/frontend/app/shared/components/assets/assets-selector.component.ts @@ -6,7 +6,7 @@ */ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core'; -import { AssetDto, AssetsState, LocalStoreService, Query, Settings, StatefulComponent } from '@app/shared/internal'; +import { AssetDto, ComponentAssetsState, LocalStoreService, Query, Settings, StatefulComponent } from '@app/shared/internal'; interface State { // The selected assets. @@ -23,6 +23,9 @@ interface State { selector: 'sqx-assets-selector', styleUrls: ['./assets-selector.component.scss'], templateUrl: './assets-selector.component.html', + providers: [ + ComponentAssetsState + ], changeDetection: ChangeDetectionStrategy.OnPush }) export class AssetsSelectorComponent extends StatefulComponent implements OnInit { @@ -30,7 +33,7 @@ export class AssetsSelectorComponent extends StatefulComponent implements public select = new EventEmitter>(); constructor(changeDector: ChangeDetectorRef, - public readonly assetsState: AssetsState, + public readonly assetsState: ComponentAssetsState, public readonly localStore: LocalStoreService ) { super(changeDector, { diff --git a/frontend/app/shared/module.ts b/frontend/app/shared/module.ts index 2917c3670..6e21e1f7d 100644 --- a/frontend/app/shared/module.ts +++ b/frontend/app/shared/module.ts @@ -15,7 +15,7 @@ import { SqxFrameworkModule } from '@app/framework'; import { MentionModule } from 'angular-mentions'; import { NgxDocViewerModule } from 'ngx-doc-viewer'; import { PreviewableType } from './components/assets/pipes'; -import { AppFormComponent, AppLanguagesService, AppMustExistGuard, AppsService, AppsState, AssetComponent, AssetDialogComponent, AssetFolderComponent, AssetFolderDialogComponent, AssetHistoryComponent, AssetPathComponent, AssetPreviewUrlPipe, AssetsDialogState, AssetsListComponent, AssetsSelectorComponent, AssetsService, AssetsState, AssetTextEditorComponent, AssetUploaderComponent, AssetUploaderState, AssetUrlPipe, AuthInterceptor, AuthService, AutoSaveService, BackupsService, BackupsState, ClientsService, ClientsState, CommentComponent, CommentsComponent, CommentsService, ContentMustExistGuard, ContentsService, ContentsState, ContributorsService, ContributorsState, FileIconPipe, FilterComparisonComponent, FilterLogicalComponent, FilterNodeComponent, GeolocationEditorComponent, GraphQlService, HelpComponent, HelpMarkdownPipe, HelpService, HistoryComponent, HistoryListComponent, HistoryMessagePipe, HistoryService, ImageCropperComponent, ImageFocusPointComponent, LanguagesService, LanguagesState, LoadAppsGuard, LoadLanguagesGuard, MarkdownEditorComponent, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, NewsService, NotifoComponent, PatternsService, PatternsState, PlansService, PlansState, QueryComponent, QueryListComponent, QueryPathComponent, ReferencesCheckboxesComponent, ReferencesDropdownComponent, ReferencesTagsComponent, RichEditorComponent, RolesService, RolesState, RuleEventsState, RulesService, RulesState, SavedQueriesComponent, SchemaCategoryComponent, SchemaMustExistGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SchemasService, SchemasState, SchemaTagSource, SearchFormComponent, SortingComponent, StockPhotoService, TableHeaderComponent, TranslationsService, UIService, UIState, UnsetAppGuard, UnsetContentGuard, UsagesService, UserDtoPicture, UserIdPicturePipe, UserNamePipe, UserNameRefPipe, UserPicturePipe, UserPictureRefPipe, UsersProviderService, UsersService, WorkflowsService, WorkflowsState } from './declarations'; +import { AppFormComponent, AppLanguagesService, AppMustExistGuard, AppsService, AppsState, AssetComponent, AssetDialogComponent, AssetFolderComponent, AssetFolderDialogComponent, AssetHistoryComponent, AssetPathComponent, AssetPreviewUrlPipe, AssetsListComponent, AssetsSelectorComponent, AssetsService, AssetsState, AssetTextEditorComponent, AssetUploaderComponent, AssetUploaderState, AssetUrlPipe, AuthInterceptor, AuthService, AutoSaveService, BackupsService, BackupsState, ClientsService, ClientsState, CommentComponent, CommentsComponent, CommentsService, ContentMustExistGuard, ContentsService, ContentsState, ContributorsService, ContributorsState, FileIconPipe, FilterComparisonComponent, FilterLogicalComponent, FilterNodeComponent, GeolocationEditorComponent, GraphQlService, HelpComponent, HelpMarkdownPipe, HelpService, HistoryComponent, HistoryListComponent, HistoryMessagePipe, HistoryService, ImageCropperComponent, ImageFocusPointComponent, LanguagesService, LanguagesState, LoadAppsGuard, LoadLanguagesGuard, MarkdownEditorComponent, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, NewsService, NotifoComponent, PatternsService, PatternsState, PlansService, PlansState, QueryComponent, QueryListComponent, QueryPathComponent, ReferencesCheckboxesComponent, ReferencesDropdownComponent, ReferencesTagsComponent, RichEditorComponent, RolesService, RolesState, RuleEventsState, RulesService, RulesState, SavedQueriesComponent, SchemaCategoryComponent, SchemaMustExistGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SchemasService, SchemasState, SchemaTagSource, SearchFormComponent, SortingComponent, StockPhotoService, TableHeaderComponent, TranslationsService, UIService, UIState, UnsetAppGuard, UnsetContentGuard, UsagesService, UserDtoPicture, UserIdPicturePipe, UserNamePipe, UserNameRefPipe, UserPicturePipe, UserPictureRefPipe, UsersProviderService, UsersService, WorkflowsService, WorkflowsState } from './declarations'; import { SearchService } from './services/search.service'; @NgModule({ @@ -117,9 +117,6 @@ import { SearchService } from './services/search.service'; UserNameRefPipe, UserPicturePipe, UserPictureRefPipe - ], - providers: [ - AssetsDialogState ] }) export class SqxSharedModule { diff --git a/frontend/app/shared/state/apps.state.ts b/frontend/app/shared/state/apps.state.ts index b4d77922e..2837ae084 100644 --- a/frontend/app/shared/state/apps.state.ts +++ b/frontend/app/shared/state/apps.state.ts @@ -39,7 +39,7 @@ export class AppsState extends State { private readonly appsService: AppsService, private readonly dialogs: DialogService ) { - super({ apps: [], selectedApp: null }); + super({ apps: [], selectedApp: null }, 'Apps'); } public reloadSelected() { @@ -50,9 +50,7 @@ export class AppsState extends State { public select(name: string | null): Observable { return this.loadApp(name, true).pipe( tap(selectedApp => { - this.next(s => { - return { ...s, selectedApp }; - }); + this.next({ selectedApp }, 'Selected'); })); } @@ -79,9 +77,7 @@ export class AppsState extends State { public load(): Observable { return this.appsService.getApps().pipe( tap(apps => { - this.next(s => { - return { ...s, apps }; - }); + this.next({ apps }, 'Loaded'); }), shareSubscribed(this.dialogs)); } @@ -93,7 +89,7 @@ export class AppsState extends State { const apps = [...s.apps, created].sortedByString(x => x.displayName); return { ...s, apps }; - }); + }, 'Created'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -151,7 +147,7 @@ export class AppsState extends State { s.selectedApp; return { ...s, apps, selectedApp }; - }); + }, 'Deleted'); } private replaceApp(updated: AppDto, app: AppDto) { @@ -165,6 +161,6 @@ export class AppsState extends State { s.selectedApp; return { ...s, apps, selectedApp }; - }); + }, 'Updated'); } } \ No newline at end of file diff --git a/frontend/app/shared/state/asset-uploader.state.ts b/frontend/app/shared/state/asset-uploader.state.ts index 59e83607f..33427fb48 100644 --- a/frontend/app/shared/state/asset-uploader.state.ts +++ b/frontend/app/shared/state/asset-uploader.state.ts @@ -50,7 +50,7 @@ export class AssetUploaderState extends State { private readonly assetsService: AssetsService, private readonly dialogs: DialogService ) { - super({ uploads: [] }); + super({ uploads: [] }, 'AssetUploader'); } public stopUpload(upload: Upload) { @@ -60,7 +60,7 @@ export class AssetUploaderState extends State { const uploads = s.uploads.removeBy('id', upload); return { ...s, uploads }; - }); + }, 'Stopped'); } public uploadFile(file: File, target?: AssetsState): Observable { @@ -125,7 +125,7 @@ export class AssetUploaderState extends State { const uploads = s.uploads.removeBy('id', upload); return { ...s, uploads }; - }); + }, 'Upload Done'); }, 10000); @@ -139,7 +139,7 @@ export class AssetUploaderState extends State { const uploads = s.uploads.replaceBy('id', upload); return { ...s, uploads }; - }); + }, 'Updated'); return upload; } @@ -149,7 +149,7 @@ export class AssetUploaderState extends State { const uploads = [upload, ...s.uploads]; return { ...s, uploads }; - }); + }, 'Upload Started'); } private get appName() { diff --git a/frontend/app/shared/state/assets.state.ts b/frontend/app/shared/state/assets.state.ts index 041bba941..3673a7d19 100644 --- a/frontend/app/shared/state/assets.state.ts +++ b/frontend/app/shared/state/assets.state.ts @@ -52,8 +52,7 @@ interface Snapshot extends ListState { canCreateFolders?: boolean; } -@Injectable() -export class AssetsState extends State { +export abstract class AssetsStateBase extends State { public tagsUnsorted = this.project(x => x.tagsAvailable); @@ -105,7 +104,7 @@ export class AssetsState extends State { public canCreateFolders = this.project(x => x.canCreateFolders === true); - constructor( + constructor(name: string, private readonly appsState: AppsState, private readonly assetsService: AssetsService, private readonly dialogs: DialogService @@ -120,19 +119,19 @@ export class AssetsState extends State { tagsAvailable: {}, tagsSelected: {}, total: 0 - }); + }, name); } public load(isReload = false, update: Partial = {}): Observable { if (!isReload) { - this.resetState(update); + this.resetState(update, 'Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); const query = createQuery(this.snapshot); @@ -161,8 +160,7 @@ export class AssetsState extends State { const { items: assets, total } = assetsResult; - this.next(s => ({ - ...s, + this.next({ assets, folders: foldersResult.items, canCreate: assetsResult.canCreate, @@ -173,10 +171,10 @@ export class AssetsState extends State { path, tagsAvailable, total - })); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -192,7 +190,7 @@ export class AssetsState extends State { const tags = updateTags(s, asset); return { ...s, assets, total: s.total + 1, ...tags }; - }); + }, 'Asset Created'); } public createAssetFolder(folderName: string) { @@ -206,7 +204,7 @@ export class AssetsState extends State { const folders = [...s.folders, folder].sortedByString(x => x.folderName); return { ...s, folders }; - }); + }, 'Folder Created'); }), shareSubscribed(this.dialogs)); } @@ -220,7 +218,7 @@ export class AssetsState extends State { const assets = s.assets.replaceBy('id', updated); return { ...s, assets, ...tags }; - }); + }, 'Asset Updated'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -232,7 +230,7 @@ export class AssetsState extends State { const folders = s.folders.replaceBy('id', updated); return { ...s, folders }; - }); + }, 'Folder Updated'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -246,7 +244,7 @@ export class AssetsState extends State { const assets = s.assets.filter(x => x.id !== asset.id); return { ...s, assets }; - }); + }, 'Asset Moving Started'); return this.assetsService.putAssetItemParent(this.appName, asset, { parentId }, asset.version).pipe( catchError(error => { @@ -254,7 +252,7 @@ export class AssetsState extends State { const assets = [asset, ...s.assets]; return { ...s, assets }; - }); + }, 'Asset Moving Failed'); return throwError(error); }), @@ -270,7 +268,7 @@ export class AssetsState extends State { const folders = s.folders.filter(x => x.id !== folder.id); return { ...s, folders }; - }); + }, 'Folder Moving Started'); return this.assetsService.putAssetItemParent(this.appName, folder, { parentId }, folder.version).pipe( catchError(error => { @@ -278,7 +276,7 @@ export class AssetsState extends State { const folders = [...s.folders, folder].sortedByString(x => x.folderName); return { ...s, folders }; - }); + }, 'Folder Moving Done'); return throwError(error); }), @@ -313,7 +311,7 @@ export class AssetsState extends State { const tags = updateTags(s, undefined, asset); return { ...s, assets, total: s.total - 1, ...tags }; - }); + }, 'Asset Deleted'); }), shareSubscribed(this.dialogs)); } @@ -325,19 +323,23 @@ export class AssetsState extends State { const folders = s.folders.filter(x => x.id !== folder.id); return { ...s, folders }; - }); + }, 'Folder Deleted'); }), shareSubscribed(this.dialogs)); } public navigate(parentId: string) { - this.next({ parentId, query: undefined, tagsSelected: {} }); + if (!this.next({ parentId, query: undefined, tagsSelected: {} }, 'Loading Navigated')) { + return EMPTY; + } return this.loadInternal(false); } public page(paging: { page: number, pageSize: number }) { - this.next(paging); + if (!this.next(paging, 'Loading Paged')) { + return EMPTY; + } return this.loadInternal(false); } @@ -373,19 +375,19 @@ export class AssetsState extends State { } private searchInternal(query?: Query | null, tags?: TagsSelected) { - this.next(s => { - const newState = { ...s, page: 0 }; + const update: Partial = { page: 0 }; - if (query !== null) { - newState.query = query; - } + if (query !== null) { + update.query = query; + } - if (tags) { - newState.tagsSelected = tags; - } + if (tags) { + update.tagsSelected = tags; + } - return newState; - }); + if (!this.next(update, 'Loading Searched')) { + return EMPTY; + } return this.loadInternal(false); } @@ -473,4 +475,19 @@ function getSortedTags(tags: { [name: string]: number }) { } @Injectable() -export class AssetsDialogState extends AssetsState { } \ No newline at end of file +export class AssetsState extends AssetsStateBase { + constructor( + appsState: AppsState, assetsService: AssetsService, dialogs: DialogService + ) { + super('Assets', appsState, assetsService, dialogs); + } +} + +@Injectable() +export class ComponentAssetsState extends AssetsStateBase { + constructor( + appsState: AppsState, assetsService: AssetsService, dialogs: DialogService + ) { + super('Component Assets', appsState, assetsService, dialogs); + } +} \ No newline at end of file diff --git a/frontend/app/shared/state/backups.state.ts b/frontend/app/shared/state/backups.state.ts index cfc632c75..1ae04a772 100644 --- a/frontend/app/shared/state/backups.state.ts +++ b/frontend/app/shared/state/backups.state.ts @@ -50,12 +50,12 @@ export class BackupsState extends State { private readonly backupsService: BackupsService, private readonly dialogs: DialogService ) { - super({ backups: [] }); + super({ backups: [] }, 'Backups'); } public load(isReload = false, silent = false): Observable { if (isReload && !silent) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload, silent); @@ -63,7 +63,7 @@ export class BackupsState extends State { private loadInternal(isReload: boolean, silent: boolean): Observable { if (!silent) { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); } return this.backupsService.getBackups(this.appName).pipe( @@ -77,10 +77,10 @@ export class BackupsState extends State { canCreate, isLoaded: true, isLoading: false - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs, { silent })); } diff --git a/frontend/app/shared/state/clients.state.ts b/frontend/app/shared/state/clients.state.ts index 208ebf60a..ea57cd051 100644 --- a/frontend/app/shared/state/clients.state.ts +++ b/frontend/app/shared/state/clients.state.ts @@ -55,14 +55,14 @@ export class ClientsState extends State { public load(isReload = false): Observable { if (!isReload) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return this.clientsService.getClients(this.appName).pipe( tap(({ version, payload }) => { @@ -73,7 +73,7 @@ export class ClientsState extends State { this.replaceClients(payload, version); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -111,7 +111,7 @@ export class ClientsState extends State { isLoaded: true, isLoading: false, version - }); + }, 'Loading Success / Updated'); } private get appName() { diff --git a/frontend/app/shared/state/comments.state.ts b/frontend/app/shared/state/comments.state.ts index 24d6beabe..da884d2a9 100644 --- a/frontend/app/shared/state/comments.state.ts +++ b/frontend/app/shared/state/comments.state.ts @@ -40,7 +40,7 @@ export class CommentsState extends State { private readonly orderDescending = false, initialVersion = -1 ) { - super({ comments: [], version: new Version(initialVersion.toString()) }); + super({ comments: [], version: new Version(initialVersion.toString()) }, 'Comments'); } public load(silent = false): Observable { @@ -68,7 +68,7 @@ export class CommentsState extends State { } return { ...s, comments, isLoaded: true, version: payload.version }; - }); + }, 'Loading Done'); }), shareSubscribed(this.dialogs, { silent })); } @@ -80,7 +80,7 @@ export class CommentsState extends State { const comments = [...s.comments, created]; return { ...s, comments }; - }); + }, 'Created'); }), shareSubscribed(this.dialogs)); } @@ -92,7 +92,7 @@ export class CommentsState extends State { const comments = s.comments.removeBy('id', comment); return { ...s, comments }; - }); + }, 'Deleted'); }), shareSubscribed(this.dialogs)); } @@ -105,7 +105,7 @@ export class CommentsState extends State { const comments = s.comments.replaceBy('id', updated); return { ...s, comments }; - }); + }, 'Updated'); }), shareSubscribed(this.dialogs)); } diff --git a/frontend/app/shared/state/contents.state.ts b/frontend/app/shared/state/contents.state.ts index 7493b2bd0..5c11555e3 100644 --- a/frontend/app/shared/state/contents.state.ts +++ b/frontend/app/shared/state/contents.state.ts @@ -86,7 +86,7 @@ export abstract class ContentsStateBase extends State { return this.appsState.appId; } - constructor( + constructor(name: string, private readonly appsState: AppsState, private readonly contentsService: ContentsService, private readonly dialogs: DialogService @@ -97,7 +97,7 @@ export abstract class ContentsStateBase extends State { pageSize: 10, total: 0, validationResults: {} - }); + }, name); } public select(id: string | null): Observable { @@ -107,7 +107,7 @@ export abstract class ContentsStateBase extends State { const contents = content ? s.contents.replaceBy('id', content) : s.contents; return { ...s, selectedContent: content, contents }; - }); + }, 'Selected'); })); } @@ -138,7 +138,7 @@ export abstract class ContentsStateBase extends State { public load(isReload = false, update: Partial = {}): Observable { if (!isReload) { - this.resetState({ selectedContent: this.snapshot.selectedContent, ...update }); + this.resetState({ selectedContent: this.snapshot.selectedContent, ...update }, 'Loading Intial'); } return this.loadInternal(isReload); @@ -161,7 +161,7 @@ export abstract class ContentsStateBase extends State { return EMPTY; } - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Done'); const { page, pageSize, query, reference, referencing } = this.snapshot; @@ -207,10 +207,10 @@ export abstract class ContentsStateBase extends State { statuses, total }; - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); })); } @@ -228,7 +228,7 @@ export abstract class ContentsStateBase extends State { const contents = [payload, ...s.contents].slice(s.pageSize); return { ...s, contents, total: s.total + 1 }; - }); + }, 'Created'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -246,7 +246,7 @@ export abstract class ContentsStateBase extends State { } return { ...s, validationResults }; - }); + }, 'Validated'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -304,13 +304,17 @@ export abstract class ContentsStateBase extends State { } public search(query?: Query): Observable { - this.next({ query, page: 0 }); + if (!this.next({ query, page: 0 }, 'Loading Searched')) { + return EMPTY; + } return this.loadInternal(false); } public page(paging: { page: number, pageSize: number }) { - this.next(paging); + if (!this.next(paging, 'Loading Done')) { + return EMPTY; + } return this.loadInternal(false); } @@ -331,7 +335,7 @@ export abstract class ContentsStateBase extends State { s.selectedContent; return { ...s, contents, selectedContent }; - }); + }, 'Updated'); } } @@ -396,7 +400,7 @@ export class ContentsState extends ContentsStateBase { constructor(appsState: AppsState, contentsService: ContentsService, dialogs: DialogService, private readonly schemasState: SchemasState ) { - super(appsState, contentsService, dialogs); + super('Contents', appsState, contentsService, dialogs); } public get schemaName() { @@ -405,13 +409,13 @@ export class ContentsState extends ContentsStateBase { } @Injectable() -export class ManualContentsState extends ContentsStateBase { +export class ComponentContentsState extends ContentsStateBase { public schema: { name: string }; constructor( appsState: AppsState, contentsService: ContentsService, dialogs: DialogService ) { - super(appsState, contentsService, dialogs); + super('Components Contents', appsState, contentsService, dialogs); } public get schemaName() { diff --git a/frontend/app/shared/state/contributors.state.ts b/frontend/app/shared/state/contributors.state.ts index e0c3c61cd..7c12d7e3a 100644 --- a/frontend/app/shared/state/contributors.state.ts +++ b/frontend/app/shared/state/contributors.state.ts @@ -71,7 +71,7 @@ export class ContributorsState extends State { pageSize: 10, total: 0, version: Version.EMPTY - }); + }, 'Contributors'); } public loadIfNotLoaded(): Observable { @@ -84,14 +84,14 @@ export class ContributorsState extends State { public load(isReload = false, update: Partial = {}): Observable { if (!isReload) { - this.resetState(update); + this.resetState(update, 'Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return this.contributorsService.getContributors(this.appName).pipe( tap(({ version, payload }) => { @@ -102,17 +102,17 @@ export class ContributorsState extends State { this.replaceContributors(version, payload); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } public page(paging: { page: number, pageSize: number }) { - this.next(paging); + this.next(paging, 'Results Paged'); } public search(query: string) { - this.next({ query }); + this.next({ query }, 'Results Filtered'); } public revoke(contributor: ContributorDto): Observable { @@ -147,7 +147,7 @@ export class ContributorsState extends State { maxContributors, total: items.length, version - }); + }, 'Loading Success / Updated'); } private get appName() { diff --git a/frontend/app/shared/state/languages.state.ts b/frontend/app/shared/state/languages.state.ts index 90aaebe7f..dfc7f7e61 100644 --- a/frontend/app/shared/state/languages.state.ts +++ b/frontend/app/shared/state/languages.state.ts @@ -87,19 +87,19 @@ export class LanguagesState extends State { allLanguagesNew: [], languages: [], version: Version.EMPTY - }); + }, 'Languages'); } public load(isReload = false): Observable { if (isReload) { - this.resetState(); + this.resetState('Loading Success'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return forkJoin([ this.getAllLanguages(), @@ -117,7 +117,7 @@ export class LanguagesState extends State { this.replaceLanguages(languages.payload, languages.version, sorted); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -162,7 +162,7 @@ export class LanguagesState extends State { languages: languages.map(x => this.createLanguage(x, languages)), version }; - }); + }, 'Loading Success / Updated'); } private get appName() { diff --git a/frontend/app/shared/state/patterns.state.ts b/frontend/app/shared/state/patterns.state.ts index d5cc4984a..4bd2bc775 100644 --- a/frontend/app/shared/state/patterns.state.ts +++ b/frontend/app/shared/state/patterns.state.ts @@ -50,19 +50,19 @@ export class PatternsState extends State { private readonly dialogs: DialogService, private readonly patternsService: PatternsService ) { - super({ patterns: [], version: Version.EMPTY }); + super({ patterns: [], version: Version.EMPTY }, 'Patterns'); } public load(isReload = false): Observable { if (!isReload) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return this.patternsService.getPatterns(this.appName).pipe( tap(({ version, payload }) => { @@ -73,7 +73,7 @@ export class PatternsState extends State { this.replacePatterns(payload, version); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareMapSubscribed(this.dialogs, x => x.payload)); } @@ -110,7 +110,7 @@ export class PatternsState extends State { isLoading: false, patterns, version, canCreate - }); + }, 'Loading Success / Updated'); } private get appName() { diff --git a/frontend/app/shared/state/plans.state.ts b/frontend/app/shared/state/plans.state.ts index b651ec694..f826c296c 100644 --- a/frontend/app/shared/state/plans.state.ts +++ b/frontend/app/shared/state/plans.state.ts @@ -76,19 +76,19 @@ export class PlansState extends State { private readonly dialogs: DialogService, private readonly plansService: PlansService ) { - super({ plans: [], version: Version.EMPTY }); + super({ plans: [], version: Version.EMPTY }, 'Plans'); } public load(isReload = false, overridePlanId?: string): Observable { if (!isReload) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload, overridePlanId); } private loadInternal(isReload: boolean, overridePlanId?: string): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return this.plansService.getPlans(this.appName).pipe( tap(({ version, payload }) => { @@ -106,10 +106,10 @@ export class PlansState extends State { isOwner: !payload.planOwner || payload.planOwner === this.userId, plans, version - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -124,7 +124,7 @@ export class PlansState extends State { const plans = s.plans.map(x => this.createPlan(x.plan, planId)); return { ...s, plans, isOwner: true, version }; - }); + }, 'Change'); } }), shareSubscribed(this.dialogs)); diff --git a/frontend/app/shared/state/roles.state.ts b/frontend/app/shared/state/roles.state.ts index d1dd265f2..12c9704ed 100644 --- a/frontend/app/shared/state/roles.state.ts +++ b/frontend/app/shared/state/roles.state.ts @@ -50,19 +50,19 @@ export class RolesState extends State { private readonly dialogs: DialogService, private readonly rolesService: RolesService ) { - super({ roles: [], version: Version.EMPTY }); + super({ roles: [], version: Version.EMPTY }, 'Roles'); } public load(isReload = false): Observable { if (!isReload) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Success'); return this.rolesService.getRoles(this.appName).pipe( tap(({ version, payload }) => { @@ -73,7 +73,7 @@ export class RolesState extends State { this.replaceRoles(payload, version); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -111,7 +111,7 @@ export class RolesState extends State { isLoading: false, roles, version - }); + }, 'Loading Success / Updated'); } private get appName() { diff --git a/frontend/app/shared/state/rule-events.state.ts b/frontend/app/shared/state/rule-events.state.ts index 7098bcee6..eb230bd3a 100644 --- a/frontend/app/shared/state/rule-events.state.ts +++ b/frontend/app/shared/state/rule-events.state.ts @@ -47,19 +47,19 @@ export class RuleEventsState extends State { page: 0, pageSize: 30, total: 0 - }); + }, 'Rule Events'); } public load(isReload = false, update: Partial = {}): Observable { if (!isReload) { - this.resetState({ ruleId: this.snapshot.ruleId, ...update }); + this.resetState({ ruleId: this.snapshot.ruleId, ...update }, 'Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); const { page, pageSize, ruleId } = this.snapshot; @@ -72,18 +72,15 @@ export class RuleEventsState extends State { this.dialogs.notifyInfo('i18n:rules.ruleEvents.reloaded'); } - return this.next(s => { - return { - ...s, - isLoaded: true, - isLoading: false, - ruleEvents, - total - }; - }); + return this.next({ + isLoaded: true, + isLoading: false, + ruleEvents, + total + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -103,23 +100,23 @@ export class RuleEventsState extends State { const ruleEvents = s.ruleEvents.replaceBy('id', setCancelled(event)); return { ...s, ruleEvents, isLoaded: true }; - }); + }, 'Cancel'); }), shareSubscribed(this.dialogs)); } public filterByRule(ruleId?: string) { - if (ruleId === this.snapshot.ruleId) { + if (!this.next({ page: 0, ruleId }, 'Loading Rule')) { return EMPTY; } - this.next({ page: 0, ruleId }); - return this.loadInternal(false); } public page(paging: { page: number, pageSize: number }) { - this.next(paging); + if (!this.next(paging, 'Loading Paged')) { + return EMPTY; + } return this.loadInternal(false); } diff --git a/frontend/app/shared/state/rules.state.ts b/frontend/app/shared/state/rules.state.ts index 6a3ef0036..fbc1e476f 100644 --- a/frontend/app/shared/state/rules.state.ts +++ b/frontend/app/shared/state/rules.state.ts @@ -68,19 +68,19 @@ export class RulesState extends State { private readonly dialogs: DialogService, private readonly rulesService: RulesService ) { - super({ rules: [] }); + super({ rules: [] }, 'Rules'); } public load(isReload = false): Observable { if (!isReload) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload); } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return this.rulesService.getRules(this.appName).pipe( tap(({ items: rules, runningRuleId, canCancelRun, canCreate, canReadEvents }) => { @@ -96,10 +96,10 @@ export class RulesState extends State { isLoading: false, runningRuleId, rules - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -111,7 +111,7 @@ export class RulesState extends State { const rules = [...s.rules, created]; return { ...s, rules }; - }); + }, 'Created'); }), shareSubscribed(this.dialogs)); } @@ -123,7 +123,7 @@ export class RulesState extends State { const rules = s.rules.removeBy('id', rule); return { ...s, rules }; - }); + }, 'Deleted'); }), shareSubscribed(this.dialogs)); } @@ -205,7 +205,7 @@ export class RulesState extends State { const rules = s.rules.replaceBy('id', rule); return { ...s, rules }; - }); + }, 'Updated'); } private get appName() { diff --git a/frontend/app/shared/state/schemas.state.ts b/frontend/app/shared/state/schemas.state.ts index ec1da927c..27bdd930e 100644 --- a/frontend/app/shared/state/schemas.state.ts +++ b/frontend/app/shared/state/schemas.state.ts @@ -76,15 +76,13 @@ export class SchemasState extends State { private readonly dialogs: DialogService, private readonly schemasService: SchemasService ) { - super({ schemas: [], categories: [] }); + super({ schemas: [], categories: [] }, 'Schemas'); } public select(idOrName: string | null): Observable { return this.loadSchema(idOrName).pipe( tap(selectedSchema => { - this.next(s => { - return { ...s, selectedSchema }; - }); + this.next({ selectedSchema }, 'Selected'); })); } @@ -107,7 +105,7 @@ export class SchemasState extends State { const schemas = s.schemas.replaceBy('id', schema); return { ...s, schemas }; - }); + }, 'Loading Schema Done'); }), catchError(() => of(null))); } @@ -125,7 +123,7 @@ export class SchemasState extends State { } private loadInternal(isReload: boolean): Observable { - this.next({ isLoading: true }); + this.next({ isLoading: true }, 'Loading Started'); return this.schemasService.getSchemas(this.appName).pipe( tap(({ items, canCreate }) => { @@ -140,10 +138,10 @@ export class SchemasState extends State { isLoaded: true, isLoading: true, schemas - }); + }, 'Loading Success'); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -155,7 +153,7 @@ export class SchemasState extends State { const schemas = [...s.schemas, created].sortedByString(x => x.displayName); return { ...s, schemas }; - }); + }, 'Created'); }), shareSubscribed(this.dialogs, { silent: true })); } @@ -172,7 +170,7 @@ export class SchemasState extends State { null; return { ...s, schemas, selectedSchema }; - }); + }, 'Deleted'); }), shareSubscribed(this.dialogs)); } @@ -182,7 +180,7 @@ export class SchemasState extends State { const categories = [...s.categories, name]; return { ...s, categories }; - }); + }, 'Category Added'); } public removeCategory(name: string) { @@ -190,7 +188,7 @@ export class SchemasState extends State { const categories = s.categories.removed(name); return { ...s, categories }; - }); + }, 'Category Removed'); } public publish(schema: SchemaDto): Observable { @@ -355,7 +353,7 @@ export class SchemasState extends State { s.selectedSchema; return { ...s, schemas, selectedSchema }; - }); + }, 'Updated'); } else { if (updateText) { this.dialogs.notifyInfo('i18n:common.nothingChanged'); diff --git a/frontend/app/shared/state/ui.state.ts b/frontend/app/shared/state/ui.state.ts index d983081e7..7987e7df9 100644 --- a/frontend/app/shared/state/ui.state.ts +++ b/frontend/app/shared/state/ui.state.ts @@ -90,7 +90,7 @@ export class UIState extends State { super({ settings: {}, settingsCommon: {} - }); + }, 'Setting'); this.loadResources(); this.loadCommon(); @@ -107,36 +107,35 @@ export class UIState extends State { settings: s.settingsCommon, settingsShared: undefined, settingsUser: undefined - })); + }), 'Loading Done'); this.uiService.getSharedSettings(app) .subscribe(payload => { - this.next(s => updateSettings(s, { settingsShared: payload })); + this.next(s => updateSettings(s, { settingsShared: payload }), 'Loading Shared Success'); }); this.uiService.getUserSettings(app) .subscribe(payload => { - this.next(s => updateSettings(s, { settingsUser: payload })); + this.next(s => updateSettings(s, { settingsUser: payload }), 'Loading User Success'); }); } private loadCommon() { this.uiService.getCommonSettings() .subscribe(payload => { - this.next(s => updateSettings(s, { settingsCommon: payload })); + this.next(s => updateSettings(s, { settingsCommon: payload }), 'Loading Common Done'); }); } private loadResources() { this.usersService.getResources() .subscribe(payload => { - this.next(s => ({ - ...s, + this.next({ canReadEvents: hasAnyLink(payload, 'admin/events'), canReadUsers: hasAnyLink(payload, 'admin/users'), canRestore: hasAnyLink(payload, 'admin/restore'), canUseOrleans: hasAnyLink(payload, 'admin/orleans') - })); + }, 'Loading Resources Done'); }); } @@ -156,7 +155,7 @@ export class UIState extends State { current[key] = value; - this.next(s => updateSettings(s, { settingsUser: root })); + this.next(s => updateSettings(s, { settingsUser: root }), 'Set User'); } } @@ -168,7 +167,7 @@ export class UIState extends State { current[key] = value; - this.next(s => updateSettings(s, { settingsShared: root })); + this.next(s => updateSettings(s, { settingsShared: root }), 'Set Shared'); } } @@ -184,7 +183,7 @@ export class UIState extends State { delete current[key]; - this.next(s => updateSettings(s, { settingsUser: root })); + this.next(s => updateSettings(s, { settingsUser: root }), 'Removed User'); return true; } @@ -200,7 +199,7 @@ export class UIState extends State { delete current[key]; - this.next(s => updateSettings(s, { settingsShared: root })); + this.next(s => updateSettings(s, { settingsShared: root }), 'Removed Shared'); return true; } diff --git a/frontend/app/shared/state/workflows.state.ts b/frontend/app/shared/state/workflows.state.ts index d26e598fe..e2ee544b0 100644 --- a/frontend/app/shared/state/workflows.state.ts +++ b/frontend/app/shared/state/workflows.state.ts @@ -54,12 +54,12 @@ export class WorkflowsState extends State { private readonly dialogs: DialogService, private readonly workflowsService: WorkflowsService ) { - super({ errors: [], workflows: [], version: Version.EMPTY }); + super({ errors: [], workflows: [], version: Version.EMPTY }, 'Workflows'); } public load(isReload = false): Observable { if (!isReload) { - this.resetState(); + this.resetState('Loading Initial'); } return this.loadInternal(isReload); @@ -77,7 +77,7 @@ export class WorkflowsState extends State { this.replaceWorkflows(payload, version); }), finalize(() => { - this.next({ isLoading: false }); + this.next({ isLoading: false }, 'Loading Done'); }), shareSubscribed(this.dialogs)); } @@ -118,7 +118,7 @@ export class WorkflowsState extends State { isLoading: false, version, workflows - }); + }, 'Loading Success / Updated'); } private get appName() { diff --git a/frontend/app/shell/pages/internal/profile-menu.component.ts b/frontend/app/shell/pages/internal/profile-menu.component.ts index e2624530b..c27dbbc17 100644 --- a/frontend/app/shell/pages/internal/profile-menu.component.ts +++ b/frontend/app/shell/pages/internal/profile-menu.component.ts @@ -63,12 +63,11 @@ export class ProfileMenuComponent extends StatefulComponent implements On const profileEmail = user.email; const profileDisplayName = user.displayName; - this.next(s => ({ - ...s, + this.next({ profileId, profileEmail, profileDisplayName - })); + }); } })); }