Browse Source

More refactorings.

pull/356/head
Sebastian Stehle 8 years ago
parent
commit
57eaab592a
  1. 32
      src/Squidex/app/features/administration/state/event-consumers.state.spec.ts
  2. 8
      src/Squidex/app/features/administration/state/event-consumers.state.ts
  3. 58
      src/Squidex/app/features/administration/state/users.state.spec.ts
  4. 10
      src/Squidex/app/features/administration/state/users.state.ts
  5. 64
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  6. 7
      src/Squidex/app/features/settings/pages/clients/clients-page.component.ts
  7. 12
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts
  8. 2
      src/Squidex/app/framework/angular/forms/forms-helper.ts
  9. 8
      src/Squidex/app/framework/state.ts
  10. 2
      src/Squidex/app/framework/utils/version.spec.ts
  11. 2
      src/Squidex/app/shared/interceptors/auth.interceptor.ts
  12. 2
      src/Squidex/app/shared/services/help.service.ts
  13. 4
      src/Squidex/app/shared/services/ui.service.ts
  14. 2
      src/Squidex/app/shared/state/assets.state.spec.ts
  15. 12
      src/Squidex/app/shared/state/clients.state.spec.ts
  16. 100
      src/Squidex/app/shared/state/clients.state.ts
  17. 22
      src/Squidex/app/shared/state/comments.state.spec.ts
  18. 124
      src/Squidex/app/shared/state/comments.state.ts
  19. 14
      src/Squidex/app/shared/state/contributors.state.spec.ts
  20. 85
      src/Squidex/app/shared/state/contributors.state.ts
  21. 6
      src/Squidex/app/shared/state/languages.state.spec.ts
  22. 6
      src/Squidex/app/shared/state/patterns.state.spec.ts
  23. 5
      src/Squidex/app/shared/state/plans.state.spec.ts
  24. 6
      src/Squidex/app/shared/state/roles.state.spec.ts
  25. 10
      src/Squidex/app/shared/state/rules.state.spec.ts
  26. 54
      src/Squidex/app/shared/state/schemas.state.spec.ts

32
src/Squidex/app/features/administration/state/event-consumers.state.spec.ts

