diff --git a/frontend/app/features/content/pages/content/content-field.component.html b/frontend/app/features/content/pages/content/content-field.component.html index df7ae8cd6..5713be2ad 100644 --- a/frontend/app/features/content/pages/content/content-field.component.html +++ b/frontend/app/features/content/pages/content/content-field.component.html @@ -1,27 +1,30 @@
-
- - - - +
+
+ + + + +
-
+
@@ -31,6 +34,7 @@
-
- - +
+
+ + +
-
+
diff --git a/frontend/app/features/content/pages/content/content-field.component.scss b/frontend/app/features/content/pages/content/content-field.component.scss index 21271daf5..146576e3b 100644 --- a/frontend/app/features/content/pages/content/content-field.component.scss +++ b/frontend/app/features/content/pages/content/content-field.component.scss @@ -3,8 +3,20 @@ position: relative; } -.languages-buttons { - @include absolute(.25rem, 1.25rem); +.languages { + &-container { + position: relative; + } + + &-buttons { + @include absolute(-.5rem, 2rem); + z-index: 1000; + } + + &-buttons-compare { + @include absolute(-.5rem, 0); + z-index: 1000; + } } .col-6 { diff --git a/frontend/app/features/content/shared/forms/array-editor.component.html b/frontend/app/features/content/shared/forms/array-editor.component.html index 0b9a3d9bc..1fedf4854 100644 --- a/frontend/app/features/content/shared/forms/array-editor.component.html +++ b/frontend/app/features/content/shared/forms/array-editor.component.html @@ -8,6 +8,7 @@ cdkDrag cdkDragLockAxis="y">
diff --git a/frontend/app/features/content/shared/forms/array-section.component.ts b/frontend/app/features/content/shared/forms/array-section.component.ts index e910bf239..069ec01eb 100644 --- a/frontend/app/features/content/shared/forms/array-section.component.ts +++ b/frontend/app/features/content/shared/forms/array-section.component.ts @@ -31,6 +31,9 @@ export class ArraySectionComponent { @Input() public languages: ReadonlyArray; + @Input() + public canUnset: boolean; + @ViewChildren(FieldEditorComponent) public editors: QueryList; diff --git a/frontend/app/features/content/shared/forms/field-editor.component.html b/frontend/app/features/content/shared/forms/field-editor.component.html index b63d49642..1f7f29adc 100644 --- a/frontend/app/features/content/shared/forms/field-editor.component.html +++ b/frontend/app/features/content/shared/forms/field-editor.component.html @@ -1,4 +1,4 @@ -
+
@@ -20,6 +20,7 @@
+
+ +
+ {{field.properties.hints}} diff --git a/frontend/app/features/content/shared/forms/field-editor.component.scss b/frontend/app/features/content/shared/forms/field-editor.component.scss index 907653b31..34f89b657 100644 --- a/frontend/app/features/content/shared/forms/field-editor.component.scss +++ b/frontend/app/features/content/shared/forms/field-editor.component.scss @@ -1,4 +1,8 @@ .field { + & { + position: relative; + } + &-required { color: $color-theme-error; } @@ -10,6 +14,14 @@ } } +.unset { + @include absolute(-.5rem, 0); + + i { + font-size: 80%; + } +} + .ui { & { margin-bottom: 1rem; diff --git a/frontend/app/features/content/shared/forms/field-editor.component.ts b/frontend/app/features/content/shared/forms/field-editor.component.ts index 3b7b294fa..5c750e855 100644 --- a/frontend/app/features/content/shared/forms/field-editor.component.ts +++ b/frontend/app/features/content/shared/forms/field-editor.component.ts @@ -8,6 +8,8 @@ import { Component, ElementRef, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core'; import { AbstractControl, FormArray, FormControl } from '@angular/forms'; import { AbstractContentForm, AppLanguageDto, EditContentForm, FieldDto, MathHelper, RootFieldDto, Types } from '@app/shared'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; @Component({ selector: 'sqx-field-editor', @@ -30,12 +32,17 @@ export class FieldEditorComponent implements OnChanges { @Input() public languages: ReadonlyArray; + @Input() + public canUnset: boolean; + @Input() public displaySuffix: string; @ViewChild('editor', { static: false }) public editor: ElementRef; + public isEmpty: Observable; + public get field() { return this.formModel.field; } @@ -55,10 +62,14 @@ export class FieldEditorComponent implements OnChanges { public uniqueId = MathHelper.guid(); public ngOnChanges(changes: SimpleChanges) { - const previousControl = changes['control']?.previousValue; + if (changes['formModel']) { + const previousControl: AbstractContentForm = changes['formModel'].previousValue; - if (previousControl && Types.isFunction(previousControl['_clearChangeFns'])) { - previousControl['_clearChangeFns'](); + if (previousControl && Types.isFunction(previousControl.form['_clearChangeFns'])) { + previousControl.form['_clearChangeFns'](); + } + + this.isEmpty = this.formModel.form.valueChanges.pipe(map(x => Types.isUndefined(x) || Types.isNull(x))); } } @@ -75,4 +86,8 @@ export class FieldEditorComponent implements OnChanges { } } } + + public unset() { + this.formModel.form.setValue(undefined); + } } \ No newline at end of file diff --git a/frontend/app/framework/angular/forms/string-form-control.spec.ts b/frontend/app/framework/angular/forms/string-form-control.spec.ts deleted file mode 100644 index de38a3436..000000000 --- a/frontend/app/framework/angular/forms/string-form-control.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Squidex Headless CMS - * - * @license - * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. - */ - -import { StringFormControl } from './string-form-control'; - -describe('StringFormControl', () => { - it('should convert empty string to undefined', () => { - const formControl = new StringFormControl(); - - formControl.setValue(''); - - expect(formControl.value).toBeUndefined(); - }); - - it('should convert empty string to undefined when patching', () => { - const formControl = new StringFormControl(); - - formControl.patchValue(''); - - expect(formControl.value).toBeUndefined(); - }); -}); \ No newline at end of file diff --git a/frontend/app/framework/angular/forms/string-form-control.ts b/frontend/app/framework/angular/forms/string-form-control.ts deleted file mode 100644 index 1a0f14d25..000000000 --- a/frontend/app/framework/angular/forms/string-form-control.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Squidex Headless CMS - * - * @license - * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. - */ - -// tslint:disable: readonly-array - -import { AbstractControlOptions, AsyncValidatorFn, FormControl, ValidatorFn } from '@angular/forms'; - -export type ValueOptions = { - onlySelf?: boolean; - emitEvent?: boolean; - emitModelToViewChange?: boolean; - emitViewToModelChange?: boolean; -}; - -export class StringFormControl extends FormControl { - constructor(formState?: any, validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null, asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null) { - super(formState, validatorOrOpts, asyncValidator); - } - - public setValue(value: any, options?: ValueOptions) { - if (value === '') { - value = undefined; - } - - super.setValue(value, options); - } - - public patchValue(value: any, options?: ValueOptions) { - if (value === '') { - value = undefined; - } - - super.patchValue(value, options); - } -} \ No newline at end of file diff --git a/frontend/app/framework/angular/modals/tooltip.directive.ts b/frontend/app/framework/angular/modals/tooltip.directive.ts index 4caf9319c..beef85be5 100644 --- a/frontend/app/framework/angular/modals/tooltip.directive.ts +++ b/frontend/app/framework/angular/modals/tooltip.directive.ts @@ -47,6 +47,13 @@ export class TooltipDirective { } } + @HostListener('click') + public onClick() { + if (this.titleText) { + this.dialogs.tooltip(new Tooltip(this.element.nativeElement, null, this.titlePosition)); + } + } + private unsetAttribute() { try { this.renderer.setProperty(this.element.nativeElement, 'title', ''); diff --git a/frontend/app/framework/declarations.ts b/frontend/app/framework/declarations.ts index a58921d19..935714657 100644 --- a/frontend/app/framework/declarations.ts +++ b/frontend/app/framework/declarations.ts @@ -31,7 +31,6 @@ export * from './angular/forms/form-hint.component'; export * from './angular/forms/forms-helper'; export * from './angular/forms/indeterminate-value.directive'; export * from './angular/forms/progress-bar.component'; -export * from './angular/forms/string-form-control'; export * from './angular/forms/transform-input.directive'; export * from './angular/forms/validators'; export * from './angular/highlight.pipe'; diff --git a/frontend/app/shared/state/contents.forms.ts b/frontend/app/shared/state/contents.forms.ts index e37a0faa4..3f04076b7 100644 --- a/frontend/app/shared/state/contents.forms.ts +++ b/frontend/app/shared/state/contents.forms.ts @@ -7,8 +7,8 @@ // tslint:disable: readonly-array -import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Form, StringFormControl, Types, valueAll$ } from '@app/framework'; +import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { Form, Types, valueAll$ } from '@app/framework'; import { BehaviorSubject } from 'rxjs'; import { AppLanguageDto } from './../services/app-languages.service'; import { LanguageDto } from './../services/languages.service'; @@ -48,7 +48,7 @@ export class PatchContentForm extends Form { for (const field of this.editableFields) { const validators = FieldsValidators.create(field, this.language.isOptional); - this.form.setControl(field.name, new StringFormControl(undefined, { updateOn: FieldUpdateOn.get(field), validators })); + this.form.setControl(field.name, new FormControl(undefined, { updateOn: FieldUpdateOn.get(field), validators })); } } @@ -328,7 +328,7 @@ export class FieldForm extends AbstractContentForm { } } -export class FieldValueForm extends AbstractContentForm { +export class FieldValueForm extends AbstractContentForm { constructor(field: RootFieldDto, isOptional: boolean ) { super(field, FieldValueForm.buildControl(field, isOptional), isOptional); @@ -339,7 +339,7 @@ export class FieldValueForm extends AbstractContentForm { +export class FieldArrayItemValueForm extends AbstractContentForm { private isRequired = false; constructor(field: NestedFieldDto, parent: RootFieldDto, rules: CompiledRule[], isOptional: boolean, source?: FieldArrayItemForm @@ -517,7 +517,7 @@ export class FieldArrayItemValueForm extends AbstractContentForm