From 55daa53ef6dca40fe23a962cafe668d2782f210f Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 15 Oct 2017 22:18:06 +0200 Subject: [PATCH] UI for tags editor --- .../content/content-field.component.html | 3 ++ .../app/features/schemas/declarations.ts | 4 ++ src/Squidex/app/features/schemas/module.ts | 8 +++- .../schemas/pages/schema/field.component.html | 6 +++ .../pages/schema/types/tags-ui.component.html | 3 ++ .../pages/schema/types/tags-ui.component.scss | 2 + .../pages/schema/types/tags-ui.component.ts | 25 ++++++++++ .../types/tags-validation.component.html | 22 +++++++++ .../types/tags-validation.component.scss | 20 ++++++++ .../schema/types/tags-validation.component.ts | 33 +++++++++++++ .../shared/services/schemas.fields.spec.ts | 23 ++++++++- .../shared/services/schemas.service.spec.ts | 14 +++++- .../app/shared/services/schemas.service.ts | 47 ++++++++++++++++++- 13 files changed, 205 insertions(+), 5 deletions(-) create mode 100644 src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html create mode 100644 src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.scss create mode 100644 src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts create mode 100644 src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.html create mode 100644 src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.scss create mode 100644 src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.ts diff --git a/src/Squidex/app/features/content/pages/content/content-field.component.html b/src/Squidex/app/features/content/pages/content/content-field.component.html index 5dabd33f2..113649272 100644 --- a/src/Squidex/app/features/content/pages/content/content-field.component.html +++ b/src/Squidex/app/features/content/pages/content/content-field.component.html @@ -98,6 +98,9 @@
+
+ +
diff --git a/src/Squidex/app/features/schemas/declarations.ts b/src/Squidex/app/features/schemas/declarations.ts index a5024eedd..5b9625739 100644 --- a/src/Squidex/app/features/schemas/declarations.ts +++ b/src/Squidex/app/features/schemas/declarations.ts @@ -21,9 +21,13 @@ export * from './pages/schema/types/references-ui.component'; export * from './pages/schema/types/references-validation.component'; export * from './pages/schema/types/string-ui.component'; export * from './pages/schema/types/string-validation.component'; +export * from './pages/schema/types/tags-ui.component'; +export * from './pages/schema/types/tags-validation.component'; + export * from './pages/schema/field.component'; export * from './pages/schema/schema-edit-form.component'; export * from './pages/schema/schema-page.component'; export * from './pages/schema/schema-scripts-form.component'; + export * from './pages/schemas/schema-form.component'; export * from './pages/schemas/schemas-page.component'; \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/module.ts b/src/Squidex/app/features/schemas/module.ts index 9cb8be7dc..7d467bc4f 100644 --- a/src/Squidex/app/features/schemas/module.ts +++ b/src/Squidex/app/features/schemas/module.ts @@ -39,7 +39,9 @@ import { SchemasPageComponent, SchemaScriptsFormComponent, StringUIComponent, - StringValidationComponent + StringValidationComponent, + TagsUIComponent, + TagsValidationComponent } from './declarations'; const routes: Routes = [ @@ -105,7 +107,9 @@ const routes: Routes = [ SchemaScriptsFormComponent, SchemasPageComponent, StringUIComponent, - StringValidationComponent + StringValidationComponent, + TagsUIComponent, + TagsValidationComponent ] }) export class SqxFeatureSchemasModule { } \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/field.component.html b/src/Squidex/app/features/schemas/pages/schema/field.component.html index 5e9a1f033..046421aa7 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/field.component.html @@ -159,6 +159,9 @@
+
+ +
@@ -188,6 +191,9 @@
+
+ +
diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html new file mode 100644 index 000000000..9a0e7afd1 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html @@ -0,0 +1,3 @@ +
+ Nothing to setup +
\ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.scss b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.scss new file mode 100644 index 000000000..fbb752506 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.scss @@ -0,0 +1,2 @@ +@import '_vars'; +@import '_mixins'; \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts new file mode 100644 index 000000000..ee57702d2 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts @@ -0,0 +1,25 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { FormGroup } from '@angular/forms'; + +import { AssetsFieldPropertiesDto } from 'shared'; + +@Component({ + selector: 'sqx-tags-ui', + styleUrls: ['tags-ui.component.scss'], + templateUrl: 'tags-ui.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TagsUIComponent { + @Input() + public editForm: FormGroup; + + @Input() + public properties: AssetsFieldPropertiesDto; +} \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.html b/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.html new file mode 100644 index 000000000..35be4c232 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.html @@ -0,0 +1,22 @@ +
+
+ + +
+ +
+
+ +
+ + +
+ + + +
+
+ +
+
+
\ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.scss b/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.scss new file mode 100644 index 000000000..2edff0687 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.scss @@ -0,0 +1,20 @@ +@import '_vars'; +@import '_mixins'; + +.minitems { + &-col { + position: relative; + } + + &-label { + @include absolute(0, -.2rem, auto, auto); + } +} + +.form-check-input { + margin: 0; +} + +.form-group { + margin-top: .5rem; +} \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.ts new file mode 100644 index 000000000..f5a6d6d96 --- /dev/null +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-validation.component.ts @@ -0,0 +1,33 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; +import { FormControl, FormGroup } from '@angular/forms'; + +import { AssetsFieldPropertiesDto } from 'shared'; + +@Component({ + selector: 'sqx-tags-validation', + styleUrls: ['tags-validation.component.scss'], + templateUrl: 'tags-validation.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TagsValidationComponent implements OnInit { + @Input() + public editForm: FormGroup; + + @Input() + public properties: AssetsFieldPropertiesDto; + + public ngOnInit() { + this.editForm.setControl('maxItems', + new FormControl(this.properties.maxItems)); + + this.editForm.setControl('minItems', + new FormControl(this.properties.minItems)); + } +} \ No newline at end of file diff --git a/src/Squidex/app/shared/services/schemas.fields.spec.ts b/src/Squidex/app/shared/services/schemas.fields.spec.ts index 45965263b..0ac71ed4e 100644 --- a/src/Squidex/app/shared/services/schemas.fields.spec.ts +++ b/src/Squidex/app/shared/services/schemas.fields.spec.ts @@ -16,7 +16,8 @@ import { JsonFieldPropertiesDto, NumberFieldPropertiesDto, ReferencesFieldPropertiesDto, - StringFieldPropertiesDto + StringFieldPropertiesDto, + TagsFieldPropertiesDto } from './../'; describe('FieldDto', () => { @@ -85,6 +86,26 @@ describe('AssetsField', () => { }); }); +describe('TagsField', () => { + const field = createField(new TagsFieldPropertiesDto(null, null, null, true, false, 1, 1)); + + it('should create validators', () => { + expect(field.createValidators(false).length).toBe(3); + }); + + it('should format to empty string if null', () => { + expect(field.formatValue(null)).toBe(''); + }); + + it('should format to asset count', () => { + expect(field.formatValue(['hello', 'squidex', 'cms'])).toBe('hello, squidex, cms'); + }); + + it('should return zero formatting if other type', () => { + expect(field.formatValue(1)).toBe(''); + }); +}); + describe('BooleanField', () => { const field = createField(new BooleanFieldPropertiesDto(null, null, null, true, false, 'Checkbox')); diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index 3c549a02a..2f8ec096e 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -386,6 +386,17 @@ describe('SchemasService', () => { properties: { fieldType: 'References' } + }, + { + fieldId: 9, + name: 'field9', + isLocked: true, + isHidden: true, + isDisabled: true, + partitioning: 'language', + properties: { + fieldType: 'Tags' + } } ], scriptQuery: '', @@ -412,7 +423,8 @@ describe('SchemasService', () => { new FieldDto(5, 'field5', true, true, true, 'language', createProperties('Json')), new FieldDto(6, 'field6', true, true, true, 'language', createProperties('Geolocation')), new FieldDto(7, 'field7', true, true, true, 'language', createProperties('Assets')), - new FieldDto(8, 'field8', true, true, true, 'language', createProperties('References')) + new FieldDto(8, 'field8', true, true, true, 'language', createProperties('References')), + new FieldDto(9, 'field9', true, true, true, 'language', createProperties('Tags')) ], '', '', diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index 0efde00d8..22c7da6b1 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -31,7 +31,8 @@ export const fieldTypes: string[] = [ 'Json', 'Number', 'References', - 'String' + 'String', + 'Tags' ]; export function createProperties(fieldType: string, values: Object | null = null): FieldPropertiesDto { @@ -62,6 +63,9 @@ export function createProperties(fieldType: string, values: Object | null = null case 'Assets': properties = new AssetsFieldPropertiesDto(null, null, null, false, false); break; + case 'Tags': + properties = new TagsFieldPropertiesDto(null, null, null, false, false); + break; default: throw 'Invalid properties type'; } @@ -607,6 +611,47 @@ export class AssetsFieldPropertiesDto extends FieldPropertiesDto { } } +export class TagsFieldPropertiesDto extends FieldPropertiesDto { + constructor(label: string | null, hints: string | null, placeholder: string | null, + isRequired: boolean, + isListField: boolean, + public readonly minItems?: number, + public readonly maxItems?: number + ) { + super('Tags', label, hints, placeholder, isRequired, isListField); + } + + public formatValue(value: any): string { + if (!value) { + return ''; + } + + if (value.length) { + return value.join(', '); + } else { + return ''; + } + } + + public createValidators(isOptional: boolean): ValidatorFn[] { + const validators: ValidatorFn[] = []; + + if (this.isRequired && !isOptional) { + validators.push(Validators.required); + } + + if (this.minItems) { + validators.push(Validators.minLength(this.minItems)); + } + + if (this.maxItems) { + validators.push(Validators.maxLength(this.maxItems)); + } + + return validators; + } +} + export class JsonFieldPropertiesDto extends FieldPropertiesDto { constructor(label: string | null, hints: string | null, placeholder: string | null, isRequired: boolean,