From 7c7cc96f04f26e515a0a0817c23b097790fa80b9 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 14 May 2018 12:39:40 +0200 Subject: [PATCH] API for schema categories. --- Squidex.sln.DotSettings | 50 ------------------- .../Schemas/Commands/ChangeCategory.cs | 14 ++++++ .../Schemas/Guards/GuardSchema.cs | 5 ++ .../Schemas/ISchemaEntity.cs | 2 + .../Schemas/SchemaGrain.cs | 13 +++++ .../Schemas/State/SchemaState.cs | 8 +++ .../Schemas/SchemaCategoryChanged.cs | 17 +++++++ .../Schemas/Models/ChangeCategoryDto.cs | 25 ++++++++++ .../Controllers/Schemas/Models/SchemaDto.cs | 5 ++ .../Controllers/Schemas/SchemasController.cs | 22 ++++++++ .../shared/services/schemas.fields.spec.ts | 2 +- .../shared/services/schemas.service.spec.ts | 29 +++++++++-- .../app/shared/services/schemas.service.ts | 33 ++++++++++-- .../app/shared/state/schemas.state.spec.ts | 42 +++++++++++++--- src/Squidex/app/shared/state/schemas.state.ts | 49 +++++++++++++++++- .../Schemas/Guards/GuardSchemaTests.cs | 8 +++ .../Schemas/SchemaGrainTests.cs | 19 +++++++ 17 files changed, 275 insertions(+), 68 deletions(-) delete mode 100644 Squidex.sln.DotSettings create mode 100644 src/Squidex.Domain.Apps.Entities/Schemas/Commands/ChangeCategory.cs create mode 100644 src/Squidex.Domain.Apps.Events/Schemas/SchemaCategoryChanged.cs create mode 100644 src/Squidex/Areas/Api/Controllers/Schemas/Models/ChangeCategoryDto.cs diff --git a/Squidex.sln.DotSettings b/Squidex.sln.DotSettings deleted file mode 100644 index ecdd59c86..000000000 --- a/Squidex.sln.DotSettings +++ /dev/null @@ -1,50 +0,0 @@ - - False - True - False - True - False - True - - False - True - - False - True - - - False - True - - False - True - - - False - True - - - True - - - - - - - - - <?xml version="1.0" encoding="utf-16"?><Profile name="Header"><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> - <?xml version="1.0" encoding="utf-16"?><Profile name="Namespaces"><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> - <?xml version="1.0" encoding="utf-16"?><Profile name="Typescript"><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs></Profile> - False - ========================================================================== - Squidex Headless CMS -========================================================================== - Copyright (c) Squidex UG (haftungsbeschraenkt) - All rights reserved. Licensed under the MIT license. -========================================================================== - - True - True - True - \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Commands/ChangeCategory.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/ChangeCategory.cs new file mode 100644 index 000000000..c6eb7ff18 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Commands/ChangeCategory.cs @@ -0,0 +1,14 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Domain.Apps.Entities.Schemas.Commands +{ + public sealed class ChangeCategory : SchemaCommand + { + public string Name { get; set; } + } +} diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs index fb59048a1..81684f6b0 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs @@ -119,6 +119,11 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards Guard.NotNull(command, nameof(command)); } + public static void CanChangeCategory(Schema schema, ChangeCategory command) + { + Guard.NotNull(command, nameof(command)); + } + public static void CanDelete(Schema schema, DeleteSchema command) { Guard.NotNull(command, nameof(command)); diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/ISchemaEntity.cs b/src/Squidex.Domain.Apps.Entities/Schemas/ISchemaEntity.cs index 8c341e76e..335a91e92 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/ISchemaEntity.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/ISchemaEntity.cs @@ -21,6 +21,8 @@ namespace Squidex.Domain.Apps.Entities.Schemas string Name { get; } + string Category { get; } + bool IsPublished { get; } bool IsDeleted { get; } diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs b/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs index 95a1c7b02..62a30e545 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/SchemaGrain.cs @@ -161,6 +161,14 @@ namespace Squidex.Domain.Apps.Entities.Schemas ConfigureScripts(c); }); + case ChangeCategory changeCategory: + return UpdateAsync(changeCategory, c => + { + GuardSchema.CanChangeCategory(Snapshot.SchemaDef, c); + + ChangeCategory(c); + }); + case DeleteSchema deleteSchema: return UpdateAsync(deleteSchema, c => { @@ -253,6 +261,11 @@ namespace Squidex.Domain.Apps.Entities.Schemas RaiseEvent(SimpleMapper.Map(command, new ScriptsConfigured())); } + public void ChangeCategory(ChangeCategory command) + { + RaiseEvent(SimpleMapper.Map(command, new SchemaCategoryChanged())); + } + public void Delete(DeleteSchema command) { RaiseEvent(SimpleMapper.Map(command, new SchemaDeleted())); diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs b/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs index 5f09910e6..256d42673 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs @@ -28,6 +28,9 @@ namespace Squidex.Domain.Apps.Entities.Schemas.State [JsonProperty] public string Name { get; set; } + [JsonProperty] + public string Category { get; set; } + [JsonProperty] public int TotalFields { get; set; } = 0; @@ -126,6 +129,11 @@ namespace Squidex.Domain.Apps.Entities.Schemas.State TotalFields++; } + protected void On(SchemaCategoryChanged @event, FieldRegistry registry) + { + Category = @event.Name; + } + protected void On(SchemaPublished @event, FieldRegistry registry) { SchemaDef = SchemaDef.Publish(); diff --git a/src/Squidex.Domain.Apps.Events/Schemas/SchemaCategoryChanged.cs b/src/Squidex.Domain.Apps.Events/Schemas/SchemaCategoryChanged.cs new file mode 100644 index 000000000..412ef928c --- /dev/null +++ b/src/Squidex.Domain.Apps.Events/Schemas/SchemaCategoryChanged.cs @@ -0,0 +1,17 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Infrastructure.EventSourcing; + +namespace Squidex.Domain.Apps.Events.Schemas +{ + [EventType(nameof(SchemaCategoryChanged))] + public sealed class SchemaCategoryChanged : SchemaEvent + { + public string Name { get; set; } + } +} diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/ChangeCategoryDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/ChangeCategoryDto.cs new file mode 100644 index 000000000..29e497ec6 --- /dev/null +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/ChangeCategoryDto.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Entities.Schemas.Commands; +using Squidex.Infrastructure.Reflection; + +namespace Squidex.Areas.Api.Controllers.Schemas.Models +{ + public sealed class ChangeCategoryDto + { + /// + /// The name of the category. + /// + public string Name { get; set; } + + public ChangeCategory ToCommand() + { + return SimpleMapper.Map(this, new ChangeCategory()); + } + } +} diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs index e36537ce7..0c0869ede 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs @@ -28,6 +28,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models [RegularExpression("^[a-z0-9]+(\\-[a-z0-9]+)*$")] public string Name { get; set; } + /// + /// The name of the category. + /// + public string Category { get; set; } + /// /// The schema properties. /// diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs b/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs index 1d2919a32..f7fc035c0 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs @@ -147,6 +147,28 @@ namespace Squidex.Areas.Api.Controllers.Schemas return NoContent(); } + /// + /// Update a schema category. + /// + /// The name of the app. + /// The name of the schema. + /// The schema object that needs to updated. + /// + /// 204 => Schema has been updated. + /// 400 => Schema properties are not valid. + /// 404 => Schema or app not found. + /// + [MustBeAppDeveloper] + [HttpPut] + [Route("apps/{app}/schemas/{name}/category")] + [ApiCosts(1)] + public async Task PutCategory(string app, string name, [FromBody] ChangeCategoryDto request) + { + await CommandBus.PublishAsync(request.ToCommand()); + + return NoContent(); + } + /// /// Update the scripts of a schema. /// diff --git a/src/Squidex/app/shared/services/schemas.fields.spec.ts b/src/Squidex/app/shared/services/schemas.fields.spec.ts index 765989151..323cac607 100644 --- a/src/Squidex/app/shared/services/schemas.fields.spec.ts +++ b/src/Squidex/app/shared/services/schemas.fields.spec.ts @@ -343,7 +343,7 @@ describe('StringField', () => { }); function createSchema(properties: SchemaPropertiesDto, index = 1, fields: FieldDto[]) { - return new SchemaDetailsDto('id' + index, 'schema' + index, properties, true, null!, null!, null!, null!, null!, fields); + return new SchemaDetailsDto('id' + index, 'schema' + index, '', properties, true, null!, null!, null!, null!, null!, fields); } function createField(properties: FieldPropertiesDto, index = 1, partitioning = 'languages') { diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index 9ca10aa58..efbc37b83 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -21,6 +21,7 @@ import { SchemaPropertiesDto, SchemasService, UpdateFieldDto, + UpdateSchemaCategoryDto, UpdateSchemaDto, UpdateSchemaScriptsDto, Version @@ -70,6 +71,7 @@ describe('SchemasService', () => { { id: 'id1', name: 'name1', + category: 'category1', properties: { label: 'label1', hints: 'hints1' @@ -85,6 +87,7 @@ describe('SchemasService', () => { { id: 'id2', name: 'name2', + category: 'category2', properties: { label: 'label2', hints: 'hints2' @@ -100,11 +103,11 @@ describe('SchemasService', () => { ]); expect(schemas).toEqual([ - new SchemaDto('id1', 'name1', new SchemaPropertiesDto('label1', 'hints1'), true, 'Created1', 'LastModifiedBy1', + new SchemaDto('id1', 'name1', 'category1', new SchemaPropertiesDto('label1', 'hints1'), true, 'Created1', 'LastModifiedBy1', DateTime.parseISO_UTC('2016-12-12T10:10'), DateTime.parseISO_UTC('2017-12-12T10:10'), new Version('11')), - new SchemaDto('id2', 'name2', new SchemaPropertiesDto('label2', 'hints2'), true, 'Created2', 'LastModifiedBy2', + new SchemaDto('id2', 'name2', 'category2', new SchemaPropertiesDto('label2', 'hints2'), true, 'Created2', 'LastModifiedBy2', DateTime.parseISO_UTC('2016-10-12T10:10'), DateTime.parseISO_UTC('2017-10-12T10:10'), new Version('22')) @@ -128,6 +131,7 @@ describe('SchemasService', () => { req.flush({ id: 'id1', name: 'name1', + category: 'category1', isPublished: true, created: '2016-12-12T10:10', createdBy: 'Created1', @@ -250,7 +254,7 @@ describe('SchemasService', () => { }); expect(schema).toEqual( - new SchemaDetailsDto('id1', 'name1', new SchemaPropertiesDto('label1', 'hints1'), true, 'Created1', 'LastModifiedBy1', + new SchemaDetailsDto('id1', 'name1', 'category1', new SchemaPropertiesDto('label1', 'hints1'), true, 'Created1', 'LastModifiedBy1', DateTime.parseISO_UTC('2016-12-12T10:10'), DateTime.parseISO_UTC('2017-12-12T10:10'), new Version('2'), @@ -297,7 +301,7 @@ describe('SchemasService', () => { }); expect(schema).toEqual( - new SchemaDetailsDto('1', dto.name, new SchemaPropertiesDto(), false, user, user, now, now, new Version('2'), [])); + new SchemaDetailsDto('1', dto.name, '', new SchemaPropertiesDto(), false, user, user, now, now, new Version('2'), [])); })); it('should make post request to add field', @@ -342,7 +346,7 @@ describe('SchemasService', () => { const dto = new UpdateSchemaScriptsDto(); - schemasService.putSchemaScripts('my-app', 'my-schema', dto, version).subscribe(); + schemasService.putScripts('my-app', 'my-schema', dto, version).subscribe(); const req = httpMock.expectOne('http://service/p/api/apps/my-app/schemas/my-schema/scripts'); @@ -352,6 +356,21 @@ describe('SchemasService', () => { req.flush({}); })); + it('should make put request to update category', + inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { + + const dto = new UpdateSchemaCategoryDto(); + + schemasService.putCategory('my-app', 'my-schema', dto, version).subscribe(); + + const req = httpMock.expectOne('http://service/p/api/apps/my-app/schemas/my-schema/category'); + + expect(req.request.method).toEqual('PUT'); + expect(req.request.headers.get('If-Match')).toBe(version.value); + + req.flush({}); + })); + it('should make put request to update field', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index 0e154710c..a5bbeaeec 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -104,6 +104,7 @@ export class SchemaDto { constructor( public readonly id: string, public readonly name: string, + public readonly category: string, public readonly properties: SchemaPropertiesDto, public readonly isPublished: boolean, public readonly createdBy: string, @@ -118,7 +119,7 @@ export class SchemaDto { export class SchemaDetailsDto extends SchemaDto { public readonly listFields: FieldDto[]; - constructor(id: string, name: string, properties: SchemaPropertiesDto, isPublished: boolean, createdBy: string, lastModifiedBy: string, created: DateTime, lastModified: DateTime, version: Version, + constructor(id: string, name: string, category: string, properties: SchemaPropertiesDto, isPublished: boolean, createdBy: string, lastModifiedBy: string, created: DateTime, lastModified: DateTime, version: Version, public readonly fields: FieldDto[], public readonly scriptQuery?: string, public readonly scriptCreate?: string, @@ -126,7 +127,7 @@ export class SchemaDetailsDto extends SchemaDto { public readonly scriptDelete?: string, public readonly scriptChange?: string ) { - super(id, name, properties, isPublished, createdBy, lastModifiedBy, created, lastModified, version); + super(id, name, category, properties, isPublished, createdBy, lastModifiedBy, created, lastModified, version); this.listFields = this.fields.filter(x => x.properties.isListField); @@ -600,6 +601,13 @@ export class UpdateSchemaDto { } } +export class UpdateSchemaCategoryDto { + constructor( + public readonly category?: string + ) { + } +} + export class AddFieldDto { constructor( public readonly name: string, @@ -659,7 +667,9 @@ export class SchemasService { return new SchemaDto( item.id, - item.name, properties, + item.name, + item.category, + properties, item.isPublished, item.createdBy, item.lastModifiedBy, @@ -698,7 +708,9 @@ export class SchemasService { return new SchemaDetailsDto( body.id, - body.name, properties, + body.name, + body.category, + properties, body.isPublished, body.createdBy, body.lastModifiedBy, @@ -727,6 +739,7 @@ export class SchemasService { return new SchemaDetailsDto( body.id, dto.name, + '', dto.properties || new SchemaPropertiesDto(), false, user, @@ -781,7 +794,7 @@ export class SchemasService { .pretifyError('Failed to delete schema. Please reload.'); } - public putSchemaScripts(appName: string, schemaName: string, dto: UpdateSchemaScriptsDto, version: Version): Observable> { + public putScripts(appName: string, schemaName: string, dto: UpdateSchemaScriptsDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/scripts`); return HTTP.putVersioned(this.http, url, dto, version) @@ -831,6 +844,16 @@ export class SchemasService { .pretifyError('Failed to unpublish schema. Please reload.'); } + public putCategory(appName: string, schemaName: string, dto: UpdateSchemaCategoryDto, version: Version): Observable> { + const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/category`); + + return HTTP.putVersioned(this.http, url, dto, version) + .do(() => { + this.analytics.trackEvent('Schema', 'CategoryChanged', appName); + }) + .pretifyError('Failed to change category. Please reload.'); + } + public putField(appName: string, schemaName: string, fieldId: number, dto: UpdateFieldDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}`); diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 8df92f2af..1a8df79c6 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -23,6 +23,7 @@ import { SchemaDto, SchemasService, UpdateFieldDto, + UpdateSchemaCategoryDto, UpdateSchemaDto, UpdateSchemaScriptsDto, Version, @@ -39,15 +40,15 @@ describe('SchemasState', () => { const newVersion = new Version('2'); const oldSchemas = [ - new SchemaDto('id1', 'name1', {}, false, creator, creator, creation, creation, version), - new SchemaDto('id2', 'name2', {}, true , creator, creator, creation, creation, version) + new SchemaDto('id1', 'name1', 'category1', {}, false, creator, creator, creation, creation, version), + new SchemaDto('id2', 'name2', 'category2', {}, true , creator, creator, creation, creation, version) ]; const field1 = new FieldDto(1, '1', false, false, false, 'l', createProperties('String')); const field2 = new FieldDto(2, '2', true, true, true, 'l', createProperties('Number')); const schema = - new SchemaDetailsDto('id2', 'name2', {}, true, + new SchemaDetailsDto('id2', 'name2', 'category2', {}, true, creator, creator, creation, creation, version, @@ -170,12 +171,26 @@ describe('SchemasState', () => { expectToBeModified(schema_1); }); + it('should change category and update user info when category changed', () => { + const category = 'my-new-category'; + + schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.category === category), version)) + .returns(() => Observable.of(new Versioned(newVersion, {}))); + + schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); + + const schema_1 = schemasState.snapshot.schemas.at(0); + + expect(schema_1.category).toEqual(category); + expectToBeModified(schema_1); + }); + describe('with selection', () => { beforeEach(() => { schemasState.select(schema.name).subscribe(); }); - it('should unmark 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)) .returns(() => Observable.of(new Versioned(newVersion, {}))); @@ -187,6 +202,21 @@ describe('SchemasState', () => { expectToBeModified(schema_1); }); + + it('should change category and update user info when category of selected schema changed', () => { + const category = 'my-new-category'; + + schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.category === category), version)) + .returns(() => Observable.of(new Versioned(newVersion, {}))); + + schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); + + const schema_1 = schemasState.snapshot.schemas.at(0); + + expect(schema_1.category).toEqual(category); + expectToBeModified(schema_1); + }); + it('should update properties and update user info when updated', () => { const request = new UpdateSchemaDto('name2_label', 'name2_hints'); @@ -205,7 +235,7 @@ describe('SchemasState', () => { it('should update script properties and update user info when scripts configured', () => { const request = new UpdateSchemaScriptsDto('query', 'create', 'update', 'delete', 'change'); - schemasService.setup(x => x.putSchemaScripts(app, schema.name, It.isAny(), version)) + schemasService.setup(x => x.putScripts(app, schema.name, It.isAny(), version)) .returns(() => Observable.of(new Versioned(newVersion, {}))); schemasState.configureScripts(schema, request, modified).subscribe(); @@ -223,7 +253,7 @@ describe('SchemasState', () => { it('should add schema to snapshot when created', () => { const request = new CreateSchemaDto('newName'); - const result = new SchemaDetailsDto('id4', 'newName', {}, false, modifier, modifier, modified, modified, version, []); + const result = new SchemaDetailsDto('id4', 'newName', '', {}, false, modifier, modifier, modified, modified, version, []); schemasService.setup(x => x.postSchema(app, request, modifier, modified)) .returns(() => Observable.of(result)); diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index ec1a9ba9f..bdef4175a 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -36,6 +36,7 @@ import { SchemaPropertiesDto, SchemasService, UpdateFieldDto, + UpdateSchemaCategoryDto, UpdateSchemaDto, UpdateSchemaScriptsDto } from './../services/schemas.service'; @@ -272,6 +273,14 @@ export class SchemasState extends State { .notify(this.dialogs); } + public changeCategory(schema: SchemaDto, name: string, now?: DateTime): Observable { + return this.schemasService.putCategory(this.appName, schema.name, new UpdateSchemaCategoryDto(name), schema.version) + .do(dto => { + this.replaceSchema(changeCategory(schema, name, this.user, dto.version, now)); + }) + .notify(this.dialogs); + } + public enableField(schema: SchemaDetailsDto, field: FieldDto, now?: DateTime): Observable { return this.schemasService.enableField(this.appName, schema.name, field.fieldId, schema.version) .do(dto => { @@ -337,7 +346,7 @@ export class SchemasState extends State { } public configureScripts(schema: SchemaDetailsDto, request: UpdateSchemaScriptsDto, now?: DateTime): Observable { - return this.schemasService.putSchemaScripts(this.appName, schema.name, request, schema.version) + return this.schemasService.putScripts(this.appName, schema.name, request, schema.version) .do(dto => { this.replaceSchema(configureScripts(schema, request, this.user, dto.version, now)); }) @@ -375,6 +384,7 @@ const setPublished = (schema: SchemaDto | SchemaDetailsDto, publish: boolean, us return new SchemaDetailsDto( schema.id, schema.name, + schema.category, schema.properties, publish, schema.createdBy, user, @@ -390,6 +400,7 @@ const setPublished = (schema: SchemaDto | SchemaDetailsDto, publish: boolean, us return new SchemaDto( schema.id, schema.name, + schema.category, schema.properties, publish, schema.createdBy, user, @@ -398,10 +409,41 @@ const setPublished = (schema: SchemaDto | SchemaDetailsDto, publish: boolean, us } }; +const changeCategory = (schema: SchemaDto | SchemaDetailsDto, category: string, user: string, version: Version, now?: DateTime) => { + if (Types.is(schema, SchemaDetailsDto)) { + return new SchemaDetailsDto( + schema.id, + schema.name, + category, + schema.properties, + schema.isPublished, + schema.createdBy, user, + schema.created, now || DateTime.now(), + version, + schema.fields, + schema.scriptQuery, + schema.scriptCreate, + schema.scriptUpdate, + schema.scriptDelete, + schema.scriptChange); + } else { + return new SchemaDto( + schema.id, + schema.name, + category, + schema.properties, + schema.isPublished, + schema.createdBy, user, + schema.created, now || DateTime.now(), + version); + } +}; + const configureScripts = (schema: SchemaDetailsDto, scripts: UpdateSchemaScriptsDto, user: string, version: Version, now?: DateTime) => new SchemaDetailsDto( schema.id, schema.name, + schema.category, schema.properties, schema.isPublished, schema.createdBy, user, @@ -418,6 +460,7 @@ const updateProperties = (schema: SchemaDetailsDto, properties: SchemaProperties new SchemaDetailsDto( schema.id, schema.name, + schema.category, properties, schema.isPublished, schema.createdBy, user, @@ -434,6 +477,7 @@ const addField = (schema: SchemaDetailsDto, field: FieldDto, user: string, versi new SchemaDetailsDto( schema.id, schema.name, + schema.category, schema.properties, schema.isPublished, schema.createdBy, user, @@ -450,6 +494,7 @@ const updateField = (schema: SchemaDetailsDto, field: FieldDto, user: string, ve new SchemaDetailsDto( schema.id, schema.name, + schema.category, schema.properties, schema.isPublished, schema.createdBy, user, @@ -466,6 +511,7 @@ const replaceFields = (schema: SchemaDetailsDto, fields: FieldDto[], user: strin new SchemaDetailsDto( schema.id, schema.name, + schema.category, schema.properties, schema.isPublished, schema.createdBy, user, @@ -482,6 +528,7 @@ const removeField = (schema: SchemaDetailsDto, field: FieldDto, user: string, ve new SchemaDetailsDto( schema.id, schema.name, + schema.category, schema.properties, schema.isPublished, schema.createdBy, user, diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs index 1f2bd3233..7f723fa68 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/GuardSchemaTests.cs @@ -186,6 +186,14 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards GuardSchema.CanReorder(schema_0, command); } + [Fact] + public void CanChangeCategory_should_not_throw_exception() + { + var command = new ChangeCategory(); + + GuardSchema.CanChangeCategory(schema_0, command); + } + [Fact] public void CanDelete_should_not_throw_exception() { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs index 2372d527e..f45e200c1 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs @@ -211,6 +211,25 @@ namespace Squidex.Domain.Apps.Entities.Schemas ); } + [Fact] + public async Task ChangeCategory_should_create_events_and_update_state() + { + var command = new ChangeCategory { Name = "my-category" }; + + await ExecuteCreateAsync(); + + var result = await sut.ExecuteAsync(CreateCommand(command)); + + result.ShouldBeEquivalent(new EntitySavedResult(1)); + + Assert.Equal(command.Name, sut.Snapshot.Category); + + LastEvents + .ShouldHaveSameEvents( + CreateEvent(new SchemaCategoryChanged { Name = command.Name }) + ); + } + [Fact] public async Task Delete_should_create_events_and_update_state() {