diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs index 7c6e647c8..f87760a38 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Linq; using Newtonsoft.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.Json.Newtonsoft; @@ -18,11 +17,11 @@ namespace Squidex.Domain.Apps.Core.Apps.Json { protected override void WriteValue(JsonWriter writer, AppPatterns value, JsonSerializer serializer) { - var json = new Dictionary(value.Count); + var json = new Dictionary(value.Count); - foreach (var (key, appPattern) in value) + foreach (var (key, pattern) in value) { - json.Add(key, new JsonAppPattern(appPattern)); + json.Add(key, pattern); } serializer.Serialize(writer, json); @@ -30,9 +29,9 @@ namespace Squidex.Domain.Apps.Core.Apps.Json protected override AppPatterns ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) { - var json = serializer.Deserialize>(reader)!; + var json = serializer.Deserialize>(reader)!; - return new AppPatterns(json.ToDictionary(x => x.Key, x => x.Value.ToPattern())); + return new AppPatterns(json); } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs deleted file mode 100644 index dfca9aa3b..000000000 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs +++ /dev/null @@ -1,38 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using Newtonsoft.Json; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Core.Apps.Json -{ - public class JsonAppPattern - { - [JsonProperty] - public string Name { get; set; } - - [JsonProperty] - public string Pattern { get; set; } - - [JsonProperty] - public string? Message { get; set; } - - public JsonAppPattern() - { - } - - public JsonAppPattern(AppPattern pattern) - { - SimpleMapper.Map(pattern, this); - } - - public AppPattern ToPattern() - { - return new AppPattern(Name, Pattern, Message); - } - } -} diff --git a/frontend/app/features/content/pages/contents/custom-view-editor.component.html b/frontend/app/features/content/pages/contents/custom-view-editor.component.html index 71d55aa29..fb4100ef9 100644 --- a/frontend/app/features/content/pages/contents/custom-view-editor.component.html +++ b/frontend/app/features/content/pages/contents/custom-view-editor.component.html @@ -15,9 +15,9 @@
- +
diff --git a/frontend/app/features/content/pages/contents/custom-view-editor.component.scss b/frontend/app/features/content/pages/contents/custom-view-editor.component.scss index 9f16730f8..cacab06be 100644 --- a/frontend/app/features/content/pages/contents/custom-view-editor.component.scss +++ b/frontend/app/features/content/pages/contents/custom-view-editor.component.scss @@ -13,7 +13,7 @@ visibility: hidden; } -.form-check { +.custom-checkbox { display: inline-block; padding-left: 2rem; padding-right: .5rem; 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 9c760a428..b2ef3fddb 100644 --- a/frontend/app/features/content/shared/forms/array-editor.component.html +++ b/frontend/app/features/content/shared/forms/array-editor.component.html @@ -24,7 +24,7 @@
-
diff --git a/frontend/app/features/settings/pages/workflows/workflow-step.component.html b/frontend/app/features/settings/pages/workflows/workflow-step.component.html index 779272ef4..294a146f4 100644 --- a/frontend/app/features/settings/pages/workflows/workflow-step.component.html +++ b/frontend/app/features/settings/pages/workflows/workflow-step.component.html @@ -1,12 +1,19 @@
-
- +
@@ -26,7 +33,11 @@
- +
@@ -47,11 +58,14 @@
-
+
- +
- +
{{ 'workflows.syntax.for' | sqxTranslate }}
- +
diff --git a/frontend/app/features/settings/pages/workflows/workflow-step.component.scss b/frontend/app/features/settings/pages/workflows/workflow-step.component.scss index 57bdbb4e9..5a84b2c16 100644 --- a/frontend/app/features/settings/pages/workflows/workflow-step.component.scss +++ b/frontend/app/features/settings/pages/workflows/workflow-step.component.scss @@ -84,9 +84,9 @@ .transition-prevent-updates { & { - line-height: 2.5rem; margin-bottom: 1rem; margin-top: .25rem; + min-height: 2.5rem; } &-to { diff --git a/frontend/app/features/settings/pages/workflows/workflow-transition.component.html b/frontend/app/features/settings/pages/workflows/workflow-transition.component.html index 48546bbb8..23040dd60 100644 --- a/frontend/app/features/settings/pages/workflows/workflow-transition.component.html +++ b/frontend/app/features/settings/pages/workflows/workflow-transition.component.html @@ -11,13 +11,25 @@ {{ 'workflows.syntax.when' | sqxTranslate }}
- +
{{ 'workflows.syntax.for' | sqxTranslate }}
- +
diff --git a/frontend/app/features/settings/pages/workflows/workflow.component.html b/frontend/app/features/settings/pages/workflows/workflow.component.html index a854574da..4f625a5c6 100644 --- a/frontend/app/features/settings/pages/workflows/workflow.component.html +++ b/frontend/app/features/settings/pages/workflows/workflow.component.html @@ -59,7 +59,10 @@
- + {{ 'workflows.workflowNameHint' | sqxTranslate }} diff --git a/frontend/app/features/settings/pages/workflows/workflows-page.component.html b/frontend/app/features/settings/pages/workflows/workflows-page.component.html index 1256e3deb..70fc6d01d 100644 --- a/frontend/app/features/settings/pages/workflows/workflows-page.component.html +++ b/frontend/app/features/settings/pages/workflows/workflows-page.component.html @@ -34,7 +34,8 @@ {{ 'workflows.empty' | sqxTranslate }}
- + diff --git a/frontend/app/framework/angular/forms/file-drop.directive.ts b/frontend/app/framework/angular/forms/file-drop.directive.ts index ad112f5ff..bcae3172e 100644 --- a/frontend/app/framework/angular/forms/file-drop.directive.ts +++ b/frontend/app/framework/angular/forms/file-drop.directive.ts @@ -6,6 +6,7 @@ */ // tslint:disable: prefer-for-of +// tslint:disable: readonly-array import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2 } from '@angular/core'; import { Types } from '@app/framework/internal'; @@ -45,18 +46,16 @@ export class FileDropDirective { } @HostListener('paste', ['$event']) - public onPaste(event: ClipboardEvent) { - if (this.noPaste) { - return; - } + public async onPaste(event: ClipboardEvent) { + if (!this.noPaste) { + this.stopEvent(event); - const files = this.getAllowedFiles(event.clipboardData); + const files = await this.getAllowedFiles(event.clipboardData); - if (files && !this.disabled) { - this.drop.emit(files); + if (files && !this.disabled) { + this.drop.emit(files); + } } - - this.stopEvent(event); } @HostListener('dragend', ['$event']) @@ -88,16 +87,15 @@ export class FileDropDirective { } @HostListener('drop', ['$event']) - public onDrop(event: DragDropEvent) { + public async onDrop(event: DragDropEvent) { if (hasFiles(event.dataTransfer)) { - const files = this.getAllowedFiles(event.dataTransfer); + this.stopDrag(event); + + const files = await this.getAllowedFiles(event.dataTransfer); if (files && !this.disabled) { this.drop.emit(files); } - - this.dragEnd(0); - this.stopEvent(event); } } @@ -106,6 +104,11 @@ export class FileDropDirective { event.stopPropagation(); } + private stopDrag(event: DragDropEvent) { + this.dragEnd(0); + this.stopEvent(event); + } + private dragStart() { this.dragCounter++; @@ -122,30 +125,20 @@ export class FileDropDirective { } } - private getAllowedFiles(dataTransfer: DataTransfer | null) { + private async getAllowedFiles(dataTransfer: DataTransfer | null) { if (!dataTransfer || !hasFiles(dataTransfer)) { return null; } - const files: File[] = []; + let files: File[] = []; - for (let i = 0; i < dataTransfer.files.length; i++) { - const file = dataTransfer.files.item(i); + for (let i = 0; i < dataTransfer.items.length; i++) { + const item = dataTransfer.items[i]; - if (file && this.isAllowedFile(file)) { - files.push(file); - } + await transferFileTree(item, files); } - if (files.length === 0) { - for (let i = 0; i < dataTransfer.items.length; i++) { - const file = dataTransfer.items[i].getAsFile(); - - if (file && this.isAllowedFile(file)) { - files.push(file); - } - } - } + files = files.filter(f => this.isAllowedFile(f)); return files.length > 0 ? files : null; } @@ -203,6 +196,62 @@ function hasFiles(dataTransfer: DataTransfer): boolean { } } +async function transferWebkitTree(item: any, files: File[]) { + if (item.isFile) { + const file = await getFilePromise(item); + + files.push(file); + } else if (item.isDirectory) { + const entries = await getFilesPromise(item); + + for (const entry of entries) { + await transferWebkitTree(entry, files); + } + } +} + +async function transferFileTree(item: DataTransferItem, files: File[]) { + if (Types.isFunction(item['webkitGetAsEntry'])) { + const webkitEntry = item.webkitGetAsEntry(); + + if (webkitEntry) { + await transferWebkitTree(webkitEntry, files); + + return; + } + } + + if (Types.isFunction(item['getAsFile'])) { + const fileItem = item.getAsFile(); + + if (fileItem) { + files.push(fileItem); + } + } +} + +function getFilesPromise(item: any): Promise> { + return new Promise((resolve, reject) => { + try { + const reader = item.createReader(); + + reader.readEntries(resolve); + } catch (ex) { + reject(ex); + } + }); +} + +function getFilePromise(item: any): Promise { + return new Promise((resolve, reject) => { + try { + item.file(resolve); + } catch (ex) { + reject(ex); + } + }); +} + interface DragDropEvent extends MouseEvent { readonly dataTransfer: DataTransfer; } \ No newline at end of file