Browse Source

Dev tools. (#617)

* Dev tools.

* Build fix.

* Another attempt.
pull/618/head
Sebastian Stehle 5 years ago
committed by GitHub
parent
commit
92b893db4b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      frontend/app/features/administration/state/event-consumers.state.ts
  2. 28
      frontend/app/features/administration/state/users.state.ts
  3. 6
      frontend/app/features/content/pages/content/references/content-references.component.ts
  4. 4
      frontend/app/features/content/shared/forms/assets-editor.component.ts
  5. 6
      frontend/app/features/content/shared/references/content-creator.component.ts
  6. 6
      frontend/app/features/content/shared/references/content-selector.component.ts
  7. 5
      frontend/app/framework/angular/forms/editors/autocomplete.component.ts
  8. 4
      frontend/app/framework/angular/forms/editors/dropdown.component.html
  9. 35
      frontend/app/framework/angular/forms/editors/dropdown.component.ts
  10. 5
      frontend/app/framework/angular/forms/editors/tag-editor.component.ts
  11. 33
      frontend/app/framework/state.ts
  12. 7
      frontend/app/shared/components/assets/assets-selector.component.ts
  13. 5
      frontend/app/shared/module.ts
  14. 16
      frontend/app/shared/state/apps.state.ts
  15. 10
      frontend/app/shared/state/asset-uploader.state.ts
  16. 83
      frontend/app/shared/state/assets.state.ts
  17. 10
      frontend/app/shared/state/backups.state.ts
  18. 8
      frontend/app/shared/state/clients.state.ts
  19. 10
      frontend/app/shared/state/comments.state.ts
  20. 34
      frontend/app/shared/state/contents.state.ts
  21. 14
      frontend/app/shared/state/contributors.state.ts
  22. 10
      frontend/app/shared/state/languages.state.ts
  23. 10
      frontend/app/shared/state/patterns.state.ts
  24. 12
      frontend/app/shared/state/plans.state.ts
  25. 10
      frontend/app/shared/state/roles.state.ts
  26. 33
      frontend/app/shared/state/rule-events.state.ts
  27. 16
      frontend/app/shared/state/rules.state.ts
  28. 24
      frontend/app/shared/state/schemas.state.ts
  29. 23
      frontend/app/shared/state/ui.state.ts
  30. 8
      frontend/app/shared/state/workflows.state.ts
  31. 5
      frontend/app/shell/pages/internal/profile-menu.component.ts

12
frontend/app/features/administration/state/event-consumers.state.ts

@ -39,12 +39,12 @@ export class EventConsumersState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly eventConsumersService: EventConsumersService private readonly eventConsumersService: EventConsumersService
) { ) {
super({ eventConsumers: [] }); super({ eventConsumers: [] }, 'EventConsumers');
} }
public load(isReload = false, silent = false): Observable<any> { public load(isReload = false, silent = false): Observable<any> {
if (isReload && !silent) { if (isReload && !silent) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload, silent); return this.loadInternal(isReload, silent);
@ -52,7 +52,7 @@ export class EventConsumersState extends State<Snapshot> {
private loadInternal(isReload: boolean, silent: boolean): Observable<any> { private loadInternal(isReload: boolean, silent: boolean): Observable<any> {
if (!silent) { if (!silent) {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
} }
return this.eventConsumersService.getEventConsumers().pipe( return this.eventConsumersService.getEventConsumers().pipe(
@ -65,10 +65,10 @@ export class EventConsumersState extends State<Snapshot> {
eventConsumers, eventConsumers,
isLoaded: true, isLoaded: true,
isLoading: false isLoading: false
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs, { silent })); shareSubscribed(this.dialogs, { silent }));
} }
@ -102,6 +102,6 @@ export class EventConsumersState extends State<Snapshot> {
const eventConsumers = s.eventConsumers.replaceBy('name', eventConsumer); const eventConsumers = s.eventConsumers.replaceBy('name', eventConsumer);
return { ...s, eventConsumers }; return { ...s, eventConsumers };
}); }, 'Updated');
} }
} }

28
frontend/app/features/administration/state/users.state.ts