@ -6,6 +6,7 @@
*/ */
import { of, throwError } from 'rxjs'; import { of, throwError } from 'rxjs';
import { onErrorResumeNext } from 'rxjs/operators';
import { IMock, It, Mock, Times } from 'typemoq'; import { IMock, It, Mock, Times } from 'typemoq';
import { DialogService } from '@app/shared'; import { DialogService } from '@app/shared';
@ -15,8 +16,8 @@ import { EventConsumersState } from './event-consumers.state';
describe('EventConsumersState', () => { describe('EventConsumersState', () => {
const oldConsumers = [ const oldConsumers = [
new EventConsumerDto('name1', false), new EventConsumerDto('name1', false, false, 'error', '1'),
new EventConsumerDto('name2', true) new EventConsumerDto('name2', true, true, 'error', '2')
]; ];
let dialogs: IMock<DialogService>; let dialogs: IMock<DialogService>;
@ -29,12 +30,16 @@ describe('EventConsumersState', () => {
eventConsumersService = Mock.ofType<EventConsumersService>(); eventConsumersService = Mock.ofType<EventConsumersService>();
eventConsumersService.setup(x => x.getEventConsumers()) eventConsumersService.setup(x => x.getEventConsumers())
.returns(() => of(oldConsumers)); .returns(() => of(oldConsumers)).verifiable(Times.atLeastOnce());
eventConsumersState = new EventConsumersState(dialogs.object, eventConsumersService.object); eventConsumersState = new EventConsumersState(dialogs.object, eventConsumersService.object);
eventConsumersState.load().subscribe(); eventConsumersState.load().subscribe();
}); });
afterEach(() => {
eventConsumersService.verifyAll();
});
it('should load event consumers', () => { it('should load event consumers', () => {
expect(eventConsumersState.snapshot.eventConsumers.values).toEqual(oldConsumers); expect(eventConsumersState.snapshot.eventConsumers.values).toEqual(oldConsumers);
expect(eventConsumersState.snapshot.isLoaded).toBeTruthy(); expect(eventConsumersState.snapshot.isLoaded).toBeTruthy();
@ -45,7 +50,10 @@ describe('EventConsumersState', () => {
}); });
it('should show notification on load when reload is true', () => { it('should show notification on load when reload is true', () => {
eventConsumersState.load(true); eventConsumersService.setup(x => x.getEventConsumers())
.returns(() => of(oldConsumers));
eventConsumersState.load(true).subscribe();
expect().nothing(); expect().nothing();
@ -56,7 +64,7 @@ describe('EventConsumersState', () => {
eventConsumersService.setup(x => x.getEventConsumers()) eventConsumersService.setup(x => x.getEventConsumers())
.returns(() => throwError({})); .returns(() => throwError({}));
eventConsumersState.load(true, false); eventConsumersState.load(true, false).pipe(onErrorResumeNext()).subscribe();
expect().nothing(); expect().nothing();
@ -67,7 +75,7 @@ describe('EventConsumersState', () => {
eventConsumersService.setup(x => x.getEventConsumers()) eventConsumersService.setup(x => x.getEventConsumers())
.returns(() => throwError({})); .returns(() => throwError({}));
eventConsumersState.load(true, true); eventConsumersState.load(true, true).pipe(onErrorResumeNext()).subscribe();
expect().nothing(); expect().nothing();
@ -76,9 +84,9 @@ describe('EventConsumersState', () => {
it('should unmark as stopped when started', () => { it('should unmark as stopped when started', () => {
eventConsumersService.setup(x => x.putStart(oldConsumers[1].name)) eventConsumersService.setup(x => x.putStart(oldConsumers[1].name))
.returns(() => of({})); .returns(() => of({})).verifiable();
eventConsumersState.start(oldConsumers[1]); eventConsumersState.start(oldConsumers[1]).subscribe();
const es_1 = eventConsumersState.snapshot.eventConsumers.at(1); const es_1 = eventConsumersState.snapshot.eventConsumers.at(1);
@ -87,9 +95,9 @@ describe('EventConsumersState', () => {
it('should mark as stopped when stopped', () => { it('should mark as stopped when stopped', () => {
eventConsumersService.setup(x => x.putStop(oldConsumers[0].name)) eventConsumersService.setup(x => x.putStop(oldConsumers[0].name))
.returns(() => of({})); .returns(() => of({})).verifiable();
eventConsumersState.stop(oldConsumers[0]); eventConsumersState.stop(oldConsumers[0]).subscribe();
const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); const es_1 = eventConsumersState.snapshot.eventConsumers.at(0);
@ -98,9 +106,9 @@ describe('EventConsumersState', () => {
it('should mark as resetting when reset', () => { it('should mark as resetting when reset', () => {
eventConsumersService.setup(x => x.putReset(oldConsumers[0].name)) eventConsumersService.setup(x => x.putReset(oldConsumers[0].name))
.returns(() => of({})); .returns(() => of({})).verifiable();
eventConsumersState.reset(oldConsumers[0]); eventConsumersState.reset(oldConsumers[0]).subscribe();
const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); const es_1 = eventConsumersState.snapshot.eventConsumers.at(0);

8
src/Squidex/app/features/administration/state/event-consumers.state.ts

@ -45,7 +45,7 @@ export class EventConsumersState extends State<Snapshot> {
super({ eventConsumers: ImmutableArray.empty() }); super({ eventConsumers: ImmutableArray.empty() });
} }
public load(isReload = false, silent = false): Observable<EventConsumersList> { public load(isReload = false, silent = false): Observable<any> {
if (!isReload) { if (!isReload) {
this.resetState(); this.resetState();
} }
@ -75,7 +75,7 @@ export class EventConsumersState extends State<Snapshot> {
public start(eventConsumer: EventConsumerDto): Observable<any> { public start(eventConsumer: EventConsumerDto): Observable<any> {
const stream = const stream =
this.eventConsumersService.putStart(eventConsumer.name).pipe( this.eventConsumersService.putStart(eventConsumer.name).pipe(
map(_ => setStopped(eventConsumer, false), share())); map(() => setStopped(eventConsumer, false), share()));
this.updateState(stream); this.updateState(stream);
@ -85,7 +85,7 @@ export class EventConsumersState extends State<Snapshot> {
public stop(eventConsumer: EventConsumerDto): Observable<EventConsumerDto> { public stop(eventConsumer: EventConsumerDto): Observable<EventConsumerDto> {
const stream = const stream =
this.eventConsumersService.putStop(eventConsumer.name).pipe( this.eventConsumersService.putStop(eventConsumer.name).pipe(
map(_ => setStopped(eventConsumer, true), share())); map(() => setStopped(eventConsumer, true), share()));
this.updateState(stream); this.updateState(stream);
@ -95,7 +95,7 @@ export class EventConsumersState extends State<Snapshot> {
public reset(eventConsumer: EventConsumerDto): Observable<any> { public reset(eventConsumer: EventConsumerDto): Observable<any> {
const stream = const stream =
this.eventConsumersService.putReset(eventConsumer.name).pipe( this.eventConsumersService.putReset(eventConsumer.name).pipe(
map(_ => reset(eventConsumer), share())); map(() => reset(eventConsumer), share()));
this.updateState(stream); this.updateState(stream);

58
src/Squidex/app/features/administration/state/users.state.spec.ts

@ -42,10 +42,14 @@ describe('UsersState', () => {
usersService = Mock.ofType<UsersService>(); usersService = Mock.ofType<UsersService>();
usersService.setup(x => x.getUsers(10, 0, undefined)) usersService.setup(x => x.getUsers(10, 0, undefined))
.returns(() => of(new UsersDto(200, oldUsers))); .returns(() => of(new UsersDto(200, oldUsers))).verifiable(Times.atLeastOnce());
usersState = new UsersState(authService.object, dialogs.object, usersService.object); usersState = new UsersState(authService.object, dialogs.object, usersService.object);
usersState.load(); usersState.load().subscribe();
});
afterEach(() => {
usersService.verifyAll();
}); });
it('should load users', () => { it('should load users', () => {
@ -60,7 +64,7 @@ describe('UsersState', () => {
}); });
it('should show notification on load when reload is true', () => { it('should show notification on load when reload is true', () => {
usersState.load(true); usersState.load(true).subscribe();
expect().nothing(); expect().nothing();
@ -68,7 +72,7 @@ describe('UsersState', () => {
}); });
it('should replace selected user when reloading', () => { it('should replace selected user when reloading', () => {
usersState.select('id1'); usersState.select('id1').subscribe();
const newUsers = [ const newUsers = [
new UserDto('id1', 'mail1@mail.de_new', 'name1_new', ['Permission1_New'], false), new UserDto('id1', 'mail1@mail.de_new', 'name1_new', ['Permission1_New'], false),
@ -78,7 +82,7 @@ describe('UsersState', () => {
usersService.setup(x => x.getUsers(10, 0, undefined)) usersService.setup(x => x.getUsers(10, 0, undefined))
.returns(() => of(new UsersDto(200, newUsers))); .returns(() => of(new UsersDto(200, newUsers)));
usersState.load(); usersState.load().subscribe();
expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUsers[0] }); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUsers[0] });
}); });
@ -92,8 +96,6 @@ describe('UsersState', () => {
expect(selectedUser!.user).toEqual(oldUsers[0]); expect(selectedUser!.user).toEqual(oldUsers[0]);
expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: oldUsers[0] }); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: oldUsers[0] });
usersService.verify(x => x.getUser(It.isAnyString()), Times.never());
}); });
it('should return user on select and load when not loaded', () => { it('should return user on select and load when not loaded', () => {
@ -108,8 +110,6 @@ describe('UsersState', () => {
expect(selectedUser!.user).toEqual(newUser); expect(selectedUser!.user).toEqual(newUser);
expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUser }); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUser });
usersService.verify(x => x.getUser('id3'), Times.once());
}); });
it('should return null on select when unselecting user', () => { it('should return null on select when unselecting user', () => {
@ -121,19 +121,17 @@ describe('UsersState', () => {
expect(selectedUser!).toBeNull(); expect(selectedUser!).toBeNull();
expect(usersState.snapshot.selectedUser).toBeNull(); expect(usersState.snapshot.selectedUser).toBeNull();
usersService.verify(x => x.getUser(It.isAnyString()), Times.never());
}); });
it('should return null on select when user is not found', () => { it('should return null on select when user is not found', () => {
usersService.setup(x => x.getUser('unknown')) usersService.setup(x => x.getUser('unknown'))
.returns(() => throwError({})); .returns(() => throwError({})).verifiable();
let selectedUser: SnapshotUser; let selectedUser: SnapshotUser;
usersState.select('unknown').subscribe(x => { usersState.select('unknown').subscribe(x => {
selectedUser = x!; selectedUser = x!;
}); }).unsubscribe();
expect(selectedUser!).toBeNull(); expect(selectedUser!).toBeNull();
expect(usersState.snapshot.selectedUser).toBeNull(); expect(usersState.snapshot.selectedUser).toBeNull();
@ -141,10 +139,10 @@ describe('UsersState', () => {
it('should mark as locked when locked', () => { it('should mark as locked when locked', () => {
usersService.setup(x => x.lockUser('id1')) usersService.setup(x => x.lockUser('id1'))
.returns(() => of({})); .returns(() => of({})).verifiable();
usersState.select('id1'); usersState.select('id1').subscribe();
usersState.lock(oldUsers[0]); usersState.lock(oldUsers[0]).subscribe();
const user_1 = usersState.snapshot.users.at(0); const user_1 = usersState.snapshot.users.at(0);
@ -154,10 +152,10 @@ describe('UsersState', () => {
it('should unmark as locked when unlocked', () => { it('should unmark as locked when unlocked', () => {
usersService.setup(x => x.unlockUser('id2')) usersService.setup(x => x.unlockUser('id2'))
.returns(() => of({})); .returns(() => of({})).verifiable();
usersState.select('id2'); usersState.select('id2').subscribe();
usersState.unlock(oldUsers[1]); usersState.unlock(oldUsers[1]).subscribe();
const user_1 = usersState.snapshot.users.at(1); const user_1 = usersState.snapshot.users.at(1);
@ -169,10 +167,10 @@ describe('UsersState', () => {
const request = { email: 'new@mail.com', displayName: 'New', permissions: ['Permission1'] }; const request = { email: 'new@mail.com', displayName: 'New', permissions: ['Permission1'] };
usersService.setup(x => x.putUser('id1', request)) usersService.setup(x => x.putUser('id1', request))
.returns(() => of({})); .returns(() => of({})).verifiable();
usersState.select('id1'); usersState.select('id1').subscribe();
usersState.update(oldUsers[0], request); usersState.update(oldUsers[0], request).subscribe();
const user_1 = usersState.snapshot.users.at(0); const user_1 = usersState.snapshot.users.at(0);
@ -186,9 +184,9 @@ describe('UsersState', () => {
const request = { ...newUser, password: 'password' }; const request = { ...newUser, password: 'password' };
usersService.setup(x => x.postUser(request)) usersService.setup(x => x.postUser(request))
.returns(() => of(newUser)); .returns(() => of(newUser)).verifiable();
usersState.create(request); usersState.create(request).subscribe();
expect(usersState.snapshot.users.values).toEqual([ expect(usersState.snapshot.users.values).toEqual([
{ isCurrentUser: false, user: newUser }, { isCurrentUser: false, user: newUser },
@ -200,10 +198,10 @@ describe('UsersState', () => {
it('should load next page and prev page when paging', () => { it('should load next page and prev page when paging', () => {
usersService.setup(x => x.getUsers(10, 10, undefined)) usersService.setup(x => x.getUsers(10, 10, undefined))
.returns(() => of(new UsersDto(200, []))); .returns(() => of(new UsersDto(200, []))).verifiable();
usersState.goNext(); usersState.goNext().subscribe();
usersState.goPrev(); usersState.goPrev().subscribe();
expect().nothing(); expect().nothing();
@ -213,12 +211,10 @@ describe('UsersState', () => {
it('should load with query when searching', () => { it('should load with query when searching', () => {
usersService.setup(x => x.getUsers(10, 0, 'my-query')) usersService.setup(x => x.getUsers(10, 0, 'my-query'))
.returns(() => of(new UsersDto(0, []))); .returns(() => of(new UsersDto(0, []))).verifiable();
usersState.search('my-query'); usersState.search('my-query').subscribe();
expect(usersState.snapshot.usersQuery).toEqual('my-query'); expect(usersState.snapshot.usersQuery).toEqual('my-query');
usersService.verify(x => x.getUsers(10, 0, 'my-query'), Times.once());
}); });
}); });

10
src/Squidex/app/features/administration/state/users.state.ts

@ -7,7 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { catchError, distinctUntilChanged, map, share, switchMap } from 'rxjs/operators'; import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators';
import '@app/framework/utils/rxjs-extensions'; import '@app/framework/utils/rxjs-extensions';
@ -113,7 +113,7 @@ export class UsersState extends State<Snapshot> {
return this.loadInternal(isReload); return this.loadInternal(isReload);
} }
private loadInternal(isReload = false): Observable<UsersResult> { private loadInternal(isReload = false): Observable<any> {
const stream = const stream =
this.usersService.getUsers( this.usersService.getUsers(
this.snapshot.usersPager.pageSize, this.snapshot.usersPager.pageSize,
@ -163,7 +163,7 @@ export class UsersState extends State<Snapshot> {
public update(user: UserDto, request: UpdateUserDto): Observable<UserDto> { public update(user: UserDto, request: UpdateUserDto): Observable<UserDto> {
const stream = const stream =
this.usersService.putUser(user.id, request).pipe( this.usersService.putUser(user.id, request).pipe(
map(_ => update(user, request)), share()); map(() => update(user, request)), share());
this.updateState(stream, false); this.updateState(stream, false);
@ -173,7 +173,7 @@ export class UsersState extends State<Snapshot> {
public lock(user: UserDto): Observable<UserDto> { public lock(user: UserDto): Observable<UserDto> {
const stream = const stream =
this.usersService.lockUser(user.id).pipe( this.usersService.lockUser(user.id).pipe(
map(_ => setLocked(user, true)), share()); map(() => setLocked(user, true)), share());
this.updateState(stream, true); this.updateState(stream, true);
@ -183,7 +183,7 @@ export class UsersState extends State<Snapshot> {
public unlock(user: UserDto): Observable<UserDto> { public unlock(user: UserDto): Observable<UserDto> {
const stream = const stream =
this.usersService.unlockUser(user.id).pipe( this.usersService.unlockUser(user.id).pipe(
map(_ => setLocked(user, false)), share()); map(() => setLocked(user, false)), share());
this.updateState(stream, true); this.updateState(stream, true);

64
src/Squidex/app/features/settings/pages/clients/client.component.ts

@ -7,7 +7,6 @@
import { Component, Input, OnChanges } from '@angular/core'; import { Component, Input, OnChanges } from '@angular/core';
import { FormBuilder } from '@angular/forms'; import { FormBuilder } from '@angular/forms';
import { onErrorResumeNext } from 'rxjs/operators';
import { import {
AccessTokenDto, AccessTokenDto,
@ -24,36 +23,6 @@ import {
const ESCAPE_KEY = 27; const ESCAPE_KEY = 27;
function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.buildUrl('identity-server/connect/token');
return `$ curl
-X POST '${url}'
-H 'Content-Type: application/x-www-form-urlencoded'
-d 'grant_type=client_credentials&
client_id=${app}:${client.id}&
client_secret=${client.secret}&
scope=squidex-api`;
}
function connectCLIWinText(app: string, client: { id: string, secret: string }) {
return `.\\sq.exe config add ${app} ${app}:${client.id} ${client.secret};.\\sq.exe config use ${app}`;
}
function connectCLINixText(app: string, client: { id: string, secret: string }) {
return `sq config add ${app} ${app}:${client.id} ${client.secret} && sq config use ${app}`;
}
function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.value;
return `var clientManager = new SquidexClientManager(
"${url}",
"${app}",
"${app}:${client.id}",
"${client.secret}")`;
}
@Component({ @Component({
selector: 'sqx-client', selector: 'sqx-client',
styleUrls: ['./client.component.scss'], styleUrls: ['./client.component.scss'],
@ -100,11 +69,11 @@ export class ClientComponent implements OnChanges {
} }
public revoke() { public revoke() {
this.clientsState.revoke(this.client).pipe(onErrorResumeNext()).subscribe(); this.clientsState.revoke(this.client);
} }
public update(role: string) { public update(role: string) {
this.clientsState.update(this.client, { role }).pipe(onErrorResumeNext()).subscribe(); this.clientsState.update(this.client, { role });
} }
public toggleRename() { public toggleRename() {
@ -144,3 +113,32 @@ export class ClientComponent implements OnChanges {
} }
} }
function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.buildUrl('identity-server/connect/token');
return `$ curl
-X POST '${url}'
-H 'Content-Type: application/x-www-form-urlencoded'
-d 'grant_type=client_credentials&
client_id=${app}:${client.id}&
client_secret=${client.secret}&
scope=squidex-api`;
}
function connectCLIWinText(app: string, client: { id: string, secret: string }) {
return `.\\sq.exe config add ${app} ${app}:${client.id} ${client.secret};.\\sq.exe config use ${app}`;
}
function connectCLINixText(app: string, client: { id: string, secret: string }) {
return `sq config add ${app} ${app}:${client.id} ${client.secret} && sq config use ${app}`;
}
function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.value;
return `var clientManager = new SquidexClientManager(
"${url}",
"${app}",
"${app}:${client.id}",
"${client.secret}")`;
}

7
src/Squidex/app/features/settings/pages/clients/clients-page.component.ts

@ -7,7 +7,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms'; import { FormBuilder } from '@angular/forms';
import { onErrorResumeNext } from 'rxjs/operators';
import { import {
AppsState, AppsState,
@ -34,13 +33,13 @@ export class ClientsPageComponent implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.rolesState.load().pipe(onErrorResumeNext()).subscribe(); this.rolesState.load();
this.clientsState.load().pipe(onErrorResumeNext()).subscribe(); this.clientsState.load();
} }
public reload() { public reload() {
this.clientsState.load(true).pipe(onErrorResumeNext()).subscribe(); this.clientsState.load(true);
} }
public attachClient() { public attachClient() {

12
src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts

@ -8,7 +8,7 @@
import { Component, Injectable, OnInit } from '@angular/core'; import { Component, Injectable, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms'; import { FormBuilder } from '@angular/forms';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { onErrorResumeNext, withLatestFrom } from 'rxjs/operators'; import { withLatestFrom } from 'rxjs/operators';
import { import {
AppsState, AppsState,
@ -68,21 +68,21 @@ export class ContributorsPageComponent implements OnInit {
} }
public ngOnInit() { public ngOnInit() {
this.rolesState.load().pipe(onErrorResumeNext()).subscribe(); this.rolesState.load();
this.contributorsState.load().pipe(onErrorResumeNext()).subscribe(); this.contributorsState.load();
} }
public reload() { public reload() {
this.contributorsState.load(true).pipe(onErrorResumeNext()).subscribe(); this.contributorsState.load(true);
} }
public remove(contributor: ContributorDto) { public remove(contributor: ContributorDto) {
this.contributorsState.revoke(contributor).pipe(onErrorResumeNext()).subscribe(); this.contributorsState.revoke(contributor);
} }
public changeRole(contributor: ContributorDto, role: string) { public changeRole(contributor: ContributorDto, role: string) {
this.contributorsState.assign({ contributorId: contributor.contributorId, role }).pipe(onErrorResumeNext()).subscribe(); this.contributorsState.assign({ contributorId: contributor.contributorId, role });
} }
public assignContributor() { public assignContributor() {

2
src/Squidex/app/framework/angular/forms/forms-helper.ts

@ -22,7 +22,7 @@ export function formControls(form: AbstractControl): AbstractControl[] {
} }
export function invalid$(form: AbstractControl): Observable<boolean> { export function invalid$(form: AbstractControl): Observable<boolean> {
return form.statusChanges.pipe(map(_ => form.invalid), startWith(form.invalid)); return form.statusChanges.pipe(map(() => form.invalid), startWith(form.invalid));
} }
export function value$<T = any>(form: AbstractControl): Observable<T> { export function value$<T = any>(form: AbstractControl): Observable<T> {

8
src/Squidex/app/framework/state.ts

@ -59,13 +59,13 @@ export class Form<T extends AbstractControl, V> {
} }
public load(value: V | undefined) { public load(value: V | undefined) {
this.state.next(_ => ({ submitted: false, error: null })); this.state.next(() => ({ submitted: false, error: null }));
this.setValue(value); this.setValue(value);
} }
public submit(): V | null { public submit(): V | null {
this.state.next(_ => ({ submitted: true })); this.state.next(() => ({ submitted: true }));
if (this.form.valid) { if (this.form.valid) {
const value = this.transformSubmit(fullValue(this.form)); const value = this.transformSubmit(fullValue(this.form));
@ -79,14 +79,14 @@ export class Form<T extends AbstractControl, V> {
} }
public submitCompleted(newValue?: V) { public submitCompleted(newValue?: V) {
this.state.next(_ => ({ submitted: false, error: null })); this.state.next(() => ({ submitted: false, error: null }));
this.enable(); this.enable();
this.setValue(newValue); this.setValue(newValue);
} }
public submitFailed(error?: string | ErrorDto) { public submitFailed(error?: string | ErrorDto) {
this.state.next(_ => ({ submitted: false, error: this.getError(error) })); this.state.next(() => ({ submitted: false, error: this.getError(error) }));
this.enable(); this.enable();
} }

2
src/Squidex/app/framework/utils/version.spec.ts

@ -24,7 +24,7 @@ describe('Version', () => {
describe('Versioned', () => { describe('Versioned', () => {
it('should initialize with version and payload', () => { it('should initialize with version and payload', () => {
const versioned = new Versioned<number>(new Version('1.0'), 123); const versioned = new Versioned(new Version('1.0'), 123);
expect(versioned.version.value).toBe('1.0'); expect(versioned.version.value).toBe('1.0');
expect(versioned.payload).toBe(123); expect(versioned.payload).toBe(123);

2
src/Squidex/app/shared/interceptors/auth.interceptor.ts

@ -50,7 +50,7 @@ export class AuthInterceptor implements HttpInterceptor {
catchError((error: HttpErrorResponse) => { catchError((error: HttpErrorResponse) => {
if (error.status === 401 && renew) { if (error.status === 401 && renew) {
return this.authService.loginSilent().pipe( return this.authService.loginSilent().pipe(
catchError(_ => { catchError(() => {
this.authService.logoutRedirect(); this.authService.logoutRedirect();
return empty(); return empty();

2
src/Squidex/app/shared/services/help.service.ts

@ -21,6 +21,6 @@ export class HelpService {
const url = `https://raw.githubusercontent.com/Squidex/squidex-docs/master/${helpPage}.md`; const url = `https://raw.githubusercontent.com/Squidex/squidex-docs/master/${helpPage}.md`;
return this.http.get(url, { responseType: 'text' }).pipe( return this.http.get(url, { responseType: 'text' }).pipe(
catchError(_ => of(''))); catchError(() => of('')));
} }
} }

4
src/Squidex/app/shared/services/ui.service.ts

@ -31,7 +31,7 @@ export class UIService {
const url = this.apiUrl.buildUrl(`api/ui/settings`); const url = this.apiUrl.buildUrl(`api/ui/settings`);
return this.http.get<UISettingsDto>(url).pipe( return this.http.get<UISettingsDto>(url).pipe(
catchError(_ => { catchError(() => {
return of({ mapType: 'OSM', mapKey: '', canCreateApps: true }); return of({ mapType: 'OSM', mapKey: '', canCreateApps: true });
})); }));
} }
@ -40,7 +40,7 @@ export class UIService {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/ui/settings`); const url = this.apiUrl.buildUrl(`api/apps/${appName}/ui/settings`);
return this.http.get<object>(url).pipe( return this.http.get<object>(url).pipe(
catchError(_ => { catchError(() => {
return of({ }); return of({ });
})); }));
} }

2
src/Squidex/app/shared/state/assets.state.spec.ts

@ -90,7 +90,7 @@ describe('AssetsState', () => {
it('should remove asset from snapshot when deleted', () => { it('should remove asset from snapshot when deleted', () => {
assetsService.setup(x => x.deleteAsset(app, oldAssets[0].id, version)) assetsService.setup(x => x.deleteAsset(app, oldAssets[0].id, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
assetsState.delete(oldAssets[0]).subscribe(); assetsState.delete(oldAssets[0]).subscribe();

12
src/Squidex/app/shared/state/clients.state.spec.ts

@ -42,12 +42,16 @@ describe('ClientsState', () => {
clientsService = Mock.ofType<ClientsService>(); clientsService = Mock.ofType<ClientsService>();
clientsService.setup(x => x.getClients(app)) clientsService.setup(x => x.getClients(app))
.returns(() => of(new ClientsDto(oldClients, version))); .returns(() => of(new ClientsDto(oldClients, version))).verifiable(Times.atLeastOnce());
clientsState = new ClientsState(clientsService.object, appsState.object, dialogs.object); clientsState = new ClientsState(clientsService.object, appsState.object, dialogs.object);
clientsState.load().subscribe(); clientsState.load().subscribe();
}); });
afterEach(() => {
clientsService.verifyAll();
});
it('should load clients', () => { it('should load clients', () => {
expect(clientsState.snapshot.clients.values).toEqual(oldClients); expect(clientsState.snapshot.clients.values).toEqual(oldClients);
expect(clientsState.snapshot.version).toEqual(version); expect(clientsState.snapshot.version).toEqual(version);
@ -70,7 +74,7 @@ describe('ClientsState', () => {
const request = { id: 'id3' }; const request = { id: 'id3' };
clientsService.setup(x => x.postClient(app, request, version)) clientsService.setup(x => x.postClient(app, request, version))
.returns(() => of(new Versioned<ClientDto>(newVersion, newClient))); .returns(() => of(new Versioned(newVersion, newClient))).verifiable();
clientsState.attach(request).subscribe(); clientsState.attach(request).subscribe();
@ -82,7 +86,7 @@ describe('ClientsState', () => {
const request = { name: 'NewName', role: 'NewRole' }; const request = { name: 'NewName', role: 'NewRole' };
clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version)) clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {}))).verifiable();
clientsState.update(oldClients[0], request).subscribe(); clientsState.update(oldClients[0], request).subscribe();
@ -95,7 +99,7 @@ describe('ClientsState', () => {
it('should remove client from snapshot when revoked', () => { it('should remove client from snapshot when revoked', () => {
clientsService.setup(x => x.deleteClient(app, oldClients[0].id, version)) clientsService.setup(x => x.deleteClient(app, oldClients[0].id, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {}))).verifiable();
clientsState.revoke(oldClients[0]).subscribe(); clientsState.revoke(oldClients[0]).subscribe();

100
src/Squidex/app/shared/state/clients.state.ts

@ -5,14 +5,16 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
// tslint:disable: no-shadowed-variable
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { distinctUntilChanged, map, share } from 'rxjs/operators';
import { import {
array,
DialogService, DialogService,
ImmutableArray, ImmutableArray,
notify,
State, State,
Version Version
} from '@app/framework'; } from '@app/framework';
@ -28,7 +30,7 @@ import {
interface Snapshot { interface Snapshot {
// The current clients. // The current clients.
clients: ImmutableArray<ClientDto>; clients: ClientsList;
// The app version. // The app version.
version: Version; version: Version;
@ -37,6 +39,8 @@ interface Snapshot {
isLoaded?: boolean; isLoaded?: boolean;
} }
type ClientsList = ImmutableArray<ClientDto>;
@Injectable() @Injectable()
export class ClientsState extends State<Snapshot> { export class ClientsState extends State<Snapshot> {
public clients = public clients =
@ -60,55 +64,69 @@ export class ClientsState extends State<Snapshot> {
this.resetState(); this.resetState();
} }
return this.clientsService.getClients(this.appName).pipe( const stream =
tap(dtos => { this.clientsService.getClients(this.appName).pipe(
if (isReload) { map(({ version, clients }) => ({ version, clients: array(clients) })), share());
this.dialogs.notifyInfo('Clients reloaded.');
} stream.subscribe(({ version, clients }) => {
if (isReload) {
this.dialogs.notifyInfo('Clients reloaded.');
}
this.next(s => { this.next(s => {
const clients = ImmutableArray.of(dtos.clients); return { ...s, clients, isLoaded: true, version };
});
});
return { ...s, clients, isLoaded: true, version: dtos.version }; return stream;
});
}),
notify(this.dialogs));
} }
public attach(request: CreateClientDto): Observable<any> { public attach(request: CreateClientDto): Observable<ClientDto> {
return this.clientsService.postClient(this.appName, request, this.version).pipe( const stream =
tap(dto => { this.clientsService.postClient(this.appName, request, this.version).pipe(
this.next(s => { share());
const clients = s.clients.push(dto.payload);
stream.subscribe(dto => {
this.next(s => {
const clients = s.clients.push(dto.payload);
return { ...s, clients, version: dto.version };
});
});
return { ...s, clients, version: dto.version }; return stream.pipe(map(x => x.payload));
});
}),
notify(this.dialogs));
} }
public revoke(client: ClientDto): Observable<any> { public revoke(client: ClientDto): Observable<any> {
return this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( const stream =
tap(dto => { this.clientsService.deleteClient(this.appName, client.id, this.version).pipe(
this.next(s => { share());
const clients = s.clients.filter(c => c.id !== client.id);
stream.subscribe(({ version }) => {
return { ...s, clients, version: dto.version }; this.next(s => {
}); const clients = s.clients.filter(c => c.id !== client.id);
}),
notify(this.dialogs)); return { ...s, clients, version };
});
});
return stream;
} }
public update(client: ClientDto, request: UpdateClientDto): Observable<any> { public update(client: ClientDto, request: UpdateClientDto): Observable<ClientDto> {
return this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( const stream =
tap(dto => { this.clientsService.putClient(this.appName, client.id, request, this.version).pipe(
this.next(s => { map(({ version }) => ({ version, client: update(client, request) })), share());
const clients = s.clients.replaceBy('id', update(client, request));
stream.subscribe(({ version, client }) => {
this.next(s => {
const clients = s.clients.replaceBy('id', client);
return { ...s, clients, version };
});
});
return { ...s, clients, version: dto.version }; return stream.pipe(map(x => x.client));
});
}),
notify(this.dialogs));
} }
private get appName() { private get appName() {

22
src/Squidex/app/shared/state/comments.state.spec.ts

@ -45,12 +45,16 @@ describe('CommentsState', () => {
commentsService = Mock.ofType<CommentsService>(); commentsService = Mock.ofType<CommentsService>();
commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) commentsService.setup(x => x.getComments(app, commentsId, new Version('-1')))
.returns(() => of(oldComments)); .returns(() => of(oldComments)).verifiable(Times.atLeastOnce());
commentsState = new CommentsState(appsState.object, commentsId, commentsService.object, dialogs.object); commentsState = new CommentsState(appsState.object, commentsId, commentsService.object, dialogs.object);
commentsState.load().subscribe(); commentsState.load().subscribe();
}); });
beforeEach(() => {
commentsService.verifyAll();
});
it('should load and merge comments', () => { it('should load and merge comments', () => {
const newComments = new CommentsDto([ const newComments = new CommentsDto([
new CommentDto('3', now, 'text3', creator) new CommentDto('3', now, 'text3', creator)
@ -59,7 +63,7 @@ describe('CommentsState', () => {
], ['1'], new Version('2')); ], ['1'], new Version('2'));
commentsService.setup(x => x.getComments(app, commentsId, new Version('1'))) commentsService.setup(x => x.getComments(app, commentsId, new Version('1')))
.returns(() => of(newComments)); .returns(() => of(newComments)).verifiable();
commentsState.load().subscribe(); commentsState.load().subscribe();
@ -78,7 +82,7 @@ describe('CommentsState', () => {
const request = { text: 'text3' }; const request = { text: 'text3' };
commentsService.setup(x => x.postComment(app, commentsId, request)) commentsService.setup(x => x.postComment(app, commentsId, request))
.returns(() => of(newComment)); .returns(() => of(newComment)).verifiable();
commentsState.create('text3').subscribe(); commentsState.create('text3').subscribe();
@ -93,28 +97,24 @@ describe('CommentsState', () => {
const request = { text: 'text2_2' }; const request = { text: 'text2_2' };
commentsService.setup(x => x.putComment(app, commentsId, '2', request)) commentsService.setup(x => x.putComment(app, commentsId, '2', request))
.returns(() => of({})); .returns(() => of({})).verifiable();
commentsState.update('2', 'text2_2', now).subscribe(); commentsState.update(oldComments.createdComments[1], 'text2_2', now).subscribe();
expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([
new CommentDto('1', now, 'text1', creator), new CommentDto('1', now, 'text1', creator),
new CommentDto('2', now, 'text2_2', creator) new CommentDto('2', now, 'text2_2', creator)
])); ]));
commentsService.verify(x => x.putComment(app, commentsId, '2', request), Times.once());
}); });
it('should remove comment from snapshot when deleted', () => { it('should remove comment from snapshot when deleted', () => {
commentsService.setup(x => x.deleteComment(app, commentsId, '2')) commentsService.setup(x => x.deleteComment(app, commentsId, '2'))
.returns(() => of({})); .returns(() => of({})).verifiable();
commentsState.delete('2').subscribe(); commentsState.delete(oldComments.createdComments[1]).subscribe();
expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([
new CommentDto('1', now, 'text1', creator) new CommentDto('1', now, 'text1', creator)
])); ]));
commentsService.verify(x => x.deleteComment(app, commentsId, '2'), Times.once());
}); });
}); });

124
src/Squidex/app/shared/state/comments.state.ts

@ -6,7 +6,7 @@
*/ */
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { distinctUntilChanged, map, share } from 'rxjs/operators';
import { import {
DateTime, DateTime,
@ -17,12 +17,12 @@ import {
Version Version
} from '@app/framework'; } from '@app/framework';
import { CommentDto, CommentsService } from './../services/comments.service'; import { CommentDto, CommentsDto, CommentsService } from './../services/comments.service';
import { AppsState } from './apps.state'; import { AppsState } from './apps.state';
interface Snapshot { interface Snapshot {
// The current comments. // The current comments.
comments: ImmutableArray<CommentDto>; comments: CommentsList;
// The version of the comments state. // The version of the comments state.
version: Version; version: Version;
@ -31,6 +31,8 @@ interface Snapshot {
isLoaded?: boolean; isLoaded?: boolean;
} }
type CommentsList = ImmutableArray<CommentDto>;
export class CommentsState extends State<Snapshot> { export class CommentsState extends State<Snapshot> {
public comments = public comments =
this.changes.pipe(map(x => x.comments), this.changes.pipe(map(x => x.comments),
@ -49,66 +51,90 @@ export class CommentsState extends State<Snapshot> {
super({ comments: ImmutableArray.empty(), version: new Version('-1') }); super({ comments: ImmutableArray.empty(), version: new Version('-1') });
} }
public load(): Observable<any> { public load(): Observable<CommentsDto> {
return this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe( const stream =
tap(dtos => { this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe(
this.next(s => { share());
let comments = s.comments;
for (let created of dtos.createdComments) { stream.subscribe(response => {
if (!comments.find(x => x.id === created.id)) { this.next(s => {
comments = comments.push(created); let comments = s.comments;
}
}
for (let updated of dtos.updatedComments) { for (let created of response.createdComments) {
comments = comments.replaceBy('id', updated); if (!comments.find(x => x.id === created.id)) {
comments = comments.push(created);
} }
}
for (let deleted of dtos.deletedComments) { for (let updated of response.updatedComments) {
comments = comments.filter(x => x.id !== deleted); comments = comments.replaceBy('id', updated);
} }
return { ...s, comments, isLoaded: true, version: dtos.version }; for (let deleted of response.deletedComments) {
}); comments = comments.filter(x => x.id !== deleted);
}), }
notify(this.dialogs));
return { ...s, comments, isLoaded: true, version: response.version };
});
}, error => {
this.dialogs.notifyError(error);
});
return stream;
} }
public create(text: string): Observable<any> { public create(text: string): Observable<CommentDto> {
return this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( const stream =
tap(dto => { this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe(
this.next(s => { share());
const comments = s.comments.push(dto);
stream.subscribe(comment => {
this.next(s => {
const comments = s.comments.push(comment);
return { ...s, comments }; return { ...s, comments };
}); });
}), }, error => {
notify(this.dialogs)); this.dialogs.notifyError(error);
});
return stream;
} }
public update(commentId: string, text: string, now?: DateTime): Observable<any> { public update(comment: CommentDto, text: string, now?: DateTime): Observable<CommentDto> {
return this.commentsService.putComment(this.appName, this.commentsId, commentId, { text }).pipe( const stream =
tap(() => { this.commentsService.putComment(this.appName, this.commentsId, comment.id, { text }).pipe(
this.next(s => { map(() => update(comment, text, now || DateTime.now())), share());
const comments = s.comments.map(c => c.id === commentId ? update(c, text, now || DateTime.now()) : c);
stream.subscribe(updated => {
this.next(s => {
const comments = s.comments.replaceBy('id', updated);
return { ...s, comments };
});
}, error => {
this.dialogs.notifyError(error);
});
return { ...s, comments }; return stream;
});
}),
notify(this.dialogs));
} }
public delete(commentId: string): Observable<any> { public delete(comment: CommentDto): Observable<any> {
return this.commentsService.deleteComment(this.appName, this.commentsId, commentId).pipe( const stream =
tap(() => { this.commentsService.deleteComment(this.appName, this.commentsId, comment.id).pipe(
this.next(s => { share());
const comments = s.comments.filter(c => c.id !== commentId);
stream.subscribe(() => {
this.next(s => {
const comments = s.comments.removeBy('id', comment);
return { ...s, comments };
});
}, error => {
this.dialogs.notifyError(error);
});
return { ...s, comments }; return stream;
});
}),
notify(this.dialogs));
} }
private get version() { private get version() {

14
src/Squidex/app/shared/state/contributors.state.spec.ts

@ -9,7 +9,6 @@ import { of } from 'rxjs';
import { IMock, It, Mock, Times } from 'typemoq'; import { IMock, It, Mock, Times } from 'typemoq';
import { import {
ContributorAssignedDto,
ContributorDto, ContributorDto,
ContributorsDto, ContributorsDto,
ContributorsService, ContributorsService,
@ -43,13 +42,18 @@ describe('ContributorsState', () => {
dialogs = Mock.ofType<DialogService>(); dialogs = Mock.ofType<DialogService>();
contributorsService = Mock.ofType<ContributorsService>(); contributorsService = Mock.ofType<ContributorsService>();
contributorsService.setup(x => x.getContributors(app)) contributorsService.setup(x => x.getContributors(app))
.returns(() => of(new ContributorsDto(oldContributors, 3, version))); .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(Times.atLeastOnce());
contributorsState = new ContributorsState(contributorsService.object, appsState.object, authService.object, dialogs.object); contributorsState = new ContributorsState(contributorsService.object, appsState.object, authService.object, dialogs.object);
contributorsState.load().subscribe(); contributorsState.load().subscribe();
}); });
afterEach(() => {
contributorsService.verifyAll();
});
it('should load contributors', () => { it('should load contributors', () => {
expect(contributorsState.snapshot.contributors.values).toEqual([ expect(contributorsState.snapshot.contributors.values).toEqual([
{ isCurrentUser: false, contributor: oldContributors[0] }, { isCurrentUser: false, contributor: oldContributors[0] },
@ -78,7 +82,7 @@ describe('ContributorsState', () => {
const response = { contributorId: newContributor.contributorId, isCreated: true }; const response = { contributorId: newContributor.contributorId, isCreated: true };
contributorsService.setup(x => x.postContributor(app, request, version)) contributorsService.setup(x => x.postContributor(app, request, version))
.returns(() => of(new Versioned<ContributorAssignedDto>(newVersion, response))); .returns(() => of(new Versioned(newVersion, response))).verifiable();
contributorsState.assign(request).subscribe(); contributorsState.assign(request).subscribe();
@ -99,7 +103,7 @@ describe('ContributorsState', () => {
const response = { contributorId: newContributor.contributorId, isCreated: true }; const response = { contributorId: newContributor.contributorId, isCreated: true };
contributorsService.setup(x => x.postContributor(app, request, version)) contributorsService.setup(x => x.postContributor(app, request, version))
.returns(() => of(new Versioned<ContributorAssignedDto>(newVersion, response))); .returns(() => of(new Versioned(newVersion, response))).verifiable();
contributorsState.assign(request).subscribe(); contributorsState.assign(request).subscribe();
@ -114,7 +118,7 @@ describe('ContributorsState', () => {
it('should remove contributor from snapshot when revoked', () => { it('should remove contributor from snapshot when revoked', () => {
contributorsService.setup(x => x.deleteContributor(app, oldContributors[0].contributorId, version)) contributorsService.setup(x => x.deleteContributor(app, oldContributors[0].contributorId, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {}))).verifiable();
contributorsState.revoke(oldContributors[0]).subscribe(); contributorsState.revoke(oldContributors[0]).subscribe();

85
src/Squidex/app/shared/state/contributors.state.ts

@ -7,13 +7,13 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs'; import { Observable, throwError } from 'rxjs';
import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators'; import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators';
import { import {
array,
DialogService, DialogService,
ErrorDto, ErrorDto,
ImmutableArray, ImmutableArray,
notify,
State, State,
Types, Types,
Version Version
@ -38,7 +38,7 @@ interface SnapshotContributor {
interface Snapshot { interface Snapshot {
// All loaded contributors. // All loaded contributors.
contributors: ImmutableArray<SnapshotContributor>; contributors: ContributorsList;
// Indicates if the maximum number of contributors are reached. // Indicates if the maximum number of contributors are reached.
isMaxReached?: boolean; isMaxReached?: boolean;
@ -53,6 +53,8 @@ interface Snapshot {
version: Version; version: Version;
} }
type ContributorsList = ImmutableArray<SnapshotContributor>;
@Injectable() @Injectable()
export class ContributorsState extends State<Snapshot> { export class ContributorsState extends State<Snapshot> {
public contributors = public contributors =
@ -85,49 +87,62 @@ export class ContributorsState extends State<Snapshot> {
this.resetState(); this.resetState();
} }
return this.contributorsService.getContributors(this.appName).pipe( const stream =
tap(dtos => { this.contributorsService.getContributors(this.appName).pipe(
if (isReload) { map(({ contributors, ...other }) => ({ ...other, contributors: array(contributors.map(x => this.createContributor(x))) })), share());
this.dialogs.notifyInfo('Contributors reloaded.');
} stream.subscribe(({ version, contributors, maxContributors }) => {
if (isReload) {
this.dialogs.notifyInfo('Contributors reloaded.');
}
const contributors = ImmutableArray.of(dtos.contributors.map(x => this.createContributor(x))); this.replaceContributors(contributors, version, maxContributors);
}, error => {
this.dialogs.notifyError(error);
});
this.replaceContributors(contributors, dtos.version, dtos.maxContributors); return stream;
}),
notify(this.dialogs));
} }
public revoke(contributor: ContributorDto): Observable<any> { public revoke(contributor: ContributorDto): Observable<any> {
return this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( const stream =
tap(dto => { this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe(share());
const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId);
stream.subscribe(({ version }) => {
const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId);
this.replaceContributors(contributors, dto.version); this.replaceContributors(contributors, version);
}), }, error => {
notify(this.dialogs)); this.dialogs.notifyError(error);
});
return stream;
} }
public assign(request: AssignContributorDto): Observable<boolean | undefined> { public assign(request: AssignContributorDto): Observable<boolean | undefined> {
return this.contributorsService.postContributor(this.appName, request, this.version).pipe( const stream =
map(dto => { this.contributorsService.postContributor(this.appName, request, this.version).pipe(
const contributors = this.updateContributors(dto.payload.contributorId, request.role, dto.version); catchError(error => {
if (Types.is(error, ErrorDto) && error.statusCode === 404) {
this.replaceContributors(contributors, dto.version); return throwError(new ErrorDto(404, 'The user does not exist.'));
} else {
return dto.payload.isCreated; return throwError(error);
}), }
catchError(error => { }),
if (Types.is(error, ErrorDto) && error.statusCode === 404) { share());
return throwError(new ErrorDto(404, 'The user does not exist.'));
} else { stream.subscribe(({ payload, version }) => {
return throwError(error); const contributors = this.updateContributors(payload.contributorId, request.role);
}
}), this.replaceContributors(contributors, version);
notify(this.dialogs)); }, error => {
this.dialogs.notifyError(error);
});
return stream.pipe(map(x => x.payload.isCreated));
} }
private updateContributors(id: string, role: string, version: Version) { private updateContributors(id: string, role: string) {
const contributor = new ContributorDto(id, role); const contributor = new ContributorDto(id, role);
const contributors = this.snapshot.contributors; const contributors = this.snapshot.contributors;

6
src/Squidex/app/shared/state/languages.state.spec.ts

@ -93,7 +93,7 @@ describe('LanguagesState', () => {
const newLanguage = new AppLanguageDto(languageIT.iso2Code, languageIT.englishName, false, false, []); const newLanguage = new AppLanguageDto(languageIT.iso2Code, languageIT.englishName, false, false, []);
languagesService.setup(x => x.postLanguage(app, It.isAny(), version)) languagesService.setup(x => x.postLanguage(app, It.isAny(), version))
.returns(() => of(new Versioned<AppLanguageDto>(newVersion, newLanguage))); .returns(() => of(new Versioned(newVersion, newLanguage)));
languagesState.add(languageIT).subscribe(); languagesState.add(languageIT).subscribe();
@ -120,7 +120,7 @@ describe('LanguagesState', () => {
const request = { isMaster: true, isOptional: false, fallback: [] }; const request = { isMaster: true, isOptional: false, fallback: [] };
languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
languagesState.update(oldLanguages[1], request).subscribe(); languagesState.update(oldLanguages[1], request).subscribe();
@ -144,7 +144,7 @@ describe('LanguagesState', () => {
it('should remove language from snapshot when deleted', () => { it('should remove language from snapshot when deleted', () => {
languagesService.setup(x => x.deleteLanguage(app, oldLanguages[1].iso2Code, version)) languagesService.setup(x => x.deleteLanguage(app, oldLanguages[1].iso2Code, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
languagesState.remove(oldLanguages[1]).subscribe(); languagesState.remove(oldLanguages[1]).subscribe();

6
src/Squidex/app/shared/state/patterns.state.spec.ts

@ -69,7 +69,7 @@ describe('PatternsState', () => {
const request = { ...newPattern }; const request = { ...newPattern };
patternsService.setup(x => x.postPattern(app, request, version)) patternsService.setup(x => x.postPattern(app, request, version))
.returns(() => of(new Versioned<PatternDto>(newVersion, newPattern))); .returns(() => of(new Versioned(newVersion, newPattern)));
patternsState.create(request).subscribe(); patternsState.create(request).subscribe();
@ -81,7 +81,7 @@ describe('PatternsState', () => {
const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' }; const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' };
patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
patternsState.update(oldPatterns[1], request).subscribe(); patternsState.update(oldPatterns[1], request).subscribe();
@ -95,7 +95,7 @@ describe('PatternsState', () => {
it('should remove pattern from snapshot when deleted', () => { it('should remove pattern from snapshot when deleted', () => {
patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version)) patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
patternsState.delete(oldPatterns[0]).subscribe(); patternsState.delete(oldPatterns[0]).subscribe();

5
src/Squidex/app/shared/state/plans.state.spec.ts

@ -11,7 +11,6 @@ import { IMock, It, Mock, Times } from 'typemoq';
import { import {
DialogService, DialogService,
PlanChangedDto,
PlanDto, PlanDto,
PlansDto, PlansDto,
PlansService, PlansService,
@ -96,7 +95,7 @@ describe('PlansState', () => {
const result = { redirectUri: 'http://url' }; const result = { redirectUri: 'http://url' };
plansService.setup(x => x.putPlan(app, It.isAny(), version)) plansService.setup(x => x.putPlan(app, It.isAny(), version))
.returns(() => of(new Versioned<PlanChangedDto>(newVersion, result))); .returns(() => of(new Versioned(newVersion, result)));
plansState.load().subscribe(); plansState.load().subscribe();
plansState.change('free').pipe(onErrorResumeNext()).subscribe(); plansState.change('free').pipe(onErrorResumeNext()).subscribe();
@ -113,7 +112,7 @@ describe('PlansState', () => {
plansState.window = <any>{ location: {} }; plansState.window = <any>{ location: {} };
plansService.setup(x => x.putPlan(app, It.isAny(), version)) plansService.setup(x => x.putPlan(app, It.isAny(), version))
.returns(() => of(new Versioned<PlanChangedDto>(newVersion, { redirectUri: '' }))); .returns(() => of(new Versioned(newVersion, { redirectUri: '' })));
plansState.load().subscribe(); plansState.load().subscribe();
plansState.change('id2_yearly').pipe(onErrorResumeNext()).subscribe(); plansState.change('id2_yearly').pipe(onErrorResumeNext()).subscribe();

6
src/Squidex/app/shared/state/roles.state.spec.ts

@ -70,7 +70,7 @@ describe('RolesState', () => {
const request = { name: newRole.name }; const request = { name: newRole.name };
rolesService.setup(x => x.postRole(app, request, version)) rolesService.setup(x => x.postRole(app, request, version))
.returns(() => of(new Versioned<RoleDto>(newVersion, newRole))); .returns(() => of(new Versioned(newVersion, newRole)));
rolesState.add(request).subscribe(); rolesState.add(request).subscribe();
@ -82,7 +82,7 @@ describe('RolesState', () => {
const request = { permissions: ['P4', 'P5'] }; const request = { permissions: ['P4', 'P5'] };
rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version)) rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rolesState.update(oldRoles[1], request).subscribe(); rolesState.update(oldRoles[1], request).subscribe();
@ -94,7 +94,7 @@ describe('RolesState', () => {
it('should remove role from snapshot when deleted', () => { it('should remove role from snapshot when deleted', () => {
rolesService.setup(x => x.deleteRole(app, oldRoles[0].name, version)) rolesService.setup(x => x.deleteRole(app, oldRoles[0].name, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rolesState.delete(oldRoles[0]).subscribe(); rolesState.delete(oldRoles[0]).subscribe();

10
src/Squidex/app/shared/state/rules.state.spec.ts

@ -86,7 +86,7 @@ describe('RulesState', () => {
const newAction = {}; const newAction = {};
rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is<UpdateRuleDto>(() => true), version)) rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is<UpdateRuleDto>(() => true), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rulesState.updateAction(oldRules[0], newAction, modified).subscribe(); rulesState.updateAction(oldRules[0], newAction, modified).subscribe();
@ -100,7 +100,7 @@ describe('RulesState', () => {
const newTrigger = {}; const newTrigger = {};
rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is<UpdateRuleDto>(() => true), version)) rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is<UpdateRuleDto>(() => true), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe(); rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe();
@ -112,7 +112,7 @@ describe('RulesState', () => {
it('should mark as enabled and update and user info when enabled', () => { it('should mark as enabled and update and user info when enabled', () => {
rulesService.setup(x => x.enableRule(app, oldRules[0].id, version)) rulesService.setup(x => x.enableRule(app, oldRules[0].id, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rulesState.enable(oldRules[0], modified).subscribe(); rulesState.enable(oldRules[0], modified).subscribe();
@ -124,7 +124,7 @@ describe('RulesState', () => {
it('should mark as disabled and update and user info when disabled', () => { it('should mark as disabled and update and user info when disabled', () => {
rulesService.setup(x => x.disableRule(app, oldRules[1].id, version)) rulesService.setup(x => x.disableRule(app, oldRules[1].id, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rulesState.disable(oldRules[1], modified).subscribe(); rulesState.disable(oldRules[1], modified).subscribe();
@ -136,7 +136,7 @@ describe('RulesState', () => {
it('should remove rule from snapshot when deleted', () => { it('should remove rule from snapshot when deleted', () => {
rulesService.setup(x => x.deleteRule(app, oldRules[0].id, version)) rulesService.setup(x => x.deleteRule(app, oldRules[0].id, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
rulesState.delete(oldRules[0]).subscribe(); rulesState.delete(oldRules[0]).subscribe();

54
src/Squidex/app/shared/state/schemas.state.spec.ts

@ -168,7 +168,7 @@ describe('SchemasState', () => {
it('should mark published and update user info when published', () => { it('should mark published and update user info when published', () => {
schemasService.setup(x => x.publishSchema(app, oldSchemas[0].name, version)) schemasService.setup(x => x.publishSchema(app, oldSchemas[0].name, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.publish(oldSchemas[0], modified).subscribe(); schemasState.publish(oldSchemas[0], modified).subscribe();
@ -180,7 +180,7 @@ describe('SchemasState', () => {
it('should unmark published and update user info when unpublished', () => { it('should unmark published and update user info when unpublished', () => {
schemasService.setup(x => x.unpublishSchema(app, oldSchemas[1].name, version)) schemasService.setup(x => x.unpublishSchema(app, oldSchemas[1].name, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.unpublish(oldSchemas[1], modified).subscribe(); schemasState.unpublish(oldSchemas[1], modified).subscribe();
@ -194,7 +194,7 @@ describe('SchemasState', () => {
const category = 'my-new-category'; const category = 'my-new-category';
schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is<UpdateSchemaCategoryDto>(i => i.name === category), version)) schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is<UpdateSchemaCategoryDto>(i => i.name === category), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); schemasState.changeCategory(oldSchemas[0], category, modified).subscribe();
@ -211,7 +211,7 @@ describe('SchemasState', () => {
it('should nmark published and update user info when published selected schema', () => { it('should nmark published and update user info when published selected schema', () => {
schemasService.setup(x => x.publishSchema(app, schema.name, version)) schemasService.setup(x => x.publishSchema(app, schema.name, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.publish(schema, modified).subscribe(); schemasState.publish(schema, modified).subscribe();
@ -225,7 +225,7 @@ describe('SchemasState', () => {
const category = 'my-new-category'; const category = 'my-new-category';
schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is<UpdateSchemaCategoryDto>(i => i.name === category), version)) schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is<UpdateSchemaCategoryDto>(i => i.name === category), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); schemasState.changeCategory(oldSchemas[0], category, modified).subscribe();
@ -239,7 +239,7 @@ describe('SchemasState', () => {
const request = { label: 'name2_label', hints: 'name2_hints' }; const request = { label: 'name2_label', hints: 'name2_hints' };
schemasService.setup(x => x.putSchema(app, schema.name, It.isAny(), version)) schemasService.setup(x => x.putSchema(app, schema.name, It.isAny(), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.update(schema, request, modified).subscribe(); schemasState.update(schema, request, modified).subscribe();
@ -254,7 +254,7 @@ describe('SchemasState', () => {
const request = { query: '<query-script>' }; const request = { query: '<query-script>' };
schemasService.setup(x => x.putScripts(app, schema.name, It.isAny(), version)) schemasService.setup(x => x.putScripts(app, schema.name, It.isAny(), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.configureScripts(schema, request, modified).subscribe(); schemasState.configureScripts(schema, request, modified).subscribe();
@ -268,7 +268,7 @@ describe('SchemasState', () => {
const request = { web: 'url' }; const request = { web: 'url' };
schemasService.setup(x => x.putPreviewUrls(app, schema.name, It.isAny(), version)) schemasService.setup(x => x.putPreviewUrls(app, schema.name, It.isAny(), version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.configurePreviewUrls(schema, request, modified).subscribe(); schemasState.configurePreviewUrls(schema, request, modified).subscribe();
@ -294,7 +294,7 @@ describe('SchemasState', () => {
it('should remove schema from snapshot when deleted', () => { it('should remove schema from snapshot when deleted', () => {
schemasService.setup(x => x.deleteSchema(app, schema.name, version)) schemasService.setup(x => x.deleteSchema(app, schema.name, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.delete(schema).subscribe(); schemasState.delete(schema).subscribe();
@ -308,7 +308,7 @@ describe('SchemasState', () => {
const newField = new RootFieldDto(3, '3', createProperties('String'), 'invariant'); const newField = new RootFieldDto(3, '3', createProperties('String'), 'invariant');
schemasService.setup(x => x.postField(app, schema.name, It.isAny(), undefined, version)) schemasService.setup(x => x.postField(app, schema.name, It.isAny(), undefined, version))
.returns(() => of(new Versioned<RootFieldDto>(newVersion, newField))); .returns(() => of(new Versioned(newVersion, newField)));
schemasState.addField(schema, request, undefined, modified).subscribe(); schemasState.addField(schema, request, undefined, modified).subscribe();
@ -324,7 +324,7 @@ describe('SchemasState', () => {
const newField = new NestedFieldDto(3, '3', createProperties('String'), 2); const newField = new NestedFieldDto(3, '3', createProperties('String'), 2);
schemasService.setup(x => x.postField(app, schema.name, It.isAny(), 2, version)) schemasService.setup(x => x.postField(app, schema.name, It.isAny(), 2, version))
.returns(() => of(new Versioned<NestedFieldDto>(newVersion, newField))); .returns(() => of(new Versioned(newVersion, newField)));
schemasState.addField(schema, request, field2, modified).subscribe(); schemasState.addField(schema, request, field2, modified).subscribe();
@ -336,7 +336,7 @@ describe('SchemasState', () => {
it('should remove field and update user info when field removed', () => { it('should remove field and update user info when field removed', () => {
schemasService.setup(x => x.deleteField(app, schema.name, field1.fieldId, undefined, version)) schemasService.setup(x => x.deleteField(app, schema.name, field1.fieldId, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.deleteField(schema, field1, modified).subscribe(); schemasState.deleteField(schema, field1, modified).subscribe();
@ -348,7 +348,7 @@ describe('SchemasState', () => {
it('should remove field and update user info when nested field removed', () => { it('should remove field and update user info when nested field removed', () => {
schemasService.setup(x => x.deleteField(app, schema.name, nested1.fieldId, 2, version)) schemasService.setup(x => x.deleteField(app, schema.name, nested1.fieldId, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.deleteField(schema, nested1, modified).subscribe(); schemasState.deleteField(schema, nested1, modified).subscribe();
@ -360,7 +360,7 @@ describe('SchemasState', () => {
it('should sort fields and update user info when fields sorted', () => { it('should sort fields and update user info when fields sorted', () => {
schemasService.setup(x => x.putFieldOrdering(app, schema.name, [field2.fieldId, field1.fieldId], undefined, version)) schemasService.setup(x => x.putFieldOrdering(app, schema.name, [field2.fieldId, field1.fieldId], undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.sortFields(schema, [field2, field1], undefined, modified).subscribe(); schemasState.sortFields(schema, [field2, field1], undefined, modified).subscribe();
@ -372,7 +372,7 @@ describe('SchemasState', () => {
it('should sort fields and update user info when nested fields sorted', () => { it('should sort fields and update user info when nested fields sorted', () => {
schemasService.setup(x => x.putFieldOrdering(app, schema.name, [nested2.fieldId, nested1.fieldId], 2, version)) schemasService.setup(x => x.putFieldOrdering(app, schema.name, [nested2.fieldId, nested1.fieldId], 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.sortFields(schema, [nested2, nested1], field2, modified).subscribe(); schemasState.sortFields(schema, [nested2, nested1], field2, modified).subscribe();
@ -386,7 +386,7 @@ describe('SchemasState', () => {
const request = { properties: createProperties('String') }; const request = { properties: createProperties('String') };
schemasService.setup(x => x.putField(app, schema.name, field1.fieldId, request, undefined, version)) schemasService.setup(x => x.putField(app, schema.name, field1.fieldId, request, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.updateField(schema, field1, request, modified).subscribe(); schemasState.updateField(schema, field1, request, modified).subscribe();
@ -400,7 +400,7 @@ describe('SchemasState', () => {
const request = { properties: createProperties('String') }; const request = { properties: createProperties('String') };
schemasService.setup(x => x.putField(app, schema.name, nested1.fieldId, request, 2, version)) schemasService.setup(x => x.putField(app, schema.name, nested1.fieldId, request, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.updateField(schema, nested1, request, modified).subscribe(); schemasState.updateField(schema, nested1, request, modified).subscribe();
@ -412,7 +412,7 @@ describe('SchemasState', () => {
it('should mark field hidden and update user info when field hidden', () => { it('should mark field hidden and update user info when field hidden', () => {
schemasService.setup(x => x.hideField(app, schema.name, field1.fieldId, undefined, version)) schemasService.setup(x => x.hideField(app, schema.name, field1.fieldId, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.hideField(schema, field1, modified).subscribe(); schemasState.hideField(schema, field1, modified).subscribe();
@ -424,7 +424,7 @@ describe('SchemasState', () => {
it('should mark field hidden and update user info when nested field hidden', () => { it('should mark field hidden and update user info when nested field hidden', () => {
schemasService.setup(x => x.hideField(app, schema.name, nested1.fieldId, 2, version)) schemasService.setup(x => x.hideField(app, schema.name, nested1.fieldId, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.hideField(schema, nested1, modified).subscribe(); schemasState.hideField(schema, nested1, modified).subscribe();
@ -436,7 +436,7 @@ describe('SchemasState', () => {
it('should mark field disabled and update user info when field disabled', () => { it('should mark field disabled and update user info when field disabled', () => {
schemasService.setup(x => x.disableField(app, schema.name, field1.fieldId, undefined, version)) schemasService.setup(x => x.disableField(app, schema.name, field1.fieldId, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.disableField(schema, field1, modified).subscribe(); schemasState.disableField(schema, field1, modified).subscribe();
@ -448,7 +448,7 @@ describe('SchemasState', () => {
it('should mark field disabled and update user info when nested disabled', () => { it('should mark field disabled and update user info when nested disabled', () => {
schemasService.setup(x => x.disableField(app, schema.name, nested1.fieldId, 2, version)) schemasService.setup(x => x.disableField(app, schema.name, nested1.fieldId, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.disableField(schema, nested1, modified).subscribe(); schemasState.disableField(schema, nested1, modified).subscribe();
@ -460,7 +460,7 @@ describe('SchemasState', () => {
it('should mark field locked and update user info when field locked', () => { it('should mark field locked and update user info when field locked', () => {
schemasService.setup(x => x.lockField(app, schema.name, field1.fieldId, undefined, version)) schemasService.setup(x => x.lockField(app, schema.name, field1.fieldId, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.lockField(schema, field1, modified).subscribe(); schemasState.lockField(schema, field1, modified).subscribe();
@ -472,7 +472,7 @@ describe('SchemasState', () => {
it('should mark field locked and update user info when nested field locked', () => { it('should mark field locked and update user info when nested field locked', () => {
schemasService.setup(x => x.lockField(app, schema.name, nested1.fieldId, 2, version)) schemasService.setup(x => x.lockField(app, schema.name, nested1.fieldId, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.lockField(schema, nested1, modified).subscribe(); schemasState.lockField(schema, nested1, modified).subscribe();
@ -484,7 +484,7 @@ describe('SchemasState', () => {
it('should unmark field hidden and update user info when field shown', () => { it('should unmark field hidden and update user info when field shown', () => {
schemasService.setup(x => x.showField(app, schema.name, field2.fieldId, undefined, version)) schemasService.setup(x => x.showField(app, schema.name, field2.fieldId, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.showField(schema, field2, modified).subscribe(); schemasState.showField(schema, field2, modified).subscribe();
@ -496,7 +496,7 @@ describe('SchemasState', () => {
it('should unmark field hidden and update user info when nested field shown', () => { it('should unmark field hidden and update user info when nested field shown', () => {
schemasService.setup(x => x.showField(app, schema.name, nested2.fieldId, 2, version)) schemasService.setup(x => x.showField(app, schema.name, nested2.fieldId, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.showField(schema, nested2, modified).subscribe(); schemasState.showField(schema, nested2, modified).subscribe();
@ -508,7 +508,7 @@ describe('SchemasState', () => {
it('should unmark field disabled and update user info when field enabled', () => { it('should unmark field disabled and update user info when field enabled', () => {
schemasService.setup(x => x.enableField(app, schema.name, field2.fieldId, undefined, version)) schemasService.setup(x => x.enableField(app, schema.name, field2.fieldId, undefined, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.enableField(schema, field2, modified).subscribe(); schemasState.enableField(schema, field2, modified).subscribe();
@ -520,7 +520,7 @@ describe('SchemasState', () => {
it('should unmark field disabled and update user info when nested field enabled', () => { it('should unmark field disabled and update user info when nested field enabled', () => {
schemasService.setup(x => x.enableField(app, schema.name, nested2.fieldId, 2, version)) schemasService.setup(x => x.enableField(app, schema.name, nested2.fieldId, 2, version))
.returns(() => of(new Versioned<any>(newVersion, {}))); .returns(() => of(new Versioned(newVersion, {})));
schemasState.enableField(schema, nested2, modified).subscribe(); schemasState.enableField(schema, nested2, modified).subscribe();

Loading…
Cancel
Save