From fefa20416149e3d2537fd318dc196ceb79d16942 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 13 Jul 2019 11:53:14 +0200 Subject: [PATCH] Stars view in content list. --- .../event-consumers-page.component.scss | 4 -- .../app/features/content/declarations.ts | 5 ++- src/Squidex/app/features/content/module.ts | 8 ++-- .../shared/content-item.component.html | 4 +- .../shared/content-item.component.scss | 4 -- .../content/shared/content-item.component.ts | 2 +- ...t.ts => content-value-editor.component.ts} | 4 +- .../content/shared/content-value.component.ts | 31 ++++++++++++++++ .../shared/references-dropdown.component.ts | 4 +- .../events/rule-events-page.component.scss | 4 -- .../app/shared/state/contents.forms.spec.ts | 35 +++++++++++++++++- .../app/shared/state/contents.forms.ts | 37 +++++++++++++++---- 12 files changed, 108 insertions(+), 34 deletions(-) rename src/Squidex/app/features/content/shared/{content-item-editor.component.ts => content-value-editor.component.ts} (97%) create mode 100644 src/Squidex/app/features/content/shared/content-value.component.ts diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.scss b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.scss index bee27d9b5..446243a46 100644 --- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.scss +++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.scss @@ -1,10 +1,6 @@ @import '_vars'; @import '_mixins'; -.truncate { - @include truncate; -} - .faulted { & { color: $color-theme-error; diff --git a/src/Squidex/app/features/content/declarations.ts b/src/Squidex/app/features/content/declarations.ts index 853a1a061..a8d2ba651 100644 --- a/src/Squidex/app/features/content/declarations.ts +++ b/src/Squidex/app/features/content/declarations.ts @@ -15,11 +15,12 @@ export * from './pages/contents/contents-page.component'; export * from './pages/schemas/schemas-page.component'; export * from './shared/array-editor.component'; -export * from './shared/assets-editor.component'; export * from './shared/array-item.component'; +export * from './shared/assets-editor.component'; export * from './shared/content-item.component'; -export * from './shared/content-item-editor.component'; export * from './shared/content-status.component'; +export * from './shared/content-value.component'; +export * from './shared/content-value-editor.component'; export * from './shared/contents-selector.component'; export * from './shared/due-time-selector.component'; export * from './shared/field-editor.component'; diff --git a/src/Squidex/app/features/content/module.ts b/src/Squidex/app/features/content/module.ts index 488f2a6c5..2592ae979 100644 --- a/src/Squidex/app/features/content/module.ts +++ b/src/Squidex/app/features/content/module.ts @@ -28,12 +28,13 @@ import { ContentFieldComponent, ContentHistoryPageComponent, ContentItemComponent, - ContentItemEditorComponent, ContentPageComponent, ContentsFiltersPageComponent, ContentsPageComponent, ContentsSelectorComponent, ContentStatusComponent, + ContentValueComponent, + ContentValueEditorComponent, DueTimeSelectorComponent, FieldEditorComponent, FieldLanguagesComponent, @@ -113,12 +114,13 @@ const routes: Routes = [ ContentFieldComponent, ContentHistoryPageComponent, ContentItemComponent, - ContentItemEditorComponent, ContentPageComponent, ContentsFiltersPageComponent, - ContentStatusComponent, ContentsPageComponent, ContentsSelectorComponent, + ContentStatusComponent, + ContentValueComponent, + ContentValueEditorComponent, DueTimeSelectorComponent, FieldEditorComponent, FieldLanguagesComponent, 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 87fde104e..b145733d8 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.html +++ b/src/Squidex/app/features/content/shared/content-item.component.html @@ -13,11 +13,11 @@ - + - {{values[i]}} + diff --git a/src/Squidex/app/features/content/shared/content-item.component.scss b/src/Squidex/app/features/content/shared/content-item.component.scss index 12788118e..d56691f00 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.scss +++ b/src/Squidex/app/features/content/shared/content-item.component.scss @@ -1,10 +1,6 @@ @import '_vars'; @import '_mixins'; -.truncate { - @include truncate; -} - .reference-edit { & { position: relative; 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 5f27a6cf9..8e038d7b2 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.ts +++ b/src/Squidex/app/features/content/shared/content-item.component.ts @@ -154,7 +154,7 @@ export class ContentItemComponent implements OnChanges { if (Types.isUndefined(value)) { this.values.push(''); } else { - this.values.push(FieldFormatter.format(field, value)); + this.values.push(FieldFormatter.format(field, value, true)); } if (this.patchForm) { diff --git a/src/Squidex/app/features/content/shared/content-item-editor.component.ts b/src/Squidex/app/features/content/shared/content-value-editor.component.ts similarity index 97% rename from src/Squidex/app/features/content/shared/content-item-editor.component.ts rename to src/Squidex/app/features/content/shared/content-value-editor.component.ts index cdfca6e8c..bdd6cd7b8 100644 --- a/src/Squidex/app/features/content/shared/content-item-editor.component.ts +++ b/src/Squidex/app/features/content/shared/content-value-editor.component.ts @@ -11,7 +11,7 @@ import { FormGroup } from '@angular/forms'; import { FieldDto } from '@app/shared'; @Component({ - selector: 'sqx-content-item-editor', + selector: 'sqx-content-value-editor', template: `
@@ -60,7 +60,7 @@ import { FieldDto } from '@app/shared';
`, changeDetection: ChangeDetectionStrategy.OnPush }) -export class ContentItemEditorComponent { +export class ContentValueEditorComponent { @Input() public field: FieldDto; diff --git a/src/Squidex/app/features/content/shared/content-value.component.ts b/src/Squidex/app/features/content/shared/content-value.component.ts new file mode 100644 index 000000000..d7870c8c7 --- /dev/null +++ b/src/Squidex/app/features/content/shared/content-value.component.ts @@ -0,0 +1,31 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { HtmlValue, Types } from '@app/shared'; + +@Component({ + selector: 'sqx-content-value', + template: ` + + {{value}} + + + + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ContentValueComponent { + public get isPlain() { + return !Types.is(this.value, HtmlValue); + } + + @Input() + public value: any; +} \ No newline at end of file diff --git a/src/Squidex/app/features/content/shared/references-dropdown.component.ts b/src/Squidex/app/features/content/shared/references-dropdown.component.ts index ac9025e7e..e5ca9f971 100644 --- a/src/Squidex/app/features/content/shared/references-dropdown.component.ts +++ b/src/Squidex/app/features/content/shared/references-dropdown.component.ts @@ -140,13 +140,13 @@ export class ReferencesDropdownComponent extends StatefulControlComponent { - const values: string[] = []; + const values: any[] = []; for (let field of schema.listFields) { const value = getRawValue(field, content.data, this.languageField); if (!Types.isUndefined(value)) { - values.push(FieldFormatter.format(field, value)); + values.push(FieldFormatter.format(field, value, false)); } } diff --git a/src/Squidex/app/features/rules/pages/events/rule-events-page.component.scss b/src/Squidex/app/features/rules/pages/events/rule-events-page.component.scss index 73d4911d2..0828441b3 100644 --- a/src/Squidex/app/features/rules/pages/events/rule-events-page.component.scss +++ b/src/Squidex/app/features/rules/pages/events/rule-events-page.component.scss @@ -5,10 +5,6 @@ h3 { margin-bottom: 1rem; } -.truncate { - @include truncate; -} - .event { &-stats { font-size: .8rem; diff --git a/src/Squidex/app/shared/state/contents.forms.spec.ts b/src/Squidex/app/shared/state/contents.forms.spec.ts index 935b47266..05aa3a27a 100644 --- a/src/Squidex/app/shared/state/contents.forms.spec.ts +++ b/src/Squidex/app/shared/state/contents.forms.spec.ts @@ -25,6 +25,7 @@ import { StringFieldPropertiesDto, TagsFieldPropertiesDto } from '@app/shared/internal'; +import { HtmlValue } from './contents.forms'; describe('SchemaDetailsDto', () => { it('should return label as display name', () => { @@ -227,7 +228,7 @@ describe('DateTimeField', () => { }); it('should format to input if parsing failed', () => { - expect(FieldFormatter.format(field, true)).toBe(true); + expect(FieldFormatter.format(field, true)).toBe(true); }); it('should format to date', () => { @@ -313,7 +314,37 @@ describe('NumberField', () => { }); it('should format to number', () => { - expect(FieldFormatter.format(field, 42)).toEqual(42); + expect(FieldFormatter.format(field, 42)).toEqual(42); + }); + + it('should format to stars if html allowed', () => { + const field2 = createField(new NumberFieldPropertiesDto('Stars')); + + expect(FieldFormatter.format(field2, 3)).toEqual(new HtmlValue('★ ★ ★ ')); + }); + + it('should format to short star view for many stars', () => { + const field2 = createField(new NumberFieldPropertiesDto('Stars')); + + expect(FieldFormatter.format(field2, 42)).toEqual(new HtmlValue('★ 42')); + }); + + it('should format to short star view for no stars', () => { + const field2 = createField(new NumberFieldPropertiesDto('Stars')); + + expect(FieldFormatter.format(field2, 0)).toEqual(new HtmlValue('★ 0')); + }); + + it('should format to short star view for negative stars', () => { + const field2 = createField(new NumberFieldPropertiesDto('Stars')); + + expect(FieldFormatter.format(field2, -13)).toEqual(new HtmlValue('★ -13')); + }); + + it('should not format to stars if html not allowed', () => { + const field2 = createField(new NumberFieldPropertiesDto('Stars')); + + expect(FieldFormatter.format(field2, 3, false)).toEqual(3); }); it('should return default value for default properties', () => { diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index f74cc0d4d..da3a2084c 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -37,6 +37,13 @@ import { UIFieldPropertiesDto } from './../services/schemas.types'; +export class HtmlValue { + constructor( + public readonly html: string + ) { + } +} + export class SaveQueryForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ @@ -49,21 +56,22 @@ export class SaveQueryForm extends Form { } } -export class FieldFormatter implements FieldPropertiesVisitor { +export class FieldFormatter implements FieldPropertiesVisitor { constructor( - private readonly value: any + private readonly value: any, + private readonly allowHtml: boolean ) { } - public static format(field: FieldDto, value: any) { + public static format(field: FieldDto, value: any, allowHtml = true) { if (value === null || value === undefined) { return ''; } - return field.properties.accept(new FieldFormatter(value)); + return field.properties.accept(new FieldFormatter(value, allowHtml)); } - public visitDateTime(properties: DateTimeFieldPropertiesDto): string { + public visitDateTime(properties: DateTimeFieldPropertiesDto): string | any { try { const parsed = DateTime.parseISO_UTC(this.value); @@ -121,15 +129,28 @@ export class FieldFormatter implements FieldPropertiesVisitor { return ''; } - public visitNumber(properties: NumberFieldPropertiesDto): string { + public visitNumber(properties: NumberFieldPropertiesDto): string | HtmlValue | number { + if (Types.isNumber(this.value) && properties.editor === 'Stars' && this.allowHtml) { + if (this.value <= 0 || this.value > 6) { + return new HtmlValue(`★ ${this.value}`); + } else { + let html = ''; + + for (let i = 0; i < this.value; i++) { + html += '★ '; + } + + return new HtmlValue(html); + } + } return this.value; } - public visitString(properties: StringFieldPropertiesDto): string { + public visitString(properties: StringFieldPropertiesDto): any { return this.value; } - public visitUI(properties: UIFieldPropertiesDto): string { + public visitUI(properties: UIFieldPropertiesDto): any { return this.value; } }