From de6689461756d02c638998805f4bff3f69b806ff Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 4 Feb 2019 22:24:09 +0100 Subject: [PATCH] Only show take over button when changes are different. --- .../content/content-field.component.html | 2 +- .../pages/content/content-field.component.ts | 16 +++++++++--- .../content/shared/array-item.component.ts | 4 +-- .../types/boolean-validation.component.ts | 10 ++++--- .../types/date-time-validation.component.ts | 14 +++++----- .../pages/schema/types/number-ui.component.ts | 11 ++++---- .../types/number-validation.component.ts | 5 ++-- .../pages/schema/types/string-ui.component.ts | 11 ++++---- .../types/string-validation.component.ts | 8 +++--- .../framework/angular/forms/forms-helper.ts | 26 ++++++++++++++++--- src/Squidex/app/shared/state/apps.forms.ts | 11 +++++--- src/Squidex/app/shared/state/backups.forms.ts | 10 ++++--- src/Squidex/app/shared/state/clients.forms.ts | 10 ++++--- .../app/shared/state/contributors.forms.ts | 6 ++--- src/Squidex/app/shared/state/roles.forms.ts | 9 +++---- src/Squidex/app/shared/state/schemas.forms.ts | 7 +++-- 16 files changed, 94 insertions(+), 66 deletions(-) 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 25b261171..3ea27986d 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 @@ -40,7 +40,7 @@
- diff --git a/src/Squidex/app/features/content/pages/content/content-field.component.ts b/src/Squidex/app/features/content/pages/content/content-field.component.ts index 2ba3f775b..3d5f98d80 100644 --- a/src/Squidex/app/features/content/pages/content/content-field.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-field.component.ts @@ -8,16 +8,18 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { AbstractControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; +import { combineLatest } from 'rxjs/operators'; import { AppLanguageDto, EditContentForm, fieldInvariant, + invalid$, LocalStoreService, RootFieldDto, SchemaDto, - Types + Types, + value$ } from '@app/shared'; @Component({ @@ -56,6 +58,7 @@ export class ContentFieldComponent implements OnChanges { public showAllControls = false; public isInvalid: Observable; + public isDifferent: Observable; constructor( private readonly localStore: LocalStoreService @@ -64,7 +67,14 @@ export class ContentFieldComponent implements OnChanges { public ngOnChanges(changes: SimpleChanges) { if (changes['fieldForm']) { - this.isInvalid = this.fieldForm.statusChanges.pipe(startWith(this.fieldForm.invalid), map(x => this.fieldForm.invalid)); + this.isInvalid = invalid$(this.fieldForm); + } + + if ((changes['fieldForm'] || changes['fieldFormCompare']) && this.fieldFormCompare) { + this.isDifferent = + value$(this.fieldForm).pipe( + combineLatest(value$(this.fieldFormCompare), + (lhs, rhs) => !Types.jsJsonEquals(lhs, rhs))); } if (changes['field']) { diff --git a/src/Squidex/app/features/content/shared/array-item.component.ts b/src/Squidex/app/features/content/shared/array-item.component.ts index 1dad7cc49..666e63068 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.ts +++ b/src/Squidex/app/features/content/shared/array-item.component.ts @@ -8,12 +8,12 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { AbstractControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; import { AppLanguageDto, EditContentForm, FieldDto, + invalid$, RootFieldDto } from '@app/shared'; @@ -69,7 +69,7 @@ export class ArrayItemComponent implements OnChanges { public ngOnChanges(changes: SimpleChanges) { if (changes['itemForm']) { - this.isInvalid = this.itemForm.statusChanges.pipe(startWith(this.itemForm.invalid), map(x => this.itemForm.invalid)); + this.isInvalid = invalid$(this.itemForm); } if (changes['itemForm'] || changes['field']) { diff --git a/src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.ts index 7d3d95408..0a5f6d787 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/boolean-validation.component.ts @@ -8,9 +8,12 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; -import { BooleanFieldPropertiesDto, FieldDto } from '@app/shared'; +import { + BooleanFieldPropertiesDto, + FieldDto, + hasNoValue$ +} from '@app/shared'; @Component({ selector: 'sqx-boolean-validation', @@ -37,7 +40,6 @@ export class BooleanValidationComponent implements OnInit { new FormControl(this.properties.inlineEditable)); this.showDefaultValue = - this.editForm.controls['isRequired'].valueChanges.pipe( - startWith(this.properties.isRequired), map(x => !x)); + hasNoValue$(this.editForm.controls['isRequired']); } } \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts index a6b1bda2d..fa5af2b84 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts @@ -8,9 +8,13 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; -import { DateTimeFieldPropertiesDto, FieldDto, ValidatorsEx } from '@app/shared'; +import { + DateTimeFieldPropertiesDto, + FieldDto, + hasNoValue$, + ValidatorsEx +} from '@app/shared'; @Component({ selector: 'sqx-date-time-validation', @@ -52,11 +56,9 @@ export class DateTimeValidationComponent implements OnInit { ])); this.showDefaultValues = - this.editForm.controls['isRequired'].valueChanges.pipe( - startWith(this.properties.isRequired), map(x => !x)); + hasNoValue$(this.editForm.controls['isRequired']); this.showDefaultValue = - this.editForm.controls['calculatedDefaultValue'].valueChanges.pipe( - startWith(this.properties.calculatedDefaultValue), map(x => !x)); + hasNoValue$(this.editForm.controls['calculatedDefaultValue']); } } \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.ts index 88c7949c7..6a9932444 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/number-ui.component.ts @@ -8,13 +8,14 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { FieldDto, FloatConverter, NumberFieldPropertiesDto, - ResourceOwner + ResourceOwner, + value$ } from '@app/shared'; @Component({ @@ -50,12 +51,10 @@ export class NumberUIComponent extends ResourceOwner implements OnInit { new FormControl(this.properties.inlineEditable)); this.hideAllowedValues = - this.editForm.controls['editor'].valueChanges.pipe( - startWith(this.properties.editor), map(x => !(x && (x === 'Radio' || x === 'Dropdown')))); + value$(this.editForm.controls['editor']).pipe(map(x => !(x && (x === 'Radio' || x === 'Dropdown')))); this.hideInlineEditable = - this.editForm.controls['editor'].valueChanges.pipe( - startWith(this.properties.editor), map(x => !(x && (x === 'Input' || x === 'Dropdown')))); + value$(this.editForm.controls['editor']).pipe(map(x => !(x === 'Input' || x === 'Dropdown'))); this.own( this.hideAllowedValues.subscribe(isSelection => { diff --git a/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts index 489010653..082aed6f4 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts @@ -8,10 +8,10 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; import { FieldDto, + hasNoValue$, NumberFieldPropertiesDto, RootFieldDto, Types @@ -54,7 +54,6 @@ export class NumberValidationComponent implements OnInit { new FormControl(this.properties.defaultValue)); this.showDefaultValue = - this.editForm.controls['isRequired'].valueChanges.pipe( - startWith(this.properties.isRequired), map(x => !x)); + hasNoValue$(this.editForm.controls['isRequired']); } } \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.ts index a731e095e..b2af7c388 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-ui.component.ts @@ -8,12 +8,13 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { FieldDto, ResourceOwner, - StringFieldPropertiesDto + StringFieldPropertiesDto, + value$ } from '@app/shared'; @Component({ @@ -47,12 +48,10 @@ export class StringUIComponent extends ResourceOwner implements OnInit { new FormControl(this.properties.inlineEditable)); this.hideAllowedValues = - this.editForm.controls['editor'].valueChanges.pipe( - startWith(this.properties.editor), map(x => !(x && (x === 'Radio' || x === 'Dropdown')))); + value$(this.editForm.controls['editor']).pipe(map(x => !(x && (x === 'Radio' || x === 'Dropdown')))); this.hideInlineEditable = - this.editForm.controls['editor'].valueChanges.pipe( - startWith(this.properties.editor), map(x => !(x && (x === 'Input' || x === 'Dropdown' || x === 'Slug')))); + value$(this.editForm.controls['editor']).pipe(map(x => !(x && (x === 'Input' || x === 'Dropdown' || x === 'Slug')))); this.own( this.hideAllowedValues.subscribe(isSelection => { diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts index 4cfd545e8..cd5173320 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts @@ -8,11 +8,11 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; import { AppPatternDto, FieldDto, + hasNoValue$, ImmutableArray, ModalModel, ResourceOwner, @@ -72,12 +72,10 @@ export class StringValidationComponent extends ResourceOwner implements OnDestro new FormControl(this.properties.defaultValue)); this.showDefaultValue = - this.editForm.controls['isRequired'].valueChanges.pipe( - startWith(this.properties.isRequired), map(x => !x)); + hasNoValue$(this.editForm.controls['isRequired']); this.showPatternSuggestions = - this.editForm.controls['pattern'].valueChanges.pipe( - startWith(''), map(x => !x || x.trim().length === 0)); + hasNoValue$(this.editForm.controls['pattern']); this.showPatternMessage = this.editForm.controls['pattern'].value && this.editForm.controls['pattern'].value.trim().length > 0; diff --git a/src/Squidex/app/framework/angular/forms/forms-helper.ts b/src/Squidex/app/framework/angular/forms/forms-helper.ts index d38f8125e..8597769a2 100644 --- a/src/Squidex/app/framework/angular/forms/forms-helper.ts +++ b/src/Squidex/app/framework/angular/forms/forms-helper.ts @@ -6,10 +6,12 @@ */ import { AbstractControl, FormArray, FormGroup } from '@angular/forms'; + import { Observable } from 'rxjs'; + import { map, startWith } from 'rxjs/operators'; import { Types } from '@app/framework/internal'; -export const formControls = (form: AbstractControl): AbstractControl[] => { +export function formControls(form: AbstractControl): AbstractControl[] { if (Types.is(form, FormGroup)) { return Object.values(form.controls); } else if (Types.is(form, FormArray)) { @@ -17,9 +19,25 @@ export const formControls = (form: AbstractControl): AbstractControl[] => { } else { return []; } -}; +} -export const fullValue = (form: AbstractControl): any => { +export function invalid$(form: AbstractControl): Observable { + return form.statusChanges.pipe(map(_ => form.invalid), startWith(form.invalid)); +} + +export function value$(form: AbstractControl): Observable { + return form.valueChanges.pipe(startWith(form.value)); +} + +export function hasValue$(form: AbstractControl): Observable { + return value$(form).pipe(map(v => !!v)); +} + +export function hasNoValue$(form: AbstractControl): Observable { + return value$(form).pipe(map(v => !v)); +} + +export function fullValue(form: AbstractControl): any { if (Types.is(form, FormGroup)) { const groupValue = {}; @@ -41,4 +59,4 @@ export const fullValue = (form: AbstractControl): any => { } else { return form.value; } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/Squidex/app/shared/state/apps.forms.ts b/src/Squidex/app/shared/state/apps.forms.ts index 57fb0995b..16d37f9de 100644 --- a/src/Squidex/app/shared/state/apps.forms.ts +++ b/src/Squidex/app/shared/state/apps.forms.ts @@ -6,15 +6,18 @@ */ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { map, startWith } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; -import { Form, ValidatorsEx } from '@app/framework'; +import { + Form, + ValidatorsEx, + value$ +} from '@app/framework'; const FALLBACK_NAME = 'my-app'; export class CreateAppForm extends Form { - public appName = - this.form.controls['name'].valueChanges.pipe(map(n => n || FALLBACK_NAME), startWith(FALLBACK_NAME)); + public appName = value$(this.form.controls['name']).pipe(map(v => v || FALLBACK_NAME)); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ diff --git a/src/Squidex/app/shared/state/backups.forms.ts b/src/Squidex/app/shared/state/backups.forms.ts index 475050a6c..f13acac93 100644 --- a/src/Squidex/app/shared/state/backups.forms.ts +++ b/src/Squidex/app/shared/state/backups.forms.ts @@ -6,13 +6,15 @@ */ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { map, startWith } from 'rxjs/operators'; -import { Form, ValidatorsEx } from '@app/framework'; +import { + Form, + hasValue$, + ValidatorsEx +} from '@app/framework'; export class RestoreForm extends Form { - public hasNoUrl = - this.form.controls['url'].valueChanges.pipe(startWith(null), map(x => !x)); + public hasNoUrl = hasValue$(this.form.controls['url']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ diff --git a/src/Squidex/app/shared/state/clients.forms.ts b/src/Squidex/app/shared/state/clients.forms.ts index 5c155f673..323cfc758 100644 --- a/src/Squidex/app/shared/state/clients.forms.ts +++ b/src/Squidex/app/shared/state/clients.forms.ts @@ -6,9 +6,12 @@ */ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { map, startWith } from 'rxjs/operators'; -import { Form, ValidatorsEx } from '@app/framework'; +import { + Form, + hasValue$, + ValidatorsEx +} from '@app/framework'; export class RenameClientForm extends Form { constructor(formBuilder: FormBuilder) { @@ -23,8 +26,7 @@ export class RenameClientForm extends Form { } export class AttachClientForm extends Form { - public hasNoName = - this.form.controls['name'].valueChanges.pipe(startWith(''), map(x => !x || x.length === 0)); + public hasNoName = hasValue$(this.form.controls['name']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ diff --git a/src/Squidex/app/shared/state/contributors.forms.ts b/src/Squidex/app/shared/state/contributors.forms.ts index 3680fa2e6..5459228de 100644 --- a/src/Squidex/app/shared/state/contributors.forms.ts +++ b/src/Squidex/app/shared/state/contributors.forms.ts @@ -6,13 +6,11 @@ */ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { map, startWith } from 'rxjs/operators'; -import { Form } from '@app/framework'; +import { Form, hasValue$ } from '@app/framework'; export class AssignContributorForm extends Form { - public hasNoUser = - this.form.controls['user'].valueChanges.pipe(startWith(null), map(x => !x)); + public hasNoUser = hasValue$(this.form.controls['user']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ diff --git a/src/Squidex/app/shared/state/roles.forms.ts b/src/Squidex/app/shared/state/roles.forms.ts index 71392bbd4..7505362a7 100644 --- a/src/Squidex/app/shared/state/roles.forms.ts +++ b/src/Squidex/app/shared/state/roles.forms.ts @@ -6,9 +6,8 @@ */ import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; -import { map, startWith } from 'rxjs/operators'; -import { Form } from '@app/framework'; +import { Form, hasValue$ } from '@app/framework'; export class EditPermissionsForm extends Form { constructor() { @@ -37,8 +36,7 @@ export class EditPermissionsForm extends Form { } export class AddPermissionForm extends Form { - public hasPermission = - this.form.controls['permission'].valueChanges.pipe(startWith(''), map(x => !x || x.length === 0)); + public hasPermission = hasValue$(this.form.controls['permission']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ @@ -52,8 +50,7 @@ export class AddPermissionForm extends Form { } export class AddRoleForm extends Form { - public hasNoName = - this.form.controls['name'].valueChanges.pipe(startWith(''), map(x => !x || x.length === 0)); + public hasNoName = hasValue$(this.form.controls['name']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ diff --git a/src/Squidex/app/shared/state/schemas.forms.ts b/src/Squidex/app/shared/state/schemas.forms.ts index bb935406d..6f7e52207 100644 --- a/src/Squidex/app/shared/state/schemas.forms.ts +++ b/src/Squidex/app/shared/state/schemas.forms.ts @@ -6,12 +6,12 @@ */ import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { map, startWith } from 'rxjs/operators'; import { Form, Types, - ValidatorsEx + ValidatorsEx, + value$ } from '@app/framework'; import { createProperties } from './../services/schemas.types'; @@ -28,8 +28,7 @@ export class CreateCategoryForm extends Form { export class CreateSchemaForm extends Form { public schemaName = - this.form.controls['name'].valueChanges.pipe( - map(n => n || FALLBACK_NAME), startWith(FALLBACK_NAME)); + value$(this.form.controls['name']).pipe(n => n || FALLBACK_NAME); constructor(formBuilder: FormBuilder) { super(formBuilder.group({