0">
|
diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts
index 645e3c8ee..810746d2f 100644
--- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts
+++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts
@@ -8,13 +8,10 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
-import {
- DialogService,
- ImmutableArray,
- ModalView
-} from '@app/shared';
+import { ImmutableArray, ModalView } from '@app/shared';
-import { EventConsumerDto, EventConsumersService } from './../../services/event-consumers.service';
+import { EventConsumerDto } from './../../services/event-consumers.service';
+import { EventConsumersState } from '@appfeatures/administration/declarations';
@Component({
selector: 'sqx-event-consumers-page',
@@ -22,87 +19,52 @@ import { EventConsumerDto, EventConsumersService } from './../../services/event-
templateUrl: './event-consumers-page.component.html'
})
export class EventConsumersPageComponent implements OnDestroy, OnInit {
- private subscription: Subscription;
+ private timerSubscription: Subscription;
public eventConsumerErrorDialog = new ModalView();
public eventConsumerError = '';
public eventConsumers = ImmutableArray.empty();
constructor(
- private readonly dialogs: DialogService,
- private readonly eventConsumersService: EventConsumersService
+ public readonly eventConsumersState: EventConsumersState
) {
}
public ngOnDestroy() {
- this.subscription.unsubscribe();
+ this.timerSubscription.unsubscribe();
}
public ngOnInit() {
- this.load(false, true);
+ this.eventConsumersState.load(false, true).onErrorResumeNext().subscribe();
- this.subscription =
- Observable.timer(4000, 4000).subscribe(() => {
- this.load();
- });
+ this.timerSubscription =
+ Observable.timer(2000, 2000)
+ .switchMap(x => this.eventConsumersState.load().onErrorResumeNext())
+ .subscribe();
}
- public load(showInfo = false, showError = false) {
- this.eventConsumersService.getEventConsumers()
- .subscribe(dtos => {
- this.eventConsumers = ImmutableArray.of(dtos);
+ public reload() {
+ this.eventConsumersState.load(true, true).onErrorResumeNext().subscribe();
+ }
- if (showInfo) {
- this.dialogs.notifyInfo('Event Consumers reloaded.');
- }
- }, error => {
- if (showError) {
- this.dialogs.notifyError(error);
- }
- });
+ public start(es: EventConsumerDto) {
+ this.eventConsumersState.start(es).onErrorResumeNext().subscribe();
}
- public start(consumer: EventConsumerDto) {
- this.eventConsumersService.startEventConsumer(consumer.name)
- .subscribe(() => {
- this.eventConsumers = this.eventConsumers.replaceBy('name', start(consumer));
- }, error => {
- this.dialogs.notifyError(error);
- });
+ public stop(es: EventConsumerDto) {
+ this.eventConsumersState.stop(es).onErrorResumeNext().subscribe();
}
- public stop(consumer: EventConsumerDto) {
- this.eventConsumersService.stopEventConsumer(consumer.name)
- .subscribe(() => {
- this.eventConsumers = this.eventConsumers.replaceBy('name', stop(consumer));
- }, error => {
- this.dialogs.notifyError(error);
- });
+ public reset(es: EventConsumerDto) {
+ this.eventConsumersState.reset(es).onErrorResumeNext().subscribe();
}
- public reset(consumer: EventConsumerDto) {
- this.eventConsumersService.resetEventConsumer(consumer.name)
- .subscribe(() => {
- this.eventConsumers = this.eventConsumers.replaceBy('name', reset(consumer));
- }, error => {
- this.dialogs.notifyError(error);
- });
+ public trackByEventConsumer(index: number, es: EventConsumerDto) {
+ return es.name;
}
public showError(eventConsumer: EventConsumerDto) {
this.eventConsumerError = eventConsumer.error;
this.eventConsumerErrorDialog.show();
}
-}
-
-function start(es: EventConsumerDto) {
- return new EventConsumerDto(es.name, false, false, es.error, es.position);
-}
-
-function stop(es: EventConsumerDto) {
- return new EventConsumerDto(es.name, true, false, es.error, es.position);
-}
-
-function reset(es: EventConsumerDto) {
- return new EventConsumerDto(es.name, es.isStopped, true, es.error, es.position);
}
\ No newline at end of file
diff --git a/src/Squidex/app/features/administration/pages/users/users-page.component.html b/src/Squidex/app/features/administration/pages/users/users-page.component.html
index 51b3dcab3..a5a65aa75 100644
--- a/src/Squidex/app/features/administration/pages/users/users-page.component.html
+++ b/src/Squidex/app/features/administration/pages/users/users-page.component.html
@@ -62,10 +62,10 @@
|
-
diff --git a/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts b/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts
index 947619278..e870f1d24 100644
--- a/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts
+++ b/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts
@@ -69,7 +69,7 @@ describe('EventConsumersService', () => {
it('should make put request to start event consumer',
inject([EventConsumersService, HttpTestingController], (eventConsumersService: EventConsumersService, httpMock: HttpTestingController) => {
- eventConsumersService.startEventConsumer('event-consumer1').subscribe();
+ eventConsumersService.putStart('event-consumer1').subscribe();
const req = httpMock.expectOne('http://service/p/api/event-consumers/event-consumer1/start');
@@ -82,7 +82,7 @@ describe('EventConsumersService', () => {
it('should make put request to stop event consumer',
inject([EventConsumersService, HttpTestingController], (eventConsumersService: EventConsumersService, httpMock: HttpTestingController) => {
- eventConsumersService.stopEventConsumer('event-consumer1').subscribe();
+ eventConsumersService.putStop('event-consumer1').subscribe();
const req = httpMock.expectOne('http://service/p/api/event-consumers/event-consumer1/stop');
@@ -95,7 +95,7 @@ describe('EventConsumersService', () => {
it('should make put request to reset event consumer',
inject([EventConsumersService, HttpTestingController], (eventConsumersService: EventConsumersService, httpMock: HttpTestingController) => {
- eventConsumersService.resetEventConsumer('event-consumer1').subscribe();
+ eventConsumersService.putReset('event-consumer1').subscribe();
const req = httpMock.expectOne('http://service/p/api/event-consumers/event-consumer1/reset');
diff --git a/src/Squidex/app/features/administration/services/event-consumers.service.ts b/src/Squidex/app/features/administration/services/event-consumers.service.ts
index 71cc57b49..36f1dd234 100644
--- a/src/Squidex/app/features/administration/services/event-consumers.service.ts
+++ b/src/Squidex/app/features/administration/services/event-consumers.service.ts
@@ -53,21 +53,21 @@ export class EventConsumersService {
.pretifyError('Failed to load event consumers. Please reload.');
}
- public startEventConsumer(name: string): Observable {
+ public putStart(name: string): Observable {
const url = this.apiUrl.buildUrl(`api/event-consumers/${name}/start`);
return HTTP.putVersioned(this.http, url, {})
.pretifyError('Failed to start event consumer. Please reload.');
}
- public stopEventConsumer(name: string): Observable {
+ public putStop(name: string): Observable {
const url = this.apiUrl.buildUrl(`api/event-consumers/${name}/stop`);
return HTTP.putVersioned(this.http, url, {})
.pretifyError('Failed to stop event consumer. Please reload.');
}
- public resetEventConsumer(name: string): Observable {
+ public putReset(name: string): Observable {
const url = this.apiUrl.buildUrl(`api/event-consumers/${name}/reset`);
return HTTP.putVersioned(this.http, url, {})
diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts
new file mode 100644
index 000000000..3a50062da
--- /dev/null
+++ b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts
@@ -0,0 +1,98 @@
+/*
+ * Squidex Headless CMS
+ *
+ * @license
+ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
+ */
+
+import { Observable } from 'rxjs';
+import { IMock, It, Mock, Times } from 'typemoq';
+
+import { DialogService } from '@app/shared';
+
+import { EventConsumerDto, EventConsumersService } from './../services/event-consumers.service';
+import { EventConsumersState } from './event-consumers.state';
+
+describe('EventConsumersState', () => {
+ const oldConsumers = [
+ new EventConsumerDto('name1', false, false, 'error', '1'),
+ new EventConsumerDto('name2', true, true, 'error', '2')
+ ];
+
+ let dialogs: IMock;
+ let eventConsumersService: IMock;
+ let eventConsumersState: EventConsumersState;
+
+ beforeEach(() => {
+ dialogs = Mock.ofType();
+
+ eventConsumersService = Mock.ofType();
+
+ eventConsumersService.setup(x => x.getEventConsumers())
+ .returns(() => Observable.of(oldConsumers));
+
+ eventConsumersState = new EventConsumersState(dialogs.object, eventConsumersService.object);
+ eventConsumersState.load().subscribe();
+ });
+
+ it('should load event consumers', () => {
+ expect(eventConsumersState.snapshot.eventConsumers.values).toEqual(oldConsumers);
+ });
+
+ it('should show notification on load when flag is true', () => {
+ eventConsumersState.load(true, true).subscribe();
+
+ dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once());
+ });
+
+ it('should show notification on load error when flag is true', () => {
+ eventConsumersService.setup(x => x.getEventConsumers())
+ .returns(() => Observable.throw({}));
+
+ eventConsumersState.load(true, true).onErrorResumeNext().subscribe();
+
+ dialogs.verify(x => x.notifyError(It.isAny()), Times.once());
+ });
+
+ it('should not show notification on load error when flag is false', () => {
+ eventConsumersService.setup(x => x.getEventConsumers())
+ .returns(() => Observable.throw({}));
+
+ eventConsumersState.load().onErrorResumeNext().subscribe();
+
+ dialogs.verify(x => x.notifyError(It.isAny()), Times.never());
+ });
+
+ it('should mark consumer as started', () => {
+ eventConsumersService.setup(x => x.putStart(oldConsumers[1].name))
+ .returns(() => Observable.of({}));
+
+ eventConsumersState.start(oldConsumers[1]).subscribe();
+
+ const es_1 = eventConsumersState.snapshot.eventConsumers.at(1);
+
+ expect(es_1.isStopped).toBeFalsy();
+ });
+
+ it('should mark consumer as stopped', () => {
+ eventConsumersService.setup(x => x.putStop(oldConsumers[0].name))
+ .returns(() => Observable.of({}));
+
+ eventConsumersState.stop(oldConsumers[0]).subscribe();
+
+ const es_1 = eventConsumersState.snapshot.eventConsumers.at(0);
+
+ expect(es_1.isStopped).toBeTruthy();
+ });
+
+ it('should mark consumer as resetting', () => {
+ eventConsumersService.setup(x => x.putReset(oldConsumers[0].name))
+ .returns(() => Observable.of({}));
+
+ eventConsumersState.reset(oldConsumers[0]).subscribe();
+
+ const es_1 = eventConsumersState.snapshot.eventConsumers.at(0);
+
+ expect(es_1.isResetting).toBeTruthy();
+ });
+});
\ No newline at end of file
diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.ts b/src/Squidex/app/features/administration/state/event-consumers.state.ts
new file mode 100644
index 000000000..e06d2a984
--- /dev/null
+++ b/src/Squidex/app/features/administration/state/event-consumers.state.ts
@@ -0,0 +1,99 @@
+/*
+ * Squidex Headless CMS
+ *
+ * @license
+ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
+ */
+
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+import '@app/framework/utils/rxjs-extensions';
+
+import {
+ DialogService,
+ ImmutableArray,
+ State
+} from '@app/shared';
+
+import { EventConsumerDto, EventConsumersService } from './../services/event-consumers.service';
+
+interface Snapshot {
+ eventConsumers: ImmutableArray;
+}
+
+@Injectable()
+export class EventConsumersState extends State {
+ public eventConsumers =
+ this.changes.map(x => x.eventConsumers);
+
+ constructor(
+ private readonly dialogs: DialogService,
+ private readonly eventConsumersService: EventConsumersService
+ ) {
+ super({ eventConsumers: ImmutableArray.empty() });
+ }
+
+ public load(notifyLoad = false, notifyError = false): Observable {
+ return this.eventConsumersService.getEventConsumers()
+ .do(dtos => {
+ if (notifyLoad) {
+ this.dialogs.notifyInfo('Event consumers reloaded.');
+ }
+
+ this.next(s => {
+ const eventConsumers = ImmutableArray.of(dtos);
+
+ return { ...s, eventConsumers };
+ });
+ })
+ .catch(error => {
+ if (notifyError) {
+ this.dialogs.notifyError(error);
+ }
+
+ return Observable.throw(error);
+ });
+ }
+
+ public start(es: EventConsumerDto): Observable {
+ return this.eventConsumersService.putStart(es.name)
+ .do(() => {
+ this.replaceEventConsumer(start(es));
+ })
+ .notify(this.dialogs);
+ }
+
+ public stop(es: EventConsumerDto): Observable {
+ return this.eventConsumersService.putStop(es.name)
+ .do(() => {
+ this.replaceEventConsumer(stop(es));
+ })
+ .notify(this.dialogs);
+ }
+
+ public reset(es: EventConsumerDto): Observable {
+ return this.eventConsumersService.putReset(es.name)
+ .do(() => {
+ this.replaceEventConsumer(reset(es));
+ })
+ .notify(this.dialogs);
+ }
+
+ private replaceEventConsumer(es: EventConsumerDto) {
+ this.next(s => {
+ const eventConsumers = s.eventConsumers.replaceBy('name', es);
+
+ return { ...s, eventConsumers };
+ });
+ }
+}
+
+const start = (es: EventConsumerDto) =>
+ new EventConsumerDto(es.name, false, false, es.error, es.position);
+
+const stop = (es: EventConsumerDto) =>
+ new EventConsumerDto(es.name, true, false, es.error, es.position);
+
+const reset = (es: EventConsumerDto) =>
+ new EventConsumerDto(es.name, es.isStopped, true, es.error, es.position);
\ No newline at end of file
diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts
index 70c8c3000..811f068cb 100644
--- a/src/Squidex/app/features/administration/state/users.state.spec.ts
+++ b/src/Squidex/app/features/administration/state/users.state.spec.ts
@@ -57,7 +57,7 @@ describe('UsersState', () => {
usersService.verifyAll();
});
- it('should raise notification on load when notify is true', () => {
+ it('should show notification on load when flag is true', () => {
usersState.load(true).subscribe();
dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once());
@@ -79,18 +79,7 @@ describe('UsersState', () => {
expect(usersState.snapshot.selectedUser).toEqual(u(newUsers[0]));
});
- it('should mark as current user when selected user equals to profile', () => {
- let selectedUser: UserDto;
-
- usersState.select('id2').subscribe(x => {
- selectedUser = x!;
- });
-
- expect(selectedUser!).toEqual(oldUsers[1]);
- expect(usersState.snapshot.selectedUser).toEqual(u(oldUsers[1]));
- });
-
- it('should not load user when already loaded', () => {
+ it('should not load user on select when already loaded', () => {
let selectedUser: UserDto;
usersState.select('id1').subscribe(x => {
@@ -103,7 +92,7 @@ describe('UsersState', () => {
usersService.verify(x => x.getUser(It.isAnyString()), Times.never());
});
- it('should load user when not loaded', () => {
+ it('should load user on select when not loaded', () => {
usersService.setup(x => x.getUser('id3'))
.returns(() => Observable.of(newUser));
@@ -119,7 +108,7 @@ describe('UsersState', () => {
usersService.verify(x => x.getUser('id3'), Times.once());
});
- it('should return null when unselecting user', () => {
+ it('should return null on select when unselecting user', () => {
let selectedUser: UserDto;
usersState.select(null).subscribe(x => {
@@ -132,7 +121,7 @@ describe('UsersState', () => {
usersService.verify(x => x.getUser(It.isAnyString()), Times.never());
});
- it('should return null when user to select is not found', () => {
+ it('should return null on select when user is not found', () => {
usersService.setup(x => x.getUser('unknown'))
.returns(() => Observable.throw({}));
diff --git a/src/Squidex/app/features/administration/state/users.state.ts b/src/Squidex/app/features/administration/state/users.state.ts
index edab26a4c..a58fdc912 100644
--- a/src/Squidex/app/features/administration/state/users.state.ts
+++ b/src/Squidex/app/features/administration/state/users.state.ts
@@ -127,10 +127,10 @@ export class UsersState extends State {
});
}
- public load(notify = false): Observable {
+ public load(notifyLoad = false): Observable {
return this.usersService.getUsers(this.snapshot.usersPager.pageSize, this.snapshot.usersPager.skip, this.snapshot.usersQuery)
.do(dtos => {
- if (notify) {
+ if (notifyLoad) {
this.dialogs.notifyInfo('Users reloaded.');
}
diff --git a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html
index ba5aa2a6e..623630b8a 100644
--- a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html
+++ b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.html
@@ -1,134 +1,136 @@
-
+
+
-
-
-
-
- Hi {{ctx.user.displayName}}
+ |