@ -8,7 +8,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import '@app/framework/utils/rxjs-extensions'; import '@app/framework/utils/rxjs-extensions';
import { DialogService, getPagingInfo, ListState, shareSubscribed, State } from '@app/shared'; 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 { catchError, finalize, tap } from 'rxjs/operators';
import { CreateUserDto, UpdateUserDto, UserDto, UsersService } from './../services/users.service'; import { CreateUserDto, UpdateUserDto, UserDto, UsersService } from './../services/users.service';
@ -58,13 +58,13 @@ export class UsersState extends State<Snapshot> {
page: 0, page: 0,
pageSize: 10, pageSize: 10,
total: 0 total: 0
}); }, 'Users');
} }
public select(id: string | null): Observable<UserDto | null> { public select(id: string | null): Observable<UserDto | null> {
return this.loadUser(id).pipe( return this.loadUser(id).pipe(
tap(selectedUser => { tap(selectedUser => {
this.next({ selectedUser }); this.next({ selectedUser }, 'Selected');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -85,14 +85,14 @@ export class UsersState extends State<Snapshot> {
public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> { public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState({ selectedUser: this.snapshot.selectedUser, ...update }); this.resetState({ selectedUser: this.snapshot.selectedUser, ...update }, 'Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
const { page, pageSize, query } = this.snapshot; const { page, pageSize, query } = this.snapshot;
@ -120,10 +120,10 @@ export class UsersState extends State<Snapshot> {
selectedUser, selectedUser,
total total
}; };
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -135,7 +135,7 @@ export class UsersState extends State<Snapshot> {
const users = [created, ...s.users].slice(0, s.pageSize); const users = [created, ...s.users].slice(0, s.pageSize);
return { ...s, users, total: s.total + 1 }; return { ...s, users, total: s.total + 1 };
}); }, 'Created');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -164,14 +164,18 @@ export class UsersState extends State<Snapshot> {
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
public search(query: string): Observable<UsersResult> { public search(query: string) {
this.next({ query, page: 0 }); if (!this.next({ query, page: 0 }, 'Loading Search')) {
return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }
public page(paging: { page: number, pageSize: number }) { public page(paging: { page: number, pageSize: number }) {
this.next(paging); if (!this.next(paging, 'Loading Paged')) {
return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }
@ -186,6 +190,6 @@ export class UsersState extends State<Snapshot> {
users.find(x => x.id === user.id); users.find(x => x.id === user.id);
return { ...s, users, selectedUser }; return { ...s, users, selectedUser };
}); }, 'Updated');
} }
} }

6
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 { 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({ @Component({
selector: 'sqx-content-references', selector: 'sqx-content-references',
@ -14,7 +14,7 @@ import { AppLanguageDto, ContentDto, ManualContentsState, QuerySynchronizer, Rou
templateUrl: './content-references.component.html', templateUrl: './content-references.component.html',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ providers: [
Router2State, ManualContentsState Router2State, ComponentContentsState
] ]
}) })
export class ContentReferencesComponent implements OnChanges { export class ContentReferencesComponent implements OnChanges {
@ -29,7 +29,7 @@ export class ContentReferencesComponent implements OnChanges {
constructor( constructor(
public readonly contentsRoute: Router2State, public readonly contentsRoute: Router2State,
public readonly contentsState: ManualContentsState public readonly contentsState: ComponentContentsState
) { ) {
} }

4
frontend/app/features/content/shared/forms/assets-editor.component.ts

@ -153,8 +153,8 @@ export class AssetsEditorComponent extends StatefulControlComponent<State, Reado
public removeLoadingAsset(file: File) { public removeLoadingAsset(file: File) {
this.next(s => ({ this.next(s => ({
...s, assetFiles: ...s,
s.assetFiles.removed(file) assetFiles: s.assetFiles.removed(file)
})); }));
} }

6
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 { 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({ @Component({
selector: 'sqx-content-creator', selector: 'sqx-content-creator',
styleUrls: ['./content-creator.component.scss'], styleUrls: ['./content-creator.component.scss'],
templateUrl: './content-creator.component.html', templateUrl: './content-creator.component.html',
providers: [ providers: [
ManualContentsState ComponentContentsState
] ]
}) })
export class ContentCreatorComponent extends ResourceOwner implements OnInit { export class ContentCreatorComponent extends ResourceOwner implements OnInit {
@ -38,7 +38,7 @@ export class ContentCreatorComponent extends ResourceOwner implements OnInit {
public contentForm: EditContentForm; public contentForm: EditContentForm;
constructor( constructor(
private readonly contentsState: ManualContentsState, private readonly contentsState: ComponentContentsState,
private readonly schemasState: SchemasState, private readonly schemasState: SchemasState,
private readonly changeDetector: ChangeDetectorRef private readonly changeDetector: ChangeDetectorRef
) { ) {

6
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 { 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({ @Component({
selector: 'sqx-content-selector', selector: 'sqx-content-selector',
styleUrls: ['./content-selector.component.scss'], styleUrls: ['./content-selector.component.scss'],
templateUrl: './content-selector.component.html', templateUrl: './content-selector.component.html',
providers: [ providers: [
ManualContentsState ComponentContentsState
] ]
}) })
export class ContentSelectorComponent extends ResourceOwner implements OnInit { export class ContentSelectorComponent extends ResourceOwner implements OnInit {
@ -47,7 +47,7 @@ export class ContentSelectorComponent extends ResourceOwner implements OnInit {
constructor( constructor(
public readonly appsState: AppsState, public readonly appsState: AppsState,
public readonly apiUrl: ApiUrlConfig, public readonly apiUrl: ApiUrlConfig,
public readonly contentsState: ManualContentsState, public readonly contentsState: ComponentContentsState,
public readonly schemasState: SchemasState, public readonly schemasState: SchemasState,
private readonly changeDetector: ChangeDetectorRef private readonly changeDetector: ChangeDetectorRef
) { ) {

5
frontend/app/framework/angular/forms/editors/autocomplete.component.ts

@ -126,12 +126,11 @@ export class AutocompleteComponent extends StatefulControlComponent<State, Reado
} }
})) }))
.subscribe(items => { .subscribe(items => {
this.next(s => ({ this.next({
...s,
suggestedIndex: -1, suggestedIndex: -1,
suggestedItems: items || [], suggestedItems: items || [],
isSearching: false isSearching: false
})); });
})); }));
} }

4
frontend/app/framework/angular/forms/editors/dropdown.component.html

@ -20,10 +20,10 @@
<div class="control-dropdown-items" #container> <div class="control-dropdown-items" #container>
<div *ngFor="let item of snapshot.suggestedItems; let i = index;" class="control-dropdown-item control-dropdown-item-selectable" <div *ngFor="let item of snapshot.suggestedItems; let i = index;" class="control-dropdown-item control-dropdown-item-selectable"
[class.active]="i === snapshot.selectedIndex" [class.active]="i === snapshot.suggestedIndex"
[class.separated]="separated" [class.separated]="separated"
(mousedown)="selectIndexAndClose(i)" (mousedown)="selectIndexAndClose(i)"
[sqxScrollActive]="i === snapshot.selectedIndex" [sqxScrollActive]="i === snapshot.suggestedIndex"
[sqxScrollContainer]="container"> [sqxScrollContainer]="container">
<ng-container *ngIf="!templateItem">{{item}}</ng-container> <ng-container *ngIf="!templateItem">{{item}}</ng-container>

35
frontend/app/framework/angular/forms/editors/dropdown.component.ts

@ -23,7 +23,7 @@ interface State {
suggestedItems: ReadonlyArray<any>; suggestedItems: ReadonlyArray<any>;
// The selected suggested index. // The selected suggested index.
selectedIndex: number; suggestedIndex: number;
// The selected item. // The selected item.
selectedItem?: number; selectedItem?: number;
@ -71,8 +71,8 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
constructor(changeDetector: ChangeDetectorRef) { constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, { super(changeDetector, {
selectedIndex: -1,
selectedItem: undefined, selectedItem: undefined,
suggestedIndex: -1,
suggestedItems: [] suggestedItems: []
}); });
} }
@ -98,12 +98,10 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
} }
})) }))
.subscribe(({ query, items }) => { .subscribe(({ query, items }) => {
this.next(s => ({ this.next({
...s,
suggestedIndex: 0,
suggestedItems: items || [], suggestedItems: items || [],
query query
})); });
})); }));
} }
@ -113,11 +111,10 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
this.resetSearch(); this.resetSearch();
this.next(s => ({ this.next({
...s,
suggestedIndex: this.getSelectedIndex(this.value), suggestedIndex: this.getSelectedIndex(this.value),
suggestedItems: this.items || [] suggestedItems: this.items || []
})); });
} }
} }
@ -159,7 +156,7 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
this.selectNextIndex(); this.selectNextIndex();
return false; return false;
} else if (Keys.isEnter(event)) { } else if (Keys.isEnter(event)) {
this.selectIndexAndClose(this.snapshot.selectedIndex); this.selectIndexAndClose(this.snapshot.suggestedIndex);
return false; return false;
} else if (Keys.isEscape(event) && this.dropdown.isOpen) { } else if (Keys.isEscape(event) && this.dropdown.isOpen) {
this.close(); this.close();
@ -194,25 +191,25 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
} }
public selectPrevIndex() { public selectPrevIndex() {
this.selectIndex(this.snapshot.selectedIndex - 1, true); this.selectIndex(this.snapshot.suggestedIndex - 1, true);
} }
public selectNextIndex() { public selectNextIndex() {
this.selectIndex(this.snapshot.selectedIndex + 1, true); this.selectIndex(this.snapshot.suggestedIndex + 1, true);
} }
public selectIndex(selectedIndex: number, fromUserAction: boolean) { public selectIndex(suggestedIndex: number, fromUserAction: boolean) {
const items = this.snapshot.suggestedItems || []; const items = this.snapshot.suggestedItems || [];
if (selectedIndex < 0) { if (suggestedIndex < 0) {
selectedIndex = 0; suggestedIndex = 0;
} }
if (selectedIndex >= items.length) { if (suggestedIndex >= items.length) {
selectedIndex = items.length - 1; suggestedIndex = items.length - 1;
} }
const selectedItem = items[selectedIndex]; const selectedItem = items[suggestedIndex];
if (fromUserAction) { if (fromUserAction) {
let selectedValue = selectedItem; let selectedValue = selectedItem;
@ -229,7 +226,7 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
} }
} }
this.next({ selectedIndex, selectedItem }); this.next({ suggestedIndex, selectedItem });
} }
private getSelectedIndex(value: any) { private getSelectedIndex(value: any) {

5
frontend/app/framework/angular/forms/editors/tag-editor.component.ts

@ -156,11 +156,10 @@ export class TagEditorComponent extends StatefulControlComponent<State, Readonly
} }
})) }))
.subscribe(items => { .subscribe(items => {
this.next(s => ({ this.next({
...s,
suggestedIndex: -1, suggestedIndex: -1,
suggestedItems: items || [] suggestedItems: items || []
})); });
})); }));
} }

