From a746d234876443cb6b494ad028d7ce9cd4a48482 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 4 Sep 2024 12:51:39 +0200 Subject: [PATCH] Add new buttons. (#1124) * Add new buttons. * Harden tests * Make screenshots. * Enable screenshots. * Fix close? --- backend/i18n/frontend_en.json | 14 ++- backend/i18n/frontend_fr.json | 8 ++ backend/i18n/frontend_it.json | 8 ++ backend/i18n/frontend_nl.json | 8 ++ backend/i18n/frontend_pt.json | 8 ++ backend/i18n/frontend_zh.json | 8 ++ backend/i18n/source/frontend_en.json | 14 ++- .../Json/ContentFieldDataConverter.cs | 6 +- .../Json/System/PolymorphicConverter.cs | 8 +- .../Json/System/StringConverter.cs | 4 +- .../Queries/Json/JsonFilterSurrogate.cs | 2 +- .../src/Squidex.Infrastructure/ThrowHelper.cs | 5 + .../src/Squidex.Web/ApiExceptionConverter.cs | 1 + .../features/apps/pages/app.component.html | 9 +- .../features/apps/pages/team.component.html | 9 +- .../pages/content/content-page.component.html | 68 ++++++++++-- .../pages/content/content-page.component.ts | 88 ++++++++------- .../references/reference-item.component.html | 3 +- .../rules/pages/rules/rule.component.html | 2 +- .../schema/fields/field-wizard.component.html | 68 +++++++++--- .../schema/fields/field-wizard.component.ts | 6 +- .../modals/dialog-renderer.component.html | 2 +- .../framework/angular/pager.component.html | 20 +++- .../framework/services/localizer.service.ts | 13 --- .../assets/asset-folder.component.html | 8 +- frontend/src/environments/environment.prod.ts | 1 - frontend/src/environments/environment.ts | 1 - frontend/src/main.ts | 4 +- tools/e2e/playwright.config.ts | 3 + tools/e2e/tests/given-app/rules.spec.ts | 3 + tools/e2e/tests/given-app/schemas.spec.ts | 2 +- tools/e2e/tests/given-schema/_setup.ts | 2 +- tools/e2e/tests/given-schema/contents.spec.ts | 104 ++++++++++++++---- 33 files changed, 379 insertions(+), 131 deletions(-) diff --git a/backend/i18n/frontend_en.json b/backend/i18n/frontend_en.json index 9b1b5462d1..4caac78856 100644 --- a/backend/i18n/frontend_en.json +++ b/backend/i18n/frontend_en.json @@ -310,6 +310,7 @@ "common.more": "More", "common.name": "Name", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "No", "common.nothingChanged": "Nothing has been changed.", "common.notSupported": "Not Supported", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} of total?", "common.pagerReload": "Click to reload view and get total number of items", + "common.pageSize": "Page Size", "common.password": "Password", "common.passwordConfirm": "Confirm Password", "common.pattern": "Pattern", @@ -328,6 +330,7 @@ "common.permissions": "Permissions", "common.prev": "Back", "common.preview": "Preview", + "common.prevPage": "Previous Page", "common.product": "Squidex Headless CMS", "common.project": "Project", "common.queryOperators.contains": "contains", @@ -359,6 +362,9 @@ "common.rules": "Rules", "common.sampleCodeLabel": "Sample Code at", "common.save": "Save", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Schema", "common.schemas": "Schemas", "common.search": "Search", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "Do you really want to remove the content?", "contents.removeConfirmTitle": "Remove content", "contents.saveAndPublish": "Save and Publish", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "at", "contents.scheduledBy": "by", "contents.scheduledTo": "to", @@ -785,9 +793,9 @@ "rules.updateFailed": "Failed to update rule. Please reload.", "rules.when": "When", "schemas.addField": "Add Field", - "schemas.addFieldAndClose": "Create and close", - "schemas.addFieldAndCreate": "Create and add field", - "schemas.addFieldAndEdit": "Create and edit field", + "schemas.addFieldAndClose": "Create", + "schemas.addFieldAndCreate": "Create & add another", + "schemas.addFieldAndEdit": "Create & edit properties", "schemas.addFieldButton": "Add Field", "schemas.addFieldFailed": "Failed to add field. Please reload.", "schemas.addNestedField": "Add Nested Field", diff --git a/backend/i18n/frontend_fr.json b/backend/i18n/frontend_fr.json index 8600471e4c..b477ad81cc 100644 --- a/backend/i18n/frontend_fr.json +++ b/backend/i18n/frontend_fr.json @@ -310,6 +310,7 @@ "common.more": "Plus", "common.name": "Nom", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "Non", "common.nothingChanged": "Rien n'a été changé.", "common.notSupported": "Non supporté", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst}-{itemLast} de {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} Du total?", "common.pagerReload": "Cliquez pour recharger la vue et obtenir le nombre total d'articles", + "common.pageSize": "Page Size", "common.password": "Mot de passe", "common.passwordConfirm": "Confirmez le mot de passe", "common.pattern": "Modèle", @@ -328,6 +330,7 @@ "common.permissions": "Autorisations", "common.prev": "Back", "common.preview": "Aperçu", + "common.prevPage": "Previous Page", "common.product": "CMS sans tête Squidex", "common.project": "Projet", "common.queryOperators.contains": "contient", @@ -359,6 +362,9 @@ "common.rules": "Règles", "common.sampleCodeLabel": "Exemple de code à", "common.save": "Sauvegarder", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Schéma", "common.schemas": "Schémas", "common.search": "Recherche", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "Voulez-vous vraiment supprimer le contenu\u00A0?", "contents.removeConfirmTitle": "Supprimer le contenu", "contents.saveAndPublish": "Enregistrer et publier", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "à", "contents.scheduledBy": "par", "contents.scheduledTo": "pour", diff --git a/backend/i18n/frontend_it.json b/backend/i18n/frontend_it.json index f565c24e0d..a63f233826 100644 --- a/backend/i18n/frontend_it.json +++ b/backend/i18n/frontend_it.json @@ -310,6 +310,7 @@ "common.more": "More", "common.name": "Nome", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "No", "common.nothingChanged": "Non è stato cambiato niente.", "common.notSupported": "Not Supported", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} of total?", "common.pagerReload": "Click to reload view and get total number of items", + "common.pageSize": "Page Size", "common.password": "Password", "common.passwordConfirm": "Conferma Password", "common.pattern": "Pattern", @@ -328,6 +330,7 @@ "common.permissions": "Permessi", "common.prev": "Back", "common.preview": "Anteprima", + "common.prevPage": "Previous Page", "common.product": "Squidex Headless CMS", "common.project": "Progetto", "common.queryOperators.contains": "contiene", @@ -359,6 +362,9 @@ "common.rules": "Regole", "common.sampleCodeLabel": "Esempio di codice per", "common.save": "Salva", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Schema", "common.schemas": "Schemi", "common.search": "Search", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "Sei sicuro di voler rimuovere il contenuto?", "contents.removeConfirmTitle": "Cancella il contenuto", "contents.saveAndPublish": "Salva e pubblica", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "alle", "contents.scheduledBy": "by", "contents.scheduledTo": "a", diff --git a/backend/i18n/frontend_nl.json b/backend/i18n/frontend_nl.json index 097bd29d8f..f32f93344a 100644 --- a/backend/i18n/frontend_nl.json +++ b/backend/i18n/frontend_nl.json @@ -310,6 +310,7 @@ "common.more": "Meer", "common.name": "Naam", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "Nee", "common.nothingChanged": "Er is niets veranderd.", "common.notSupported": "Not Supported", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst} - {itemLast} van {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} of total?", "common.pagerReload": "Click to reload view and get total number of items", + "common.pageSize": "Page Size", "common.password": "Wachtwoord", "common.passwordConfirm": "Bevestig wachtwoord", "common.pattern": "Patroon", @@ -328,6 +330,7 @@ "common.permissions": "Rechten", "common.prev": "Back", "common.preview": "Preview", + "common.prevPage": "Previous Page", "common.product": "Squidex Headless CMS", "common.project": "Project", "common.queryOperators.contains": "bevat", @@ -359,6 +362,9 @@ "common.rules": "Regels", "common.sampleCodeLabel": "Voorbeeldcode bij", "common.save": "Opslaan", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Schema", "common.schemas": "Schema's", "common.search": "Zoeken", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "Wil je de inhoud echt verwijderen?", "contents.removeConfirmTitle": "Verwijder inhoud", "contents.saveAndPublish": "Opslaan en publiceren", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "bij", "contents.scheduledBy": "door", "contents.scheduledTo": "naar", diff --git a/backend/i18n/frontend_pt.json b/backend/i18n/frontend_pt.json index 7bad6bb148..1c0c73a187 100644 --- a/backend/i18n/frontend_pt.json +++ b/backend/i18n/frontend_pt.json @@ -310,6 +310,7 @@ "common.more": "Mais", "common.name": "Nome", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "Não", "common.nothingChanged": "Nada foi mudado.", "common.notSupported": "Não suportado", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst}-{itemLast} de {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} do total?", "common.pagerReload": "Clique para recarregar a vista e obter o número total de itens", + "common.pageSize": "Page Size", "common.password": "Password", "common.passwordConfirm": "Confirmar Password", "common.pattern": "Padrão", @@ -328,6 +330,7 @@ "common.permissions": "Permissões", "common.prev": "Back", "common.preview": "Previsualizar", + "common.prevPage": "Previous Page", "common.product": "CMS Headless Squidex", "common.project": "Projeto", "common.queryOperators.contains": "contém", @@ -359,6 +362,9 @@ "common.rules": "Regras", "common.sampleCodeLabel": "Código de amostra em", "common.save": "Salvar", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Esquema", "common.schemas": "Esquemas", "common.search": "Pesquisar", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "Quer mesmo remover o conteúdo?", "contents.removeConfirmTitle": "Remover conteúdo", "contents.saveAndPublish": "Salvar e Publicar", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "em", "contents.scheduledBy": "por", "contents.scheduledTo": "Para", diff --git a/backend/i18n/frontend_zh.json b/backend/i18n/frontend_zh.json index 2e1004ecbf..a168e96305 100644 --- a/backend/i18n/frontend_zh.json +++ b/backend/i18n/frontend_zh.json @@ -310,6 +310,7 @@ "common.more": "More", "common.name": "名称", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "不", "common.nothingChanged": "什么都没有改变。", "common.notSupported": "Not Supported", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst}-{itemLast} 的 {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} of total?", "common.pagerReload": "Click to reload view and get total number of items", + "common.pageSize": "Page Size", "common.password": "密码", "common.passwordConfirm": "确认密码", "common.pattern": "模式", @@ -328,6 +330,7 @@ "common.permissions": "权限", "common.prev": "Back", "common.preview": "预览", + "common.prevPage": "Previous Page", "common.product": "Squidex Headless CMS", "common.project": "项目", "common.queryOperators.contains": "包含", @@ -359,6 +362,9 @@ "common.rules": "规则", "common.sampleCodeLabel": "示例代码在", "common.save": "保存", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Schema", "common.schemas": "Schemas", "common.search": "搜索", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "您真的要删除内容吗?", "contents.removeConfirmTitle": "删除内容", "contents.saveAndPublish": "保存并发布", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "at", "contents.scheduledBy": "by", "contents.scheduledTo": "to", diff --git a/backend/i18n/source/frontend_en.json b/backend/i18n/source/frontend_en.json index 9b1b5462d1..4caac78856 100644 --- a/backend/i18n/source/frontend_en.json +++ b/backend/i18n/source/frontend_en.json @@ -310,6 +310,7 @@ "common.more": "More", "common.name": "Name", "common.next": "Continue", + "common.nextPage": "Next Page", "common.no": "No", "common.nothingChanged": "Nothing has been changed.", "common.notSupported": "Not Supported", @@ -320,6 +321,7 @@ "common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}", "common.pagerInfoNoTotal": "{itemFirst}-{itemLast} of total?", "common.pagerReload": "Click to reload view and get total number of items", + "common.pageSize": "Page Size", "common.password": "Password", "common.passwordConfirm": "Confirm Password", "common.pattern": "Pattern", @@ -328,6 +330,7 @@ "common.permissions": "Permissions", "common.prev": "Back", "common.preview": "Preview", + "common.prevPage": "Previous Page", "common.product": "Squidex Headless CMS", "common.project": "Project", "common.queryOperators.contains": "contains", @@ -359,6 +362,9 @@ "common.rules": "Rules", "common.sampleCodeLabel": "Sample Code at", "common.save": "Save", + "common.saveAdd": "Save & add another", + "common.saveClose": "Save & close", + "common.saveEdit": "Save & editor", "common.schema": "Schema", "common.schemas": "Schemas", "common.search": "Search", @@ -480,6 +486,8 @@ "contents.removeConfirmText": "Do you really want to remove the content?", "contents.removeConfirmTitle": "Remove content", "contents.saveAndPublish": "Save and Publish", + "contents.saveAndPublishAdd": "Save and Publish & add another", + "contents.saveAndPublishClose": "Save and Publish & close", "contents.scheduledAt": "at", "contents.scheduledBy": "by", "contents.scheduledTo": "to", @@ -785,9 +793,9 @@ "rules.updateFailed": "Failed to update rule. Please reload.", "rules.when": "When", "schemas.addField": "Add Field", - "schemas.addFieldAndClose": "Create and close", - "schemas.addFieldAndCreate": "Create and add field", - "schemas.addFieldAndEdit": "Create and edit field", + "schemas.addFieldAndClose": "Create", + "schemas.addFieldAndCreate": "Create & add another", + "schemas.addFieldAndEdit": "Create & edit properties", "schemas.addFieldButton": "Add Field", "schemas.addFieldFailed": "Failed to add field. Please reload.", "schemas.addNestedField": "Add Nested Field", diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Json/ContentFieldDataConverter.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Json/ContentFieldDataConverter.cs index cd33047a12..9fbd0df5c2 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Json/ContentFieldDataConverter.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Json/ContentFieldDataConverter.cs @@ -27,7 +27,8 @@ public sealed class ContentFieldDataConverter : JsonConverter if (!reader.Read()) { - throw new JsonException("Unexpected end when reading Object."); + ThrowHelper.JsonSystemException("Unexpected end when reading Object."); + return result; } var value = JsonSerializer.Deserialize(ref reader, options)!; @@ -48,7 +49,8 @@ public sealed class ContentFieldDataConverter : JsonConverter } } - throw new JsonException("Unexpected end when reading Object."); + ThrowHelper.JsonSystemException("Unexpected end when reading Object."); + return result; } public override void Write(Utf8JsonWriter writer, ContentFieldData value, JsonSerializerOptions options) diff --git a/backend/src/Squidex.Infrastructure/Json/System/PolymorphicConverter.cs b/backend/src/Squidex.Infrastructure/Json/System/PolymorphicConverter.cs index a268be7bb4..833290c7e6 100644 --- a/backend/src/Squidex.Infrastructure/Json/System/PolymorphicConverter.cs +++ b/backend/src/Squidex.Infrastructure/Json/System/PolymorphicConverter.cs @@ -63,7 +63,7 @@ public static Action Modifier(TypeRegistry typeRegistry) if (typeReader.TokenType != JsonTokenType.StartObject) { - throw new JsonException(); + ThrowHelper.JsonSystemException($"Expected Object, got '{reader.TokenType}'"); } while (typeReader.Read()) @@ -75,7 +75,7 @@ public static Action Modifier(TypeRegistry typeRegistry) if (typeReader.TokenType != JsonTokenType.String) { - ThrowHelper.JsonException($"Expected string discriminator value, got '{reader.TokenType}'"); + ThrowHelper.JsonSystemException($"Expected string discriminator value, got '{reader.TokenType}'"); return default!; } @@ -94,7 +94,7 @@ public static Action Modifier(TypeRegistry typeRegistry) } } - ThrowHelper.JsonException($"Object has no discriminator '{discriminatorName}'."); + ThrowHelper.JsonSystemException($"Object has no discriminator '{discriminatorName}'."); return default!; } @@ -114,7 +114,7 @@ private Type GetDiscriminatorType(string name) { if (!typeRegistry.TryGetType(name, out var type)) { - ThrowHelper.JsonException($"Object has invalid discriminator '{name}'."); + ThrowHelper.JsonSystemException($"Object has invalid discriminator '{name}'."); return default!; } diff --git a/backend/src/Squidex.Infrastructure/Json/System/StringConverter.cs b/backend/src/Squidex.Infrastructure/Json/System/StringConverter.cs index 6f286754dd..dd11efc565 100644 --- a/backend/src/Squidex.Infrastructure/Json/System/StringConverter.cs +++ b/backend/src/Squidex.Infrastructure/Json/System/StringConverter.cs @@ -43,7 +43,7 @@ public StringConverter() } catch (Exception ex) { - ThrowHelper.JsonException("Error while converting from string.", ex); + ThrowHelper.JsonSystemException("Error while converting from string.", ex); return default; } @@ -53,7 +53,7 @@ public StringConverter() return JsonSerializer.Deserialize(ref reader, optionsWithoutSelf); default: - ThrowHelper.JsonException($"Expected string or object, got {reader.TokenType}."); + ThrowHelper.JsonSystemException($"Expected string or object, got {reader.TokenType}."); return default; } } diff --git a/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterSurrogate.cs b/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterSurrogate.cs index 18d38e114a..fb495c5b26 100644 --- a/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterSurrogate.cs +++ b/backend/src/Squidex.Infrastructure/Queries/Json/JsonFilterSurrogate.cs @@ -50,7 +50,7 @@ public FilterNode ToSource() return new CompareFilter(Path, Op ?? CompareOperator.Equals, Value); } - ThrowHelper.JsonException(Errors.InvalidJsonStructure()); + ThrowHelper.JsonSystemException(Errors.InvalidJsonStructure()); return default!; } } diff --git a/backend/src/Squidex.Infrastructure/ThrowHelper.cs b/backend/src/Squidex.Infrastructure/ThrowHelper.cs index cdb42fa2e4..d36134611f 100644 --- a/backend/src/Squidex.Infrastructure/ThrowHelper.cs +++ b/backend/src/Squidex.Infrastructure/ThrowHelper.cs @@ -45,4 +45,9 @@ public static void NotSupportedException(string? message = null) { throw new NotSupportedException(message); } + + public static void JsonSystemException(string? message = null, Exception? ex = null) + { + throw new System.Text.Json.JsonException(message, ex); + } } diff --git a/backend/src/Squidex.Web/ApiExceptionConverter.cs b/backend/src/Squidex.Web/ApiExceptionConverter.cs index b611165376..43b6dac04c 100644 --- a/backend/src/Squidex.Web/ApiExceptionConverter.cs +++ b/backend/src/Squidex.Web/ApiExceptionConverter.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Security; using System.Text; +using System.Text.Json; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Squidex.Infrastructure; diff --git a/frontend/src/app/features/apps/pages/app.component.html b/frontend/src/app/features/apps/pages/app.component.html index bc1163b921..1445c3ae72 100644 --- a/frontend/src/app/features/apps/pages/app.component.html +++ b/frontend/src/app/features/apps/pages/app.component.html @@ -29,8 +29,13 @@

{{ app.displayName }}

@if (app.canLeave) { - diff --git a/frontend/src/app/features/apps/pages/team.component.html b/frontend/src/app/features/apps/pages/team.component.html index 9d4c5da167..5f7708a35d 100644 --- a/frontend/src/app/features/apps/pages/team.component.html +++ b/frontend/src/app/features/apps/pages/team.component.html @@ -7,8 +7,13 @@

{{ team.name }}

{{ "common.edit" | sqxTranslate }}
- diff --git a/frontend/src/app/features/content/pages/content/content-page.component.html b/frontend/src/app/features/content/pages/content/content-page.component.html index ab786f88f6..15b293b5dc 100644 --- a/frontend/src/app/features/content/pages/content/content-page.component.html +++ b/frontend/src/app/features/content/pages/content/content-page.component.html @@ -1,6 +1,6 @@ -
+
@@ -76,8 +76,12 @@

{{ "contents.createTitle" | sqxTranslate }}

[languages]="languages" [percents]="contentForm.translationStatus | async"> @if (content.canDelete) { - @@ -115,14 +119,60 @@

{{ "contents.createTitle" | sqxTranslate }}

[percents]="contentForm.translationStatus | async">
@if (contentsState.canCreate | async) { - + } @if (contentsState.canCreateAndPublish | async) { - + }
} diff --git a/frontend/src/app/features/content/pages/content/content-page.component.ts b/frontend/src/app/features/content/pages/content/content-page.component.ts index ab7d173b5c..0c03b2752e 100644 --- a/frontend/src/app/features/content/pages/content/content-page.component.ts +++ b/frontend/src/app/features/content/pages/content/content-page.component.ts @@ -18,6 +18,8 @@ import { ContentEditorComponent } from './editor/content-editor.component'; import { ContentInspectionComponent } from './inspecting/content-inspection.component'; import { ContentReferencesComponent } from './references/content-references.component'; +type SaveNavigationMode = 'Close' | 'Add' | 'Edit'; + @Component({ standalone: true, selector: 'sqx-content-page', @@ -64,6 +66,7 @@ export class ContentPageComponent implements CanComponentDeactivate, OnInit { private readonly subscriptions = new Subscriptions(); private readonly mutableContext: Record; private autoSaveKey!: AutoSaveKey; + private autoSaveIgnore = false; public schema!: SchemaDto; @@ -75,6 +78,8 @@ export class ContentPageComponent implements CanComponentDeactivate, OnInit { public contentVersion: Version | null = null; public contentForm!: EditContentForm; public contentFormCompare: EditContentForm | null = null; + public saveOnlyDropdown = new ModalModel(); + public savePublishDropdown = new ModalModel(); public dropdown = new ModalModel(); @@ -237,52 +242,61 @@ export class ContentPageComponent implements CanComponentDeactivate, OnInit { ); } - public saveAndPublish() { - this.saveContent(true); + public saveAndPublish(navigationMode: SaveNavigationMode) { + this.saveContent(true, navigationMode); } - public save() { - this.saveContent(false); + public saveAsDraft(navigationMode: SaveNavigationMode) { + this.saveContent(false, navigationMode); } - private saveContent(publish: boolean) { + private saveContent(publish: boolean, navigationMode: SaveNavigationMode) { const value = this.contentForm.submit(); - if (value) { - if (this.content) { - if (!this.content.canUpdate) { - return; - } + if (!value) { + this.contentForm.submitFailed('i18n:contents.contentNotValid', false); + return; + } - this.contentsState.update(this.content, value) - .subscribe({ - next: () => { - this.contentForm.submitCompleted({ noReset: true }); - }, - error: error => { - this.contentForm.submitFailed(error); - }, - }); - } else { - if (!this.canCreate(publish)) { - return; - } + if (this.content) { + if (!this.content.canUpdate) { + return; + } - this.contentsState.create(value, publish, this.contentId) - .subscribe({ - next: content => { + this.contentsState.update(this.content, value) + .subscribe({ + next: () => { + this.contentForm.submitCompleted({ noReset: true }); + }, + error: error => { + this.contentForm.submitFailed(error); + }, + }); + } else { + if (!this.canCreate(publish)) { + return; + } + + this.contentsState.create(value, publish, this.contentId) + .subscribe({ + next: content => { + if (navigationMode == 'Edit') { this.contentForm.submitCompleted({ noReset: true }); this.contentForm.load(content.data, true); this.router.navigate([content.id, 'history'], { relativeTo: this.route.parent! }); - }, - error: error => { - this.contentForm.submitFailed(error); - }, - }); - } - } else { - this.contentForm.submitFailed('i18n:contents.contentNotValid', false); + } else if (navigationMode === 'Close') { + this.autoSaveIgnore = true; + + this.router.navigate(['./'], { relativeTo: this.route.parent! }); + } else { + this.contentForm = new EditContentForm(this.languages, this.schema, this.schemasState.schemaMap, this.formContext); + } + }, + error: error => { + this.contentForm.submitFailed(error); + }, + }); } } @@ -314,9 +328,9 @@ export class ContentPageComponent implements CanComponentDeactivate, OnInit { public changeLanguage(language: AppLanguageDto) { this.language = language; - this.updateContext(); - this.localStore.set(this.languageKey(), language.iso2Code); + + this.updateContext(); } public checkPendingChangesBeforePreview() { @@ -332,7 +346,7 @@ export class ContentPageComponent implements CanComponentDeactivate, OnInit { } private checkPendingChanges(text: string) { - if (this.content && !this.content.canUpdate) { + if ((this.content && !this.content.canUpdate) || this.autoSaveIgnore) { return of(true); } diff --git a/frontend/src/app/features/content/shared/references/reference-item.component.html b/frontend/src/app/features/content/shared/references/reference-item.component.html index f1d196e1c8..e4553da504 100644 --- a/frontend/src/app/features/content/shared/references/reference-item.component.html +++ b/frontend/src/app/features/content/shared/references/reference-item.component.html @@ -48,8 +48,7 @@
- diff --git a/frontend/src/app/features/rules/pages/rules/rule.component.html b/frontend/src/app/features/rules/pages/rules/rule.component.html index 20af1d2386..b2c4739df6 100644 --- a/frontend/src/app/features/rules/pages/rules/rule.component.html +++ b/frontend/src/app/features/rules/pages/rules/rule.component.html @@ -14,8 +14,8 @@ diff --git a/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.html b/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.html index 9d07c0259c..a83928b9a3 100644 --- a/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.html +++ b/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.html @@ -88,26 +88,64 @@ @if (!editForm) {
- - - +
+ + + + + + {{ "schemas.addFieldAndCreate" | sqxTranslate }} + + + {{ "schemas.addFieldAndEdit" | sqxTranslate }} + + +
} @if (editForm) {
- - +
+ + + + + + {{ "schemas.saveFieldAndClose" | sqxTranslate }} + + +
} diff --git a/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.ts b/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.ts index ad4a095afa..c3b7e27680 100644 --- a/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.ts +++ b/frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.ts @@ -8,7 +8,7 @@ import { AsyncPipe } from '@angular/common'; import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { AddFieldForm, AppSettingsDto, ControlErrorsComponent, createProperties, EditFieldForm, FieldDto, fieldTypes, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, LanguagesState, ModalDialogComponent, RootFieldDto, SchemaDto, SchemasState, TooltipDirective, TranslatePipe, Types } from '@app/shared'; +import { AddFieldForm, AppSettingsDto, ControlErrorsComponent, createProperties, DropdownMenuComponent, EditFieldForm, FieldDto, fieldTypes, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, LanguagesState, ModalDialogComponent, ModalDirective, ModalModel, ModalPlacementDirective, RootFieldDto, SchemaDto, SchemasState, TooltipDirective, TranslatePipe, Types } from '@app/shared'; import { FieldFormComponent } from './forms/field-form.component'; const DEFAULT_FIELD = { name: '', partitioning: 'invariant', properties: createProperties('String') }; @@ -21,6 +21,7 @@ const DEFAULT_FIELD = { name: '', partitioning: 'invariant', properties: createP imports: [ AsyncPipe, ControlErrorsComponent, + DropdownMenuComponent, FieldFormComponent, FocusOnInitDirective, FormAlertComponent, @@ -28,6 +29,8 @@ const DEFAULT_FIELD = { name: '', partitioning: 'invariant', properties: createP FormHintComponent, FormsModule, ModalDialogComponent, + ModalDirective, + ModalPlacementDirective, ReactiveFormsModule, TooltipDirective, TranslatePipe, @@ -53,6 +56,7 @@ export class FieldWizardComponent implements OnInit { public field!: FieldDto; public addFieldForm = new AddFieldForm(); + public addFieldModal = new ModalModel(); public editForm?: EditFieldForm; diff --git a/frontend/src/app/framework/angular/modals/dialog-renderer.component.html b/frontend/src/app/framework/angular/modals/dialog-renderer.component.html index fd5fabf771..af6da645bd 100644 --- a/frontend/src/app/framework/angular/modals/dialog-renderer.component.html +++ b/frontend/src/app/framework/angular/modals/dialog-renderer.component.html @@ -31,7 +31,7 @@
@for (notification of snapshot.notifications; track notification) { -
+