mirror of https://github.com/Squidex/squidex.git
11 changed files with 290 additions and 205 deletions
@ -0,0 +1,99 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { Observable } from 'rxjs'; |
||||
|
import { IMock, Mock } from 'typemoq'; |
||||
|
|
||||
|
import { |
||||
|
AppsState, |
||||
|
AppPatternDto, |
||||
|
AppPatternsDto, |
||||
|
AppPatternsService, |
||||
|
PatternsState, |
||||
|
DialogService, |
||||
|
EditAppPatternDto, |
||||
|
Version, |
||||
|
Versioned |
||||
|
} from '@app/shared'; |
||||
|
|
||||
|
describe('PatternsState', () => { |
||||
|
const app = 'my-app'; |
||||
|
const version = new Version('1'); |
||||
|
const newVersion = new Version('2'); |
||||
|
|
||||
|
const oldPatterns = [ |
||||
|
new AppPatternDto('id1', 'name1', 'pattern1', ''), |
||||
|
new AppPatternDto('id2', 'name2', 'pattern2', '') |
||||
|
]; |
||||
|
|
||||
|
let dialogs: IMock<DialogService>; |
||||
|
let appsState: IMock<AppsState>; |
||||
|
let patternsService: IMock<AppPatternsService>; |
||||
|
let patternsState: PatternsState; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
dialogs = Mock.ofType<DialogService>(); |
||||
|
|
||||
|
appsState = Mock.ofType<AppsState>(); |
||||
|
|
||||
|
appsState.setup(x => x.appName) |
||||
|
.returns(() => app); |
||||
|
|
||||
|
patternsService = Mock.ofType<AppPatternsService>(); |
||||
|
|
||||
|
patternsService.setup(x => x.getPatterns(app)) |
||||
|
.returns(() => Observable.of(new AppPatternsDto(oldPatterns, version))); |
||||
|
|
||||
|
patternsState = new PatternsState(patternsService.object, appsState.object, dialogs.object); |
||||
|
patternsState.load().subscribe(); |
||||
|
}); |
||||
|
|
||||
|
it('should load patterns', () => { |
||||
|
expect(patternsState.snapshot.patterns.values).toEqual(oldPatterns); |
||||
|
expect(patternsState.snapshot.version).toEqual(version); |
||||
|
}); |
||||
|
|
||||
|
it('should add pattern to snapshot', () => { |
||||
|
const newPattern = new AppPatternDto('id3', 'name3', 'pattern3', ''); |
||||
|
|
||||
|
const request = new EditAppPatternDto('name3', 'pattern3', ''); |
||||
|
|
||||
|
patternsService.setup(x => x.postPattern(app, request, version)) |
||||
|
.returns(() => Observable.of(new Versioned<AppPatternDto>(newVersion, newPattern))); |
||||
|
|
||||
|
patternsState.create(request).subscribe(); |
||||
|
|
||||
|
expect(patternsState.snapshot.patterns.values).toEqual([...oldPatterns, newPattern]); |
||||
|
expect(patternsState.snapshot.version).toEqual(newVersion); |
||||
|
}); |
||||
|
|
||||
|
it('should update pattern in snapshot', () => { |
||||
|
const request = new EditAppPatternDto('a_name2', 'a_pattern2', 'a_message2'); |
||||
|
|
||||
|
patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) |
||||
|
.returns(() => Observable.of(new Versioned<any>(newVersion, {}))); |
||||
|
|
||||
|
patternsState.update(oldPatterns[1], request).subscribe(); |
||||
|
|
||||
|
const pattern_1 = patternsState.snapshot.patterns.at(0); |
||||
|
|
||||
|
expect(pattern_1.name).toBe('a_name2'); |
||||
|
expect(pattern_1.pattern).toBe('a_pattern2'); |
||||
|
expect(pattern_1.message).toBe('a_message2'); |
||||
|
expect(patternsState.snapshot.version).toEqual(newVersion); |
||||
|
}); |
||||
|
|
||||
|
it('should remove pattern from snapshot', () => { |
||||
|
patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version)) |
||||
|
.returns(() => Observable.of(new Versioned<any>(newVersion, {}))); |
||||
|
|
||||
|
patternsState.delete(oldPatterns[0]).subscribe(); |
||||
|
|
||||
|
expect(patternsState.snapshot.patterns.values).toEqual([oldPatterns[1]]); |
||||
|
expect(patternsState.snapshot.version).toEqual(newVersion); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,131 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { Injectable } from '@angular/core'; |
||||
|
import { FormBuilder, Validators, FormGroup } from '@angular/forms'; |
||||
|
import { Observable } from 'rxjs'; |
||||
|
|
||||
|
import '@app/framework/utils/rxjs-extensions'; |
||||
|
|
||||
|
import { |
||||
|
DialogService, |
||||
|
ImmutableArray, |
||||
|
Form, |
||||
|
State, |
||||
|
ValidatorsEx, |
||||
|
Version |
||||
|
} from '@app/framework'; |
||||
|
|
||||
|
import { AppsState } from './apps.state'; |
||||
|
|
||||
|
import { |
||||
|
AppPatternDto, |
||||
|
AppPatternsService, |
||||
|
EditAppPatternDto |
||||
|
} from './../services/app-patterns.service'; |
||||
|
|
||||
|
export class EditPatternForm extends Form<FormGroup> { |
||||
|
constructor(formBuilder: FormBuilder) { |
||||
|
super(formBuilder.group({ |
||||
|
name: ['', |
||||
|
[ |
||||
|
Validators.required, |
||||
|
Validators.maxLength(100), |
||||
|
ValidatorsEx.pattern('[A-z0-9]+[A-z0-9\- ]*[A-z0-9]', 'Name can only contain letters, numbers, dashes and spaces.') |
||||
|
] |
||||
|
], |
||||
|
pattern: ['', |
||||
|
[ |
||||
|
Validators.required |
||||
|
] |
||||
|
], |
||||
|
message: ['', |
||||
|
[ |
||||
|
Validators.maxLength(1000) |
||||
|
] |
||||
|
] |
||||
|
})); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
interface Snapshot { |
||||
|
patterns: ImmutableArray<AppPatternDto>; |
||||
|
|
||||
|
isLoaded: boolean; |
||||
|
|
||||
|
version: Version; |
||||
|
} |
||||
|
|
||||
|
@Injectable() |
||||
|
export class PatternsState extends State<Snapshot> { |
||||
|
public patterns = |
||||
|
this.changes.map(x => x.patterns); |
||||
|
|
||||
|
public isLoaded = |
||||
|
this.changes.map(x => x.isLoaded); |
||||
|
|
||||
|
constructor( |
||||
|
private readonly appPatternsService: AppPatternsService, |
||||
|
private readonly appsState: AppsState, |
||||
|
private readonly dialogs: DialogService |
||||
|
) { |
||||
|
super({ patterns: ImmutableArray.empty(), version: new Version(''), isLoaded: false }); |
||||
|
} |
||||
|
|
||||
|
public load(): Observable<any> { |
||||
|
return this.appPatternsService.getPatterns(this.appName) |
||||
|
.do(dtos => { |
||||
|
this.next(s => { |
||||
|
return { patterns: ImmutableArray.of(dtos.patterns), isLoaded: true, version: dtos.version }; |
||||
|
}); |
||||
|
}) |
||||
|
.notify(this.dialogs); |
||||
|
} |
||||
|
|
||||
|
public create(request: EditAppPatternDto): Observable<any> { |
||||
|
return this.appPatternsService.postPattern(this.appName, request, this.snapshot.version) |
||||
|
.do(dto => { |
||||
|
this.next(s => { |
||||
|
const patterns = s.patterns.push(dto.payload).sortByStringAsc(x => x.name); |
||||
|
|
||||
|
return { ...s, patterns, version: dto.version }; |
||||
|
}); |
||||
|
}) |
||||
|
.notify(this.dialogs); |
||||
|
} |
||||
|
|
||||
|
public update(pattern: AppPatternDto, request: EditAppPatternDto): Observable<any> { |
||||
|
return this.appPatternsService.putPattern(this.appName, pattern.id, request, this.snapshot.version) |
||||
|
.do(dto => { |
||||
|
this.next(s => { |
||||
|
const patterns = s.patterns.replaceBy('id', update(pattern, request)).sortByStringAsc(x => x.name); |
||||
|
|
||||
|
return { ...s, patterns, version: dto.version }; |
||||
|
}); |
||||
|
}) |
||||
|
.notify(this.dialogs); |
||||
|
} |
||||
|
|
||||
|
public delete(pattern: AppPatternDto): Observable<any> { |
||||
|
return this.appPatternsService.deletePattern(this.appName, pattern.id, this.snapshot.version) |
||||
|
.do(dto => { |
||||
|
this.next(s => { |
||||
|
const patterns = s.patterns.filter(c => c.id !== pattern.id); |
||||
|
|
||||
|
return { ...s, patterns, version: dto.version }; |
||||
|
}); |
||||
|
}) |
||||
|
.notify(this.dialogs); |
||||
|
} |
||||
|
|
||||
|
private get appName() { |
||||
|
return this.appsState.appName; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const update = (pattern: AppPatternDto, request: EditAppPatternDto) => |
||||
|
new AppPatternDto(pattern.id, request.name, request.pattern, request.message); |
||||
Loading…
Reference in new issue