33
frontend/app/framework/state.ts

@ -100,8 +100,11 @@ export interface ListState<TQuery = any> {
query?: TQuery; query?: TQuery;
} }
const devToolsExtension = window['__REDUX_DEVTOOLS_EXTENSION__'];
export class State<T extends {}> { export class State<T extends {}> {
private readonly state: BehaviorSubject<Readonly<T>>; private readonly state: BehaviorSubject<Readonly<T>>;
private readonly devTools?: any;
public get changes(): Observable<Readonly<T>> { public get changes(): Observable<Readonly<T>> {
return this.state; return this.state;
@ -127,20 +130,32 @@ export class State<T extends {}> {
} }
constructor( constructor(
private readonly initialState: Readonly<T> private readonly initialState: Readonly<T>,
private readonly debugName?: string
) { ) {
this.state = new BehaviorSubject(initialState); 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<T>) | Partial<T>) { public resetState(update?: ((v: T) => Readonly<T>) | Partial<T> | string, action = 'Reset') {
return this.updateState(this.initialState, update); if (Types.isString(update)) {
return this.updateState(this.initialState, {}, update);
} else {
return this.updateState(this.initialState, update, action);
}
} }
public next(update: ((v: T) => Readonly<T>) | Partial<T>) { public next(update: ((v: T) => Readonly<T>) | Partial<T>, action = 'Update') {
return this.updateState(this.state.value, update); return this.updateState(this.state.value, update, action);
} }
private updateState(state: T, update?: ((v: T) => Readonly<T>) | Partial<T>) { private updateState(state: T, update?: ((v: T) => Readonly<T>) | Partial<T>, action?: string) {
let newState = state; let newState = state;
if (update) { if (update) {
@ -167,6 +182,12 @@ export class State<T extends {}> {
} }
if (isChanged) { if (isChanged) {
if (action && this.devTools) {
const name = `[${this.debugName}] ${action}`;
this.devTools?.send(name, newState);
}
this.state.next(newState); this.state.next(newState);
} }

7
frontend/app/shared/components/assets/assets-selector.component.ts

@ -6,7 +6,7 @@
*/ */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core'; 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 { interface State {
// The selected assets. // The selected assets.
@ -23,6 +23,9 @@ interface State {
selector: 'sqx-assets-selector', selector: 'sqx-assets-selector',
styleUrls: ['./assets-selector.component.scss'], styleUrls: ['./assets-selector.component.scss'],
templateUrl: './assets-selector.component.html', templateUrl: './assets-selector.component.html',
providers: [
ComponentAssetsState
],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class AssetsSelectorComponent extends StatefulComponent<State> implements OnInit { export class AssetsSelectorComponent extends StatefulComponent<State> implements OnInit {
@ -30,7 +33,7 @@ export class AssetsSelectorComponent extends StatefulComponent<State> implements
public select = new EventEmitter<ReadonlyArray<AssetDto>>(); public select = new EventEmitter<ReadonlyArray<AssetDto>>();
constructor(changeDector: ChangeDetectorRef, constructor(changeDector: ChangeDetectorRef,
public readonly assetsState: AssetsState, public readonly assetsState: ComponentAssetsState,
public readonly localStore: LocalStoreService public readonly localStore: LocalStoreService
) { ) {
super(changeDector, { super(changeDector, {

5
frontend/app/shared/module.ts

@ -15,7 +15,7 @@ import { SqxFrameworkModule } from '@app/framework';
import { MentionModule } from 'angular-mentions'; import { MentionModule } from 'angular-mentions';
import { NgxDocViewerModule } from 'ngx-doc-viewer'; import { NgxDocViewerModule } from 'ngx-doc-viewer';
import { PreviewableType } from './components/assets/pipes'; 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'; import { SearchService } from './services/search.service';
@NgModule({ @NgModule({
@ -117,9 +117,6 @@ import { SearchService } from './services/search.service';
UserNameRefPipe, UserNameRefPipe,
UserPicturePipe, UserPicturePipe,
UserPictureRefPipe UserPictureRefPipe
],
providers: [
AssetsDialogState
] ]
}) })
export class SqxSharedModule { export class SqxSharedModule {

16
frontend/app/shared/state/apps.state.ts

@ -39,7 +39,7 @@ export class AppsState extends State<Snapshot> {
private readonly appsService: AppsService, private readonly appsService: AppsService,
private readonly dialogs: DialogService private readonly dialogs: DialogService
) { ) {
super({ apps: [], selectedApp: null }); super({ apps: [], selectedApp: null }, 'Apps');
} }
public reloadSelected() { public reloadSelected() {
@ -50,9 +50,7 @@ export class AppsState extends State<Snapshot> {
public select(name: string | null): Observable<AppDto | null> { public select(name: string | null): Observable<AppDto | null> {
return this.loadApp(name, true).pipe( return this.loadApp(name, true).pipe(
tap(selectedApp => { tap(selectedApp => {
this.next(s => { this.next({ selectedApp }, 'Selected');
return { ...s, selectedApp };
});
})); }));
} }
@ -79,9 +77,7 @@ export class AppsState extends State<Snapshot> {
public load(): Observable<any> { public load(): Observable<any> {
return this.appsService.getApps().pipe( return this.appsService.getApps().pipe(
tap(apps => { tap(apps => {
this.next(s => { this.next({ apps }, 'Loaded');
return { ...s, apps };
});
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -93,7 +89,7 @@ export class AppsState extends State<Snapshot> {
const apps = [...s.apps, created].sortedByString(x => x.displayName); const apps = [...s.apps, created].sortedByString(x => x.displayName);
return { ...s, apps }; return { ...s, apps };
}); }, 'Created');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -151,7 +147,7 @@ export class AppsState extends State<Snapshot> {
s.selectedApp; s.selectedApp;
return { ...s, apps, selectedApp }; return { ...s, apps, selectedApp };
}); }, 'Deleted');
} }
private replaceApp(updated: AppDto, app: AppDto) { private replaceApp(updated: AppDto, app: AppDto) {
@ -165,6 +161,6 @@ export class AppsState extends State<Snapshot> {
s.selectedApp; s.selectedApp;
return { ...s, apps, selectedApp }; return { ...s, apps, selectedApp };
}); }, 'Updated');
} }
} }

10
frontend/app/shared/state/asset-uploader.state.ts

@ -50,7 +50,7 @@ export class AssetUploaderState extends State<Snapshot> {
private readonly assetsService: AssetsService, private readonly assetsService: AssetsService,
private readonly dialogs: DialogService private readonly dialogs: DialogService
) { ) {
super({ uploads: [] }); super({ uploads: [] }, 'AssetUploader');
} }
public stopUpload(upload: Upload) { public stopUpload(upload: Upload) {
@ -60,7 +60,7 @@ export class AssetUploaderState extends State<Snapshot> {
const uploads = s.uploads.removeBy('id', upload); const uploads = s.uploads.removeBy('id', upload);
return { ...s, uploads }; return { ...s, uploads };
}); }, 'Stopped');
} }
public uploadFile(file: File, target?: AssetsState): Observable<UploadResult> { public uploadFile(file: File, target?: AssetsState): Observable<UploadResult> {
@ -125,7 +125,7 @@ export class AssetUploaderState extends State<Snapshot> {
const uploads = s.uploads.removeBy('id', upload); const uploads = s.uploads.removeBy('id', upload);
return { ...s, uploads }; return { ...s, uploads };
}); }, 'Upload Done');
}, 10000); }, 10000);
@ -139,7 +139,7 @@ export class AssetUploaderState extends State<Snapshot> {
const uploads = s.uploads.replaceBy('id', upload); const uploads = s.uploads.replaceBy('id', upload);
return { ...s, uploads }; return { ...s, uploads };
}); }, 'Updated');
return upload; return upload;
} }
@ -149,7 +149,7 @@ export class AssetUploaderState extends State<Snapshot> {
const uploads = [upload, ...s.uploads]; const uploads = [upload, ...s.uploads];
return { ...s, uploads }; return { ...s, uploads };
}); }, 'Upload Started');
} }
private get appName() { private get appName() {

83
frontend/app/shared/state/assets.state.ts

@ -52,8 +52,7 @@ interface Snapshot extends ListState<Query> {
canCreateFolders?: boolean; canCreateFolders?: boolean;
} }
@Injectable() export abstract class AssetsStateBase extends State<Snapshot> {
export class AssetsState extends State<Snapshot> {
public tagsUnsorted = public tagsUnsorted =
this.project(x => x.tagsAvailable); this.project(x => x.tagsAvailable);
@ -105,7 +104,7 @@ export class AssetsState extends State<Snapshot> {
public canCreateFolders = public canCreateFolders =
this.project(x => x.canCreateFolders === true); this.project(x => x.canCreateFolders === true);
constructor( constructor(name: string,
private readonly appsState: AppsState, private readonly appsState: AppsState,
private readonly assetsService: AssetsService, private readonly assetsService: AssetsService,
private readonly dialogs: DialogService private readonly dialogs: DialogService
@ -120,19 +119,19 @@ export class AssetsState extends State<Snapshot> {
tagsAvailable: {}, tagsAvailable: {},
tagsSelected: {}, tagsSelected: {},
total: 0 total: 0
}); }, name);
} }
public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> { public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(update); this.resetState(update, 'Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
const query = createQuery(this.snapshot); const query = createQuery(this.snapshot);
@ -161,8 +160,7 @@ export class AssetsState extends State<Snapshot> {
const { items: assets, total } = assetsResult; const { items: assets, total } = assetsResult;
this.next(s => ({ this.next({
...s,
assets, assets,
folders: foldersResult.items, folders: foldersResult.items,
canCreate: assetsResult.canCreate, canCreate: assetsResult.canCreate,
@ -173,10 +171,10 @@ export class AssetsState extends State<Snapshot> {
path, path,
tagsAvailable, tagsAvailable,
total total
})); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -192,7 +190,7 @@ export class AssetsState extends State<Snapshot> {
const tags = updateTags(s, asset); const tags = updateTags(s, asset);
return { ...s, assets, total: s.total + 1, ...tags }; return { ...s, assets, total: s.total + 1, ...tags };
}); }, 'Asset Created');
} }
public createAssetFolder(folderName: string) { public createAssetFolder(folderName: string) {
@ -206,7 +204,7 @@ export class AssetsState extends State<Snapshot> {
const folders = [...s.folders, folder].sortedByString(x => x.folderName); const folders = [...s.folders, folder].sortedByString(x => x.folderName);
return { ...s, folders }; return { ...s, folders };
}); }, 'Folder Created');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -220,7 +218,7 @@ export class AssetsState extends State<Snapshot> {
const assets = s.assets.replaceBy('id', updated); const assets = s.assets.replaceBy('id', updated);
return { ...s, assets, ...tags }; return { ...s, assets, ...tags };
}); }, 'Asset Updated');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -232,7 +230,7 @@ export class AssetsState extends State<Snapshot> {
const folders = s.folders.replaceBy('id', updated); const folders = s.folders.replaceBy('id', updated);
return { ...s, folders }; return { ...s, folders };
}); }, 'Folder Updated');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -246,7 +244,7 @@ export class AssetsState extends State<Snapshot> {
const assets = s.assets.filter(x => x.id !== asset.id); const assets = s.assets.filter(x => x.id !== asset.id);
return { ...s, assets }; return { ...s, assets };
}); }, 'Asset Moving Started');
return this.assetsService.putAssetItemParent(this.appName, asset, { parentId }, asset.version).pipe( return this.assetsService.putAssetItemParent(this.appName, asset, { parentId }, asset.version).pipe(
catchError(error => { catchError(error => {
@ -254,7 +252,7 @@ export class AssetsState extends State<Snapshot> {
const assets = [asset, ...s.assets]; const assets = [asset, ...s.assets];
return { ...s, assets }; return { ...s, assets };
}); }, 'Asset Moving Failed');
return throwError(error); return throwError(error);
}), }),
@ -270,7 +268,7 @@ export class AssetsState extends State<Snapshot> {
const folders = s.folders.filter(x => x.id !== folder.id); const folders = s.folders.filter(x => x.id !== folder.id);
return { ...s, folders }; return { ...s, folders };
}); }, 'Folder Moving Started');
return this.assetsService.putAssetItemParent(this.appName, folder, { parentId }, folder.version).pipe( return this.assetsService.putAssetItemParent(this.appName, folder, { parentId }, folder.version).pipe(
catchError(error => { catchError(error => {
@ -278,7 +276,7 @@ export class AssetsState extends State<Snapshot> {
const folders = [...s.folders, folder].sortedByString(x => x.folderName); const folders = [...s.folders, folder].sortedByString(x => x.folderName);
return { ...s, folders }; return { ...s, folders };
}); }, 'Folder Moving Done');
return throwError(error); return throwError(error);
}), }),
@ -313,7 +311,7 @@ export class AssetsState extends State<Snapshot> {
const tags = updateTags(s, undefined, asset); const tags = updateTags(s, undefined, asset);
return { ...s, assets, total: s.total - 1, ...tags }; return { ...s, assets, total: s.total - 1, ...tags };
}); }, 'Asset Deleted');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -325,19 +323,23 @@ export class AssetsState extends State<Snapshot> {
const folders = s.folders.filter(x => x.id !== folder.id); const folders = s.folders.filter(x => x.id !== folder.id);
return { ...s, folders }; return { ...s, folders };
}); }, 'Folder Deleted');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
public navigate(parentId: string) { 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); return this.loadInternal(false);
} }
public page(paging: { page: number, pageSize: number }) { public page(paging: { page: number, pageSize: number }) {
this.next(paging); if (!this.next(paging, 'Loading Paged')) {
return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }
@ -373,19 +375,19 @@ export class AssetsState extends State<Snapshot> {
} }
private searchInternal(query?: Query | null, tags?: TagsSelected) { private searchInternal(query?: Query | null, tags?: TagsSelected) {
this.next(s => { const update: Partial<Snapshot> = { page: 0 };
const newState = { ...s, page: 0 };
if (query !== null) { if (query !== null) {
newState.query = query; update.query = query;
} }
if (tags) { if (tags) {
newState.tagsSelected = tags; update.tagsSelected = tags;
} }
return newState; if (!this.next(update, 'Loading Searched')) {
}); return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }
@ -473,4 +475,19 @@ function getSortedTags(tags: { [name: string]: number }) {
} }
@Injectable() @Injectable()
export class AssetsDialogState extends AssetsState { } 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);
}
}

