From 35899498684f222b7bbf5f733ac64bf98198f5d6 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 19 Feb 2018 12:22:49 +0100 Subject: [PATCH] UI improved. --- .../content/content-field.component.html | 188 +++++++++--------- .../pages/content/content-field.component.ts | 24 ++- .../content/content-history.component.scss | 2 +- .../pages/content/content-page.component.ts | 44 ++-- .../shared/content-item.component.html | 4 +- .../content/shared/content-item.component.ts | 11 +- .../shared/references-editor.component.scss | 2 +- .../pages/dashboard-page.component.scss | 2 +- .../schemas/pages/schema/field.component.html | 2 +- .../pages/schema/schema-page.component.scss | 2 +- .../pages/schemas/schemas-page.component.scss | 2 +- .../pages/clients/client.component.scss | 2 +- .../angular/control-errors.component.ts | 25 ++- .../framework/angular/stars.component.scss | 1 + .../angular/tag-editor.component.scss | 2 +- .../framework/angular/toggle.component.scss | 4 +- .../shared/components/asset.component.scss | 4 +- .../shared/components/history.component.scss | 2 +- .../app/shared/services/schemas.service.ts | 3 +- src/Squidex/app/theme/_bootstrap.scss | 4 +- src/Squidex/app/theme/_forms.scss | 4 +- src/Squidex/app/theme/_lists.scss | 2 +- src/Squidex/app/theme/_static.scss | 2 +- 23 files changed, 179 insertions(+), 159 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 44784c00c..7e4a1e9f6 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 @@ -5,112 +5,106 @@ Disabled -
-
-
- -
- - - Please remember to check all languages when you see validation errors. - +
+
+
-
-
- + + Please remember to check all languages when you see validation errors. + +
-
-
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
-
- -
-
-
- -
-
-
-
-
- -
-
- -
-
- -
-
- + + +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ +
-
- +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
-
- +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
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 b3f36db2a..deca02d33 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 @@ -6,10 +6,14 @@ */ import { Component, Input, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { AbstractControl, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; -import { AppLanguageDto, FieldDto } from 'shared'; +import { + AppLanguageDto, + FieldDto, + fieldInvariant +} from 'shared'; @Component({ selector: 'sqx-content-field', @@ -29,7 +33,7 @@ export class ContentFieldComponent implements OnInit { @Input() public contentFormSubmitted: boolean; - public selectedFormControl: string; + public selectedFormControl: AbstractControl; public selectedLanguage: AppLanguageDto; constructor( @@ -39,23 +43,21 @@ export class ContentFieldComponent implements OnInit { } public ngOnInit() { - if (this.field.isDisabled) { - this.fieldForm.disable(); - } - - const masterLanguage = this.languages.find(l => l.isMaster)!; + const masterLanguage = this.languages[0]; if (this.field.isLocalizable) { - this.selectedFormControl = masterLanguage.iso2Code; + this.selectedFormControl = this.fieldForm.controls[masterLanguage.iso2Code]; } else { - this.selectedFormControl = 'iv'; + this.selectedFormControl = this.fieldForm.controls[fieldInvariant]; } this.selectedLanguage = masterLanguage; } public selectLanguage(language: AppLanguageDto) { - this.selectedFormControl = language.iso2Code; + this.selectedFormControl['_clearChangeFns'](); + + this.selectedFormControl = this.fieldForm.controls[language.iso2Code]; this.selectedLanguage = language; } diff --git a/src/Squidex/app/features/content/pages/content/content-history.component.scss b/src/Squidex/app/features/content/pages/content/content-history.component.scss index 161a7830b..9fa38efc6 100644 --- a/src/Squidex/app/features/content/pages/content/content-history.component.scss +++ b/src/Squidex/app/features/content/pages/content/content-history.component.scss @@ -28,7 +28,7 @@ &-left { min-width: 2.8rem; max-width: 2.8rem; - margin-top: .3rem; + margin-top: .25rem; } &-created { diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.ts b/src/Squidex/app/features/content/pages/content/content-page.component.ts index c67137e86..fceb55df8 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-page.component.ts @@ -25,6 +25,7 @@ import { CanComponentDeactivate, ContentDto, ContentsService, + fieldInvariant, SchemaDetailsDto, Version } from 'shared'; @@ -106,8 +107,7 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy, const routeData = allData(this.ctx.route); - this.languages = routeData.appLanguages; - + this.setupLanguages(routeData); this.setupContentForm(routeData.schema); this.ctx.route.data.map(d => d.content) @@ -171,7 +171,7 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy, this.ctx.notifyInfo('Content saved successfully.'); - this.emitContentUpdated(this.content); + this.emitContentUpdated(content); this.enableContentForm(); this.reloadContentForm(content); }, error => { @@ -226,32 +226,44 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy, if (this.schema.fields.length === 0) { this.contentForm.enable(); } else { - for (const field of this.schema.fields.filter(f => !f.isDisabled)) { - this.contentForm.controls[field.name].enable(); + for (const field of this.schema.fields) { + const fieldForm = this.contentForm.controls[field.name]; + + if (field.isDisabled) { + fieldForm.disable(); + } else { + fieldForm.enable(); + } } } } + private setupLanguages(routeData: { [name: string]: any; }) { + this.languages = routeData.appLanguages; + } + private setupContentForm(schema: SchemaDetailsDto) { this.schema = schema; const controls: { [key: string]: AbstractControl } = {}; for (const field of schema.fields) { - const group = new FormGroup({}); + const fieldForm = new FormGroup({}); if (field.isLocalizable) { for (let language of this.languages) { - group.setControl(language.iso2Code, new FormControl(undefined, field.createValidators(language.isOptional))); + fieldForm.setControl(language.iso2Code, new FormControl(undefined, field.createValidators(language.isOptional))); } } else { - group.setControl('iv', new FormControl(undefined, field.createValidators(false))); + fieldForm.setControl(fieldInvariant, new FormControl(undefined, field.createValidators(false))); } - controls[field.name] = group; + controls[field.name] = fieldForm; } this.contentForm = new FormGroup(controls); + + this.enableContentForm(); } private reloadContentForm(content: ContentDto) { @@ -263,14 +275,14 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy, if (!this.isNewMode) { for (const field of this.schema.fields) { const fieldValue = this.content.data[field.name] || {}; - const fieldForm = this.contentForm.get(field.name); + const fieldForm = this.contentForm.controls[field.name]; - if (field.partitioning === 'language') { + if (field.isLocalizable) { for (let language of this.languages) { fieldForm.controls[language.iso2Code].setValue(fieldValue[language.iso2Code]); } } else { - fieldForm.controls['iv'].setValue(fieldValue['iv'] === undefined ? null : fieldValue['iv']); + fieldForm.controls[fieldInvariant].setValue(fieldValue[fieldInvariant] === undefined ? null : fieldValue[fieldInvariant]); } } if (this.content.status === 'Archived') { @@ -279,14 +291,16 @@ export class ContentPageComponent implements CanComponentDeactivate, OnDestroy, } else { for (const field of this.schema.fields) { const defaultValue = field.defaultValue(); + if (defaultValue) { - const fieldForm = this.contentForm.get(field.name); - if (field.partitioning === 'language') { + const fieldForm = this.contentForm.controls[field.name]; + + if (field.isLocalizable) { for (let language of this.languages) { fieldForm.controls[language.iso2Code].setValue(defaultValue); } } else { - fieldForm.controls['iv'].setValue(defaultValue); + fieldForm.controls[fieldInvariant].setValue(defaultValue); } } } diff --git a/src/Squidex/app/features/content/shared/content-item.component.html b/src/Squidex/app/features/content/shared/content-item.component.html index c19c1d417..ccc5f9ba0 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.html +++ b/src/Squidex/app/features/content/shared/content-item.component.html @@ -39,8 +39,8 @@
-
- +
+
diff --git a/src/Squidex/app/features/content/shared/content-item.component.ts b/src/Squidex/app/features/content/shared/content-item.component.ts index a2fb8aea0..794b20523 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.ts +++ b/src/Squidex/app/features/content/shared/content-item.component.ts @@ -15,6 +15,7 @@ import { ContentsService, fadeAnimation, FieldDto, + fieldInvariant, ModalView, SchemaDto, Types, @@ -122,10 +123,10 @@ export class ContentItemComponent implements OnInit, OnChanges { if (field.properties['inlineEditable']) { const value = this.form.controls[field.name].value; - if (field.partitioning === 'invariant') { - request[field.name] = { iv: value }; - } else { + if (field.isLocalizable) { request[field.name] = { [this.language.iso2Code]: value }; + } else { + request[field.name] = { iv: value }; } } } @@ -176,10 +177,10 @@ export class ContentItemComponent implements OnInit, OnChanges { const contentField = this.content.data[field.name]; if (contentField) { - if (field.partitioning === 'language') { + if (field.isLocalizable) { return contentField[this.language.iso2Code]; } else { - return contentField['iv']; + return contentField[fieldInvariant]; } } diff --git a/src/Squidex/app/features/content/shared/references-editor.component.scss b/src/Squidex/app/features/content/shared/references-editor.component.scss index c7bc71e73..ae939e2d1 100644 --- a/src/Squidex/app/features/content/shared/references-editor.component.scss +++ b/src/Squidex/app/features/content/shared/references-editor.component.scss @@ -53,7 +53,7 @@ .table { & { - margin-bottom: -.3rem; + margin-bottom: -.25rem; margin-top: 1rem; } diff --git a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss index 5300cbf67..6a898a0e2 100644 --- a/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss +++ b/src/Squidex/app/features/dashboard/pages/dashboard-page.component.scss @@ -136,7 +136,7 @@ &-left { min-width: 2.8rem; max-width: 2.8rem; - margin-top: .3rem; + margin-top: .25rem; } &-created { 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 23145e1b2..1ad2a35e3 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/field.component.html @@ -6,7 +6,7 @@ {{displayName}} - localizable + localizable
diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.scss b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.scss index 3138b8b90..229c4556b 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.scss +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.scss @@ -25,7 +25,7 @@ color: $color-border-dark; font-size: .9rem; font-weight: normal; - padding: .6rem .3rem; + padding: .6rem .25rem; border: 0; background: transparent; vertical-align: baseline; diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.scss b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.scss index 7d5f586d9..7927c3637 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.scss +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.scss @@ -43,7 +43,7 @@ $button-size: calc(2.5rem - 2px); @include truncate; display: inline-block; background: $color-dark2-control; - padding: .1rem .3rem; + padding: .1rem .25rem; font-size: .8rem; font-weight: normal; margin-left: 10px; diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.scss b/src/Squidex/app/features/settings/pages/clients/client.component.scss index 5bfbabd3f..6dfdfcfa1 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.scss +++ b/src/Squidex/app/features/settings/pages/clients/client.component.scss @@ -23,7 +23,7 @@ $color-editor: #eceeef; display: none; font-size: .9rem; font-weight: normal; - padding: .6rem .3rem; + padding: .6rem .25rem; border: 0; background: transparent; vertical-align: baseline; diff --git a/src/Squidex/app/framework/angular/control-errors.component.ts b/src/Squidex/app/framework/angular/control-errors.component.ts index d37f51b3f..df6fa3819 100644 --- a/src/Squidex/app/framework/angular/control-errors.component.ts +++ b/src/Squidex/app/framework/angular/control-errors.component.ts @@ -41,7 +41,7 @@ export class ControlErrorsComponent implements OnChanges, OnDestroy { private originalMarkAsTouched: any; @Input() - public for: string; + public for: string | AbstractControl; @Input() public fieldName: string; @@ -61,9 +61,6 @@ export class ControlErrorsComponent implements OnChanges, OnDestroy { @Optional() @Host() private readonly formGroupDirective: FormGroupDirective, private readonly changeDetector: ChangeDetectorRef ) { - if (!this.formGroupDirective) { - throw new Error('control-errors must be used with a parent formGroup directive'); - } } public ngOnDestroy() { @@ -74,10 +71,20 @@ export class ControlErrorsComponent implements OnChanges, OnDestroy { if (this.fieldName) { this.displayFieldName = this.fieldName; } else if (this.for) { - this.displayFieldName = this.for.substr(0, 1).toUpperCase() + this.for.substr(1); + if (this.for instanceof String) { + this.displayFieldName = this.for.substr(0, 1).toUpperCase() + this.for.substr(1); + } else { + this.displayFieldName = 'field'; + } } - const control = this.formGroupDirective.form.controls[this.for]; + let control: AbstractControl | null = null; + + if (typeof this.for === 'string') { + control = this.formGroupDirective.form.controls[this.for]; + } else { + control = this.for; + } if (this.control !== control) { this.unsubscribe(); @@ -85,8 +92,6 @@ export class ControlErrorsComponent implements OnChanges, OnDestroy { this.control = control; if (control) { - const self = this; - this.controlSubscription = Observable.merge(control.valueChanges, control.statusChanges) .subscribe(() => { @@ -95,6 +100,8 @@ export class ControlErrorsComponent implements OnChanges, OnDestroy { this.originalMarkAsTouched = this.control.markAsTouched; + const self = this; + this.control['markAsTouched'] = function () { self.originalMarkAsTouched.apply(this, arguments); @@ -119,7 +126,7 @@ export class ControlErrorsComponent implements OnChanges, OnDestroy { private createMessages() { const errors: string[] = []; - if (this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted) && this.control.errors) { + if (this.control && this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted) && this.control.errors) { for (let key in this.control.errors) { if (this.control.errors.hasOwnProperty(key)) { let message = (this.errors ? this.errors[key] : null) || DEFAULT_ERRORS[key.toLowerCase()]; diff --git a/src/Squidex/app/framework/angular/stars.component.scss b/src/Squidex/app/framework/angular/stars.component.scss index f518a8eee..1c8c6c5f1 100644 --- a/src/Squidex/app/framework/angular/stars.component.scss +++ b/src/Squidex/app/framework/angular/stars.component.scss @@ -13,6 +13,7 @@ $color-gold: #ffd700; border: 0; height: 2.4rem; line-height: 2.4rem; + vertical-align: middle; } &.disabled { diff --git a/src/Squidex/app/framework/angular/tag-editor.component.scss b/src/Squidex/app/framework/angular/tag-editor.component.scss index bdb2af557..024cc5ca8 100644 --- a/src/Squidex/app/framework/angular/tag-editor.component.scss +++ b/src/Squidex/app/framework/angular/tag-editor.component.scss @@ -12,7 +12,7 @@ display: inline-block; color: $color-dark-foreground; margin-right: .4rem; - margin-bottom: .3rem; + margin-bottom: .25rem; min-height: 1.6rem; padding: 0 .6rem; background: $color-theme-blue; diff --git a/src/Squidex/app/framework/angular/toggle.component.scss b/src/Squidex/app/framework/angular/toggle.component.scss index d3c6432b6..580f9f16c 100644 --- a/src/Squidex/app/framework/angular/toggle.component.scss +++ b/src/Squidex/app/framework/angular/toggle.component.scss @@ -2,8 +2,8 @@ @import '_vars'; $toggle-width: 2.2rem; -$toggle-height: 1.4rem; -$toggle-button-size: $toggle-height - .3rem; +$toggle-height: 1.25rem; +$toggle-button-size: $toggle-height - .25rem; .toggle { &-button { diff --git a/src/Squidex/app/shared/components/asset.component.scss b/src/Squidex/app/shared/components/asset.component.scss index 147c38474..257ec6bac 100644 --- a/src/Squidex/app/shared/components/asset.component.scss +++ b/src/Squidex/app/shared/components/asset.component.scss @@ -23,7 +23,7 @@ } @mixin asset-type { - padding: .1rem .3rem; + padding: .1rem .25rem; text-transform: uppercase; font-size: .7rem; font-weight: normal; @@ -62,7 +62,7 @@ &-text { @include absolute(40%, 0, 0, 0); text-align: center; - font-size: 1.3rem; + font-size: 1.25rem; font-weight: lighter; } } diff --git a/src/Squidex/app/shared/components/history.component.scss b/src/Squidex/app/shared/components/history.component.scss index 5e93d36ed..561b534d7 100644 --- a/src/Squidex/app/shared/components/history.component.scss +++ b/src/Squidex/app/shared/components/history.component.scss @@ -14,7 +14,7 @@ &-left { min-width: 2.8rem; max-width: 2.8rem; - margin-top: .3rem; + margin-top: .25rem; } &-created { diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index 7245b0588..1808908f1 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -22,7 +22,6 @@ import { Version, Versioned } from 'framework'; -import { partition } from 'rxjs/operator/partition'; export const fieldTypes: string[] = [ 'Assets', @@ -36,6 +35,8 @@ export const fieldTypes: string[] = [ 'Tags' ]; +export const fieldInvariant = 'iv'; + export function createProperties(fieldType: string, values: Object | null = null): FieldPropertiesDto { let properties: FieldPropertiesDto; diff --git a/src/Squidex/app/theme/_bootstrap.scss b/src/Squidex/app/theme/_bootstrap.scss index 9bf6e087a..d1eb20b2d 100644 --- a/src/Squidex/app/theme/_bootstrap.scss +++ b/src/Squidex/app/theme/_bootstrap.scss @@ -10,7 +10,7 @@ & { font-size: .9rem; font-weight: normal; - padding: .3rem .6rem; + padding: .25rem .6rem; } &-primary { @@ -421,7 +421,7 @@ a { } &-header { - @include border-radius-top(.3rem); + @include border-radius-top(.25rem); background: $color-modal-header-background; font-size: 1rem; font-weight: normal; diff --git a/src/Squidex/app/theme/_forms.scss b/src/Squidex/app/theme/_forms.scss index 2e7ae72e2..e69af6ba2 100644 --- a/src/Squidex/app/theme/_forms.scss +++ b/src/Squidex/app/theme/_forms.scss @@ -48,7 +48,7 @@ font-size: .9rem; font-weight: normal; line-height: 1.1rem; - padding: .3rem .4rem; + padding: .25rem .4rem; padding-bottom: .5rem; background: $color-theme-error; } @@ -100,7 +100,7 @@ max-height: 15rem; border: 1px solid $color-input-border; background: $color-dark-foreground; - padding: .3rem 0; + padding: .25rem 0; overflow-y: auto; } diff --git a/src/Squidex/app/theme/_lists.scss b/src/Squidex/app/theme/_lists.scss index 754191386..520d9b75f 100644 --- a/src/Squidex/app/theme/_lists.scss +++ b/src/Squidex/app/theme/_lists.scss @@ -177,7 +177,7 @@ // Spacer item between two normal items, because table rows cannot have margins. .spacer { border: 0; - height: .3rem; + height: .25rem; } } diff --git a/src/Squidex/app/theme/_static.scss b/src/Squidex/app/theme/_static.scss index 2a724c867..b5d375f7f 100644 --- a/src/Squidex/app/theme/_static.scss +++ b/src/Squidex/app/theme/_static.scss @@ -109,7 +109,7 @@ noscript { &-icon { display: inline-block; - font-size: 1.3rem; + font-size: 1.25rem; font-weight: normal; vertical-align: middle; width: 1.6rem;