10
frontend/app/shared/state/backups.state.ts

@ -50,12 +50,12 @@ export class BackupsState extends State<Snapshot> {
private readonly backupsService: BackupsService, private readonly backupsService: BackupsService,
private readonly dialogs: DialogService private readonly dialogs: DialogService
) { ) {
super({ backups: [] }); super({ backups: [] }, 'Backups');
} }
public load(isReload = false, silent = false): Observable<any> { public load(isReload = false, silent = false): Observable<any> {
if (isReload && !silent) { if (isReload && !silent) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload, silent); return this.loadInternal(isReload, silent);
@ -63,7 +63,7 @@ export class BackupsState extends State<Snapshot> {
private loadInternal(isReload: boolean, silent: boolean): Observable<any> { private loadInternal(isReload: boolean, silent: boolean): Observable<any> {
if (!silent) { if (!silent) {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
} }
return this.backupsService.getBackups(this.appName).pipe( return this.backupsService.getBackups(this.appName).pipe(
@ -77,10 +77,10 @@ export class BackupsState extends State<Snapshot> {
canCreate, canCreate,
isLoaded: true, isLoaded: true,
isLoading: false isLoading: false
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs, { silent })); shareSubscribed(this.dialogs, { silent }));
} }

8
frontend/app/shared/state/clients.state.ts

@ -55,14 +55,14 @@ export class ClientsState extends State<Snapshot> {
public load(isReload = false): Observable<any> { public load(isReload = false): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return this.clientsService.getClients(this.appName).pipe( return this.clientsService.getClients(this.appName).pipe(
tap(({ version, payload }) => { tap(({ version, payload }) => {
@ -73,7 +73,7 @@ export class ClientsState extends State<Snapshot> {
this.replaceClients(payload, version); this.replaceClients(payload, version);
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -111,7 +111,7 @@ export class ClientsState extends State<Snapshot> {
isLoaded: true, isLoaded: true,
isLoading: false, isLoading: false,
version version
}); }, 'Loading Success / Updated');
} }
private get appName() { private get appName() {

10
frontend/app/shared/state/comments.state.ts

@ -40,7 +40,7 @@ export class CommentsState extends State<Snapshot> {
private readonly orderDescending = false, private readonly orderDescending = false,
initialVersion = -1 initialVersion = -1
) { ) {
super({ comments: [], version: new Version(initialVersion.toString()) }); super({ comments: [], version: new Version(initialVersion.toString()) }, 'Comments');
} }
public load(silent = false): Observable<any> { public load(silent = false): Observable<any> {
@ -68,7 +68,7 @@ export class CommentsState extends State<Snapshot> {
} }
return { ...s, comments, isLoaded: true, version: payload.version }; return { ...s, comments, isLoaded: true, version: payload.version };
}); }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs, { silent })); shareSubscribed(this.dialogs, { silent }));
} }
@ -80,7 +80,7 @@ export class CommentsState extends State<Snapshot> {
const comments = [...s.comments, created]; const comments = [...s.comments, created];
return { ...s, comments }; return { ...s, comments };
}); }, 'Created');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -92,7 +92,7 @@ export class CommentsState extends State<Snapshot> {
const comments = s.comments.removeBy('id', comment); const comments = s.comments.removeBy('id', comment);
return { ...s, comments }; return { ...s, comments };
}); }, 'Deleted');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -105,7 +105,7 @@ export class CommentsState extends State<Snapshot> {
const comments = s.comments.replaceBy('id', updated); const comments = s.comments.replaceBy('id', updated);
return { ...s, comments }; return { ...s, comments };
}); }, 'Updated');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }

34
frontend/app/shared/state/contents.state.ts

@ -86,7 +86,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
return this.appsState.appId; return this.appsState.appId;
} }
constructor( constructor(name: string,
private readonly appsState: AppsState, private readonly appsState: AppsState,
private readonly contentsService: ContentsService, private readonly contentsService: ContentsService,
private readonly dialogs: DialogService private readonly dialogs: DialogService
@ -97,7 +97,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
pageSize: 10, pageSize: 10,
total: 0, total: 0,
validationResults: {} validationResults: {}
}); }, name);
} }
public select(id: string | null): Observable<ContentDto | null> { public select(id: string | null): Observable<ContentDto | null> {
@ -107,7 +107,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
const contents = content ? s.contents.replaceBy('id', content) : s.contents; const contents = content ? s.contents.replaceBy('id', content) : s.contents;
return { ...s, selectedContent: content, contents }; return { ...s, selectedContent: content, contents };
}); }, 'Selected');
})); }));
} }
@ -138,7 +138,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> { public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState({ selectedContent: this.snapshot.selectedContent, ...update }); this.resetState({ selectedContent: this.snapshot.selectedContent, ...update }, 'Loading Intial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
@ -161,7 +161,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
return EMPTY; return EMPTY;
} }
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Done');
const { page, pageSize, query, reference, referencing } = this.snapshot; const { page, pageSize, query, reference, referencing } = this.snapshot;
@ -207,10 +207,10 @@ export abstract class ContentsStateBase extends State<Snapshot> {
statuses, statuses,
total total
}; };
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
})); }));
} }
@ -228,7 +228,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
const contents = [payload, ...s.contents].slice(s.pageSize); const contents = [payload, ...s.contents].slice(s.pageSize);
return { ...s, contents, total: s.total + 1 }; return { ...s, contents, total: s.total + 1 };
}); }, 'Created');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -246,7 +246,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
} }
return { ...s, validationResults }; return { ...s, validationResults };
}); }, 'Validated');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -304,13 +304,17 @@ export abstract class ContentsStateBase extends State<Snapshot> {
} }
public search(query?: Query): Observable<any> { public search(query?: Query): Observable<any> {
this.next({ query, page: 0 }); if (!this.next({ query, page: 0 }, 'Loading Searched')) {
return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }
public page(paging: { page: number, pageSize: number }) { public page(paging: { page: number, pageSize: number }) {
this.next(paging); if (!this.next(paging, 'Loading Done')) {
return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }
@ -331,7 +335,7 @@ export abstract class ContentsStateBase extends State<Snapshot> {
s.selectedContent; s.selectedContent;
return { ...s, contents, selectedContent }; return { ...s, contents, selectedContent };
}); }, 'Updated');
} }
} }
@ -396,7 +400,7 @@ export class ContentsState extends ContentsStateBase {
constructor(appsState: AppsState, contentsService: ContentsService, dialogs: DialogService, constructor(appsState: AppsState, contentsService: ContentsService, dialogs: DialogService,
private readonly schemasState: SchemasState private readonly schemasState: SchemasState
) { ) {
super(appsState, contentsService, dialogs); super('Contents', appsState, contentsService, dialogs);
} }
public get schemaName() { public get schemaName() {
@ -405,13 +409,13 @@ export class ContentsState extends ContentsStateBase {
} }
@Injectable() @Injectable()
export class ManualContentsState extends ContentsStateBase { export class ComponentContentsState extends ContentsStateBase {
public schema: { name: string }; public schema: { name: string };
constructor( constructor(
appsState: AppsState, contentsService: ContentsService, dialogs: DialogService appsState: AppsState, contentsService: ContentsService, dialogs: DialogService
) { ) {
super(appsState, contentsService, dialogs); super('Components Contents', appsState, contentsService, dialogs);
} }
public get schemaName() { public get schemaName() {

14
frontend/app/shared/state/contributors.state.ts

@ -71,7 +71,7 @@ export class ContributorsState extends State<Snapshot> {
pageSize: 10, pageSize: 10,
total: 0, total: 0,
version: Version.EMPTY version: Version.EMPTY
}); }, 'Contributors');
} }
public loadIfNotLoaded(): Observable<any> { public loadIfNotLoaded(): Observable<any> {
@ -84,14 +84,14 @@ export class ContributorsState extends State<Snapshot> {
public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> { public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(update); this.resetState(update, 'Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return this.contributorsService.getContributors(this.appName).pipe( return this.contributorsService.getContributors(this.appName).pipe(
tap(({ version, payload }) => { tap(({ version, payload }) => {
@ -102,17 +102,17 @@ export class ContributorsState extends State<Snapshot> {
this.replaceContributors(version, payload); this.replaceContributors(version, payload);
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
public page(paging: { page: number, pageSize: number }) { public page(paging: { page: number, pageSize: number }) {
this.next(paging); this.next(paging, 'Results Paged');
} }
public search(query: string) { public search(query: string) {
this.next({ query }); this.next({ query }, 'Results Filtered');
} }
public revoke(contributor: ContributorDto): Observable<any> { public revoke(contributor: ContributorDto): Observable<any> {
@ -147,7 +147,7 @@ export class ContributorsState extends State<Snapshot> {
maxContributors, maxContributors,
total: items.length, total: items.length,
version version
}); }, 'Loading Success / Updated');
} }
private get appName() { private get appName() {

10
frontend/app/shared/state/languages.state.ts

@ -87,19 +87,19 @@ export class LanguagesState extends State<Snapshot> {
allLanguagesNew: [], allLanguagesNew: [],
languages: [], languages: [],
version: Version.EMPTY version: Version.EMPTY
}); }, 'Languages');
} }
public load(isReload = false): Observable<any> { public load(isReload = false): Observable<any> {
if (isReload) { if (isReload) {
this.resetState(); this.resetState('Loading Success');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return forkJoin([ return forkJoin([
this.getAllLanguages(), this.getAllLanguages(),
@ -117,7 +117,7 @@ export class LanguagesState extends State<Snapshot> {
this.replaceLanguages(languages.payload, languages.version, sorted); this.replaceLanguages(languages.payload, languages.version, sorted);
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -162,7 +162,7 @@ export class LanguagesState extends State<Snapshot> {
languages: languages.map(x => this.createLanguage(x, languages)), languages: languages.map(x => this.createLanguage(x, languages)),
version version
}; };
}); }, 'Loading Success / Updated');
} }
private get appName() { private get appName() {

10
frontend/app/shared/state/patterns.state.ts

@ -50,19 +50,19 @@ export class PatternsState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly patternsService: PatternsService private readonly patternsService: PatternsService
) { ) {
super({ patterns: [], version: Version.EMPTY }); super({ patterns: [], version: Version.EMPTY }, 'Patterns');
} }
public load(isReload = false): Observable<any> { public load(isReload = false): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return this.patternsService.getPatterns(this.appName).pipe( return this.patternsService.getPatterns(this.appName).pipe(
tap(({ version, payload }) => { tap(({ version, payload }) => {
@ -73,7 +73,7 @@ export class PatternsState extends State<Snapshot> {
this.replacePatterns(payload, version); this.replacePatterns(payload, version);
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareMapSubscribed(this.dialogs, x => x.payload)); shareMapSubscribed(this.dialogs, x => x.payload));
} }
@ -110,7 +110,7 @@ export class PatternsState extends State<Snapshot> {
isLoading: false, isLoading: false,
patterns, patterns,
version, canCreate version, canCreate
}); }, 'Loading Success / Updated');
} }
private get appName() { private get appName() {

12
frontend/app/shared/state/plans.state.ts

@ -76,19 +76,19 @@ export class PlansState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly plansService: PlansService private readonly plansService: PlansService
) { ) {
super({ plans: [], version: Version.EMPTY }); super({ plans: [], version: Version.EMPTY }, 'Plans');
} }
public load(isReload = false, overridePlanId?: string): Observable<any> { public load(isReload = false, overridePlanId?: string): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload, overridePlanId); return this.loadInternal(isReload, overridePlanId);
} }
private loadInternal(isReload: boolean, overridePlanId?: string): Observable<any> { private loadInternal(isReload: boolean, overridePlanId?: string): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return this.plansService.getPlans(this.appName).pipe( return this.plansService.getPlans(this.appName).pipe(
tap(({ version, payload }) => { tap(({ version, payload }) => {
@ -106,10 +106,10 @@ export class PlansState extends State<Snapshot> {
isOwner: !payload.planOwner || payload.planOwner === this.userId, isOwner: !payload.planOwner || payload.planOwner === this.userId,
plans, plans,
version version
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -124,7 +124,7 @@ export class PlansState extends State<Snapshot> {
const plans = s.plans.map(x => this.createPlan(x.plan, planId)); const plans = s.plans.map(x => this.createPlan(x.plan, planId));
return { ...s, plans, isOwner: true, version }; return { ...s, plans, isOwner: true, version };
}); }, 'Change');
} }
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));

10
frontend/app/shared/state/roles.state.ts

@ -50,19 +50,19 @@ export class RolesState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly rolesService: RolesService private readonly rolesService: RolesService
) { ) {
super({ roles: [], version: Version.EMPTY }); super({ roles: [], version: Version.EMPTY }, 'Roles');
} }
public load(isReload = false): Observable<any> { public load(isReload = false): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Success');
return this.rolesService.getRoles(this.appName).pipe( return this.rolesService.getRoles(this.appName).pipe(
tap(({ version, payload }) => { tap(({ version, payload }) => {
@ -73,7 +73,7 @@ export class RolesState extends State<Snapshot> {
this.replaceRoles(payload, version); this.replaceRoles(payload, version);
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -111,7 +111,7 @@ export class RolesState extends State<Snapshot> {
isLoading: false, isLoading: false,
roles, roles,
version version
}); }, 'Loading Success / Updated');
} }
private get appName() { private get appName() {

33
frontend/app/shared/state/rule-events.state.ts

@ -47,19 +47,19 @@ export class RuleEventsState extends State<Snapshot> {
page: 0, page: 0,
pageSize: 30, pageSize: 30,
total: 0 total: 0
}); }, 'Rule Events');
} }
public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> { public load(isReload = false, update: Partial<Snapshot> = {}): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState({ ruleId: this.snapshot.ruleId, ...update }); this.resetState({ ruleId: this.snapshot.ruleId, ...update }, 'Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
const { page, pageSize, ruleId } = this.snapshot; const { page, pageSize, ruleId } = this.snapshot;
@ -72,18 +72,15 @@ export class RuleEventsState extends State<Snapshot> {
this.dialogs.notifyInfo('i18n:rules.ruleEvents.reloaded'); this.dialogs.notifyInfo('i18n:rules.ruleEvents.reloaded');
} }
return this.next(s => { return this.next({
return { isLoaded: true,
...s, isLoading: false,
isLoaded: true, ruleEvents,
isLoading: false, total
ruleEvents, }, 'Loading Success');
total
};
});
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -103,23 +100,23 @@ export class RuleEventsState extends State<Snapshot> {
const ruleEvents = s.ruleEvents.replaceBy('id', setCancelled(event)); const ruleEvents = s.ruleEvents.replaceBy('id', setCancelled(event));
return { ...s, ruleEvents, isLoaded: true }; return { ...s, ruleEvents, isLoaded: true };
}); }, 'Cancel');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
public filterByRule(ruleId?: string) { public filterByRule(ruleId?: string) {
if (ruleId === this.snapshot.ruleId) { if (!this.next({ page: 0, ruleId }, 'Loading Rule')) {
return EMPTY; return EMPTY;
} }
this.next({ page: 0, ruleId });
return this.loadInternal(false); return this.loadInternal(false);
} }
public page(paging: { page: number, pageSize: number }) { public page(paging: { page: number, pageSize: number }) {
this.next(paging); if (!this.next(paging, 'Loading Paged')) {
return EMPTY;
}
return this.loadInternal(false); return this.loadInternal(false);
} }

16
frontend/app/shared/state/rules.state.ts

@ -68,19 +68,19 @@ export class RulesState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly rulesService: RulesService private readonly rulesService: RulesService
) { ) {
super({ rules: [] }); super({ rules: [] }, 'Rules');
} }
public load(isReload = false): Observable<any> { public load(isReload = false): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return this.rulesService.getRules(this.appName).pipe( return this.rulesService.getRules(this.appName).pipe(
tap(({ items: rules, runningRuleId, canCancelRun, canCreate, canReadEvents }) => { tap(({ items: rules, runningRuleId, canCancelRun, canCreate, canReadEvents }) => {
@ -96,10 +96,10 @@ export class RulesState extends State<Snapshot> {
isLoading: false, isLoading: false,
runningRuleId, runningRuleId,
rules rules
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -111,7 +111,7 @@ export class RulesState extends State<Snapshot> {
const rules = [...s.rules, created]; const rules = [...s.rules, created];
return { ...s, rules }; return { ...s, rules };
}); }, 'Created');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -123,7 +123,7 @@ export class RulesState extends State<Snapshot> {
const rules = s.rules.removeBy('id', rule); const rules = s.rules.removeBy('id', rule);
return { ...s, rules }; return { ...s, rules };
}); }, 'Deleted');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -205,7 +205,7 @@ export class RulesState extends State<Snapshot> {
const rules = s.rules.replaceBy('id', rule); const rules = s.rules.replaceBy('id', rule);
return { ...s, rules }; return { ...s, rules };
}); }, 'Updated');
} }
private get appName() { private get appName() {

24
frontend/app/shared/state/schemas.state.ts

@ -76,15 +76,13 @@ export class SchemasState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly schemasService: SchemasService private readonly schemasService: SchemasService
) { ) {
super({ schemas: [], categories: [] }); super({ schemas: [], categories: [] }, 'Schemas');
} }
public select(idOrName: string | null): Observable<SchemaDetailsDto | null> { public select(idOrName: string | null): Observable<SchemaDetailsDto | null> {
return this.loadSchema(idOrName).pipe( return this.loadSchema(idOrName).pipe(
tap(selectedSchema => { tap(selectedSchema => {
this.next(s => { this.next({ selectedSchema }, 'Selected');
return { ...s, selectedSchema };
});
})); }));
} }
@ -107,7 +105,7 @@ export class SchemasState extends State<Snapshot> {
const schemas = s.schemas.replaceBy('id', schema); const schemas = s.schemas.replaceBy('id', schema);
return { ...s, schemas }; return { ...s, schemas };
}); }, 'Loading Schema Done');
}), }),
catchError(() => of(null))); catchError(() => of(null)));
} }
@ -125,7 +123,7 @@ export class SchemasState extends State<Snapshot> {
} }
private loadInternal(isReload: boolean): Observable<any> { private loadInternal(isReload: boolean): Observable<any> {
this.next({ isLoading: true }); this.next({ isLoading: true }, 'Loading Started');
return this.schemasService.getSchemas(this.appName).pipe( return this.schemasService.getSchemas(this.appName).pipe(
tap(({ items, canCreate }) => { tap(({ items, canCreate }) => {
@ -140,10 +138,10 @@ export class SchemasState extends State<Snapshot> {
isLoaded: true, isLoaded: true,
isLoading: true, isLoading: true,
schemas schemas
}); }, 'Loading Success');
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -155,7 +153,7 @@ export class SchemasState extends State<Snapshot> {
const schemas = [...s.schemas, created].sortedByString(x => x.displayName); const schemas = [...s.schemas, created].sortedByString(x => x.displayName);
return { ...s, schemas }; return { ...s, schemas };
}); }, 'Created');
}), }),
shareSubscribed(this.dialogs, { silent: true })); shareSubscribed(this.dialogs, { silent: true }));
} }
@ -172,7 +170,7 @@ export class SchemasState extends State<Snapshot> {
null; null;
return { ...s, schemas, selectedSchema }; return { ...s, schemas, selectedSchema };
}); }, 'Deleted');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -182,7 +180,7 @@ export class SchemasState extends State<Snapshot> {
const categories = [...s.categories, name]; const categories = [...s.categories, name];
return { ...s, categories }; return { ...s, categories };
}); }, 'Category Added');
} }
public removeCategory(name: string) { public removeCategory(name: string) {
@ -190,7 +188,7 @@ export class SchemasState extends State<Snapshot> {
const categories = s.categories.removed(name); const categories = s.categories.removed(name);
return { ...s, categories }; return { ...s, categories };
}); }, 'Category Removed');
} }
public publish(schema: SchemaDto): Observable<SchemaDto> { public publish(schema: SchemaDto): Observable<SchemaDto> {
@ -355,7 +353,7 @@ export class SchemasState extends State<Snapshot> {
s.selectedSchema; s.selectedSchema;
return { ...s, schemas, selectedSchema }; return { ...s, schemas, selectedSchema };
}); }, 'Updated');
} else { } else {
if (updateText) { if (updateText) {
this.dialogs.notifyInfo('i18n:common.nothingChanged'); this.dialogs.notifyInfo('i18n:common.nothingChanged');

23
frontend/app/shared/state/ui.state.ts

@ -90,7 +90,7 @@ export class UIState extends State<Snapshot> {
super({ super({
settings: {}, settings: {},
settingsCommon: {} settingsCommon: {}
}); }, 'Setting');
this.loadResources(); this.loadResources();
this.loadCommon(); this.loadCommon();
@ -107,36 +107,35 @@ export class UIState extends State<Snapshot> {
settings: s.settingsCommon, settings: s.settingsCommon,
settingsShared: undefined, settingsShared: undefined,
settingsUser: undefined settingsUser: undefined
})); }), 'Loading Done');
this.uiService.getSharedSettings(app) this.uiService.getSharedSettings(app)
.subscribe(payload => { .subscribe(payload => {
this.next(s => updateSettings(s, { settingsShared: payload })); this.next(s => updateSettings(s, { settingsShared: payload }), 'Loading Shared Success');
}); });
this.uiService.getUserSettings(app) this.uiService.getUserSettings(app)
.subscribe(payload => { .subscribe(payload => {
this.next(s => updateSettings(s, { settingsUser: payload })); this.next(s => updateSettings(s, { settingsUser: payload }), 'Loading User Success');
}); });
} }
private loadCommon() { private loadCommon() {
this.uiService.getCommonSettings() this.uiService.getCommonSettings()
.subscribe(payload => { .subscribe(payload => {
this.next(s => updateSettings(s, { settingsCommon: payload })); this.next(s => updateSettings(s, { settingsCommon: payload }), 'Loading Common Done');
}); });
} }
private loadResources() { private loadResources() {
this.usersService.getResources() this.usersService.getResources()
.subscribe(payload => { .subscribe(payload => {
this.next(s => ({ this.next({
...s,
canReadEvents: hasAnyLink(payload, 'admin/events'), canReadEvents: hasAnyLink(payload, 'admin/events'),
canReadUsers: hasAnyLink(payload, 'admin/users'), canReadUsers: hasAnyLink(payload, 'admin/users'),
canRestore: hasAnyLink(payload, 'admin/restore'), canRestore: hasAnyLink(payload, 'admin/restore'),
canUseOrleans: hasAnyLink(payload, 'admin/orleans') canUseOrleans: hasAnyLink(payload, 'admin/orleans')
})); }, 'Loading Resources Done');
}); });
} }
@ -156,7 +155,7 @@ export class UIState extends State<Snapshot> {
current[key] = value; 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<Snapshot> {
current[key] = value; 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<Snapshot> {
delete current[key]; delete current[key];
this.next(s => updateSettings(s, { settingsUser: root })); this.next(s => updateSettings(s, { settingsUser: root }), 'Removed User');
return true; return true;
} }
@ -200,7 +199,7 @@ export class UIState extends State<Snapshot> {
delete current[key]; delete current[key];
this.next(s => updateSettings(s, { settingsShared: root })); this.next(s => updateSettings(s, { settingsShared: root }), 'Removed Shared');
return true; return true;
} }

8
frontend/app/shared/state/workflows.state.ts

@ -54,12 +54,12 @@ export class WorkflowsState extends State<Snapshot> {
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
private readonly workflowsService: WorkflowsService private readonly workflowsService: WorkflowsService
) { ) {
super({ errors: [], workflows: [], version: Version.EMPTY }); super({ errors: [], workflows: [], version: Version.EMPTY }, 'Workflows');
} }
public load(isReload = false): Observable<any> { public load(isReload = false): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState('Loading Initial');
} }
return this.loadInternal(isReload); return this.loadInternal(isReload);
@ -77,7 +77,7 @@ export class WorkflowsState extends State<Snapshot> {
this.replaceWorkflows(payload, version); this.replaceWorkflows(payload, version);
}), }),
finalize(() => { finalize(() => {
this.next({ isLoading: false }); this.next({ isLoading: false }, 'Loading Done');
}), }),
shareSubscribed(this.dialogs)); shareSubscribed(this.dialogs));
} }
@ -118,7 +118,7 @@ export class WorkflowsState extends State<Snapshot> {
isLoading: false, isLoading: false,
version, version,
workflows workflows
}); }, 'Loading Success / Updated');
} }
private get appName() { private get appName() {

5
frontend/app/shell/pages/internal/profile-menu.component.ts

@ -63,12 +63,11 @@ export class ProfileMenuComponent extends StatefulComponent<State> implements On
const profileEmail = user.email; const profileEmail = user.email;
const profileDisplayName = user.displayName; const profileDisplayName = user.displayName;
this.next(s => ({ this.next({
...s,
profileId, profileId,
profileEmail, profileEmail,
profileDisplayName profileDisplayName
})); });
} }
})); }));
} }

Loading…
Cancel
Save