Browse Source

Release/design2 (#738)

* Panels design.

* Move to style guide.

* More progress

* A lot of progress.

* Design improvements.

* Simplified sass.

* Design cleanup.

* Style fixes.

* Design improvements.

* A lot of fixes.

* Remove eslint.

* Design improvements.

* Design fixes.-

* Fix title service.

* Tests fixed.

* More design fixes and shortcuts

* A lot more fixes.

* More fixes.

* More fixes.

* Fix for titles.

* More fixes.

* Load outdatedbrowser from local files.

* Style fix and remove of CDN.

* rules.actionEdit

* Do not show unset button when disabled.

* Notifo and padding fixes.

* Fix build.

* Shortcut improvements.

* Shortcut impprovements.

* Fix tests

* Dummy change.

* Fix shortcut service and more tests.
pull/739/head
Sebastian Stehle 4 years ago
committed by GitHub
parent
commit
1aac6aeef0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      README.md
  2. 68
      backend/i18n/frontend_en.json
  3. 62
      backend/i18n/frontend_it.json
  4. 62
      backend/i18n/frontend_nl.json
  5. 64
      backend/i18n/frontend_zh.json
  6. 1
      backend/i18n/source/backend_en.json
  7. 68
      backend/i18n/source/frontend_en.json
  8. 39
      backend/i18n/source/frontend_it.json
  9. 39
      backend/i18n/source/frontend_nl.json
  10. 72
      backend/i18n/source/frontend_zh.json
  11. 3
      backend/src/Squidex.Shared/Texts.it.resx
  12. 3
      backend/src/Squidex.Shared/Texts.nl.resx
  13. 3
      backend/src/Squidex.Shared/Texts.resx
  14. 3
      backend/src/Squidex.Shared/Texts.zh.resx
  15. 11
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
  16. 22
      backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs
  17. 27
      frontend/.sass-lint.yml
  18. 32
      frontend/.stylelintrc.json
  19. 8
      frontend/app-config/webpack.config.js
  20. 784
      frontend/app/_theme.html
  21. 2
      frontend/app/features/administration/administration-area.component.html
  22. 8
      frontend/app/features/administration/pages/cluster/cluster-page.component.html
  23. 6
      frontend/app/features/administration/pages/event-consumers/event-consumer.component.html
  24. 20
      frontend/app/features/administration/pages/event-consumers/event-consumers-page.component.html
  25. 8
      frontend/app/features/administration/pages/event-consumers/event-consumers-page.component.scss
  26. 30
      frontend/app/features/administration/pages/restore/restore-page.component.html
  27. 26
      frontend/app/features/administration/pages/restore/restore-page.component.scss
  28. 26
      frontend/app/features/administration/pages/users/user-page.component.html
  29. 4
      frontend/app/features/administration/pages/users/user.component.html
  30. 47
      frontend/app/features/administration/pages/users/users-page.component.html
  31. 17
      frontend/app/features/api/api-area.component.html
  32. 6
      frontend/app/features/api/pages/graphql/graphql-page.component.html
  33. 23
      frontend/app/features/api/pages/graphql/graphql-page.component.scss
  34. 2
      frontend/app/features/apps/pages/app.component.html
  35. 26
      frontend/app/features/apps/pages/apps-page.component.html
  36. 39
      frontend/app/features/apps/pages/apps-page.component.scss
  37. 14
      frontend/app/features/apps/pages/onboarding-dialog.component.scss
  38. 30
      frontend/app/features/assets/pages/asset-tags.component.html
  39. 8
      frontend/app/features/assets/pages/asset-tags.component.scss
  40. 36
      frontend/app/features/assets/pages/assets-filters-page.component.html
  41. 36
      frontend/app/features/assets/pages/assets-page.component.html
  42. 4
      frontend/app/features/assets/pages/assets-page.component.scss
  43. 12
      frontend/app/features/content/pages/comments/comments-page.component.html
  44. 6
      frontend/app/features/content/pages/content/content-event.component.html
  45. 14
      frontend/app/features/content/pages/content/content-event.component.scss
  46. 25
      frontend/app/features/content/pages/content/content-history-page.component.html
  47. 46
      frontend/app/features/content/pages/content/content-page.component.html
  48. 11
      frontend/app/features/content/pages/content/editor/content-editor.component.html
  49. 13
      frontend/app/features/content/pages/content/editor/content-editor.component.scss
  50. 18
      frontend/app/features/content/pages/content/editor/content-field.component.html
  51. 8
      frontend/app/features/content/pages/content/editor/content-field.component.scss
  52. 4
      frontend/app/features/content/pages/content/editor/content-section.component.html
  53. 39
      frontend/app/features/content/pages/content/editor/content-section.component.scss
  54. 2
      frontend/app/features/content/pages/content/editor/field-languages.component.html
  55. 2
      frontend/app/features/content/pages/content/references/content-references.component.html
  56. 52
      frontend/app/features/content/pages/contents/contents-filters-page.component.html
  57. 42
      frontend/app/features/content/pages/contents/contents-page.component.html
  58. 17
      frontend/app/features/content/pages/contents/contents-page.component.scss
  59. 12
      frontend/app/features/content/pages/contents/custom-view-editor.component.html
  60. 2
      frontend/app/features/content/pages/contents/custom-view-editor.component.scss
  61. 50
      frontend/app/features/content/pages/schemas/schemas-page.component.html
  62. 23
      frontend/app/features/content/pages/schemas/schemas-page.component.scss
  63. 20
      frontend/app/features/content/pages/sidebar/sidebar-page.component.html
  64. 2
      frontend/app/features/content/shared/content-extension.component.html
  65. 64
      frontend/app/features/content/shared/content-extension.component.ts
  66. 6
      frontend/app/features/content/shared/content-status.component.html
  67. 6
      frontend/app/features/content/shared/content-status.component.scss
  68. 12
      frontend/app/features/content/shared/due-time-selector.component.html
  69. 4
      frontend/app/features/content/shared/forms/array-editor.component.html
  70. 2
      frontend/app/features/content/shared/forms/array-editor.component.scss
  71. 4
      frontend/app/features/content/shared/forms/array-item.component.html
  72. 6
      frontend/app/features/content/shared/forms/array-item.component.scss
  73. 6
      frontend/app/features/content/shared/forms/assets-editor.component.html
  74. 36
      frontend/app/features/content/shared/forms/assets-editor.component.scss
  75. 31
      frontend/app/features/content/shared/forms/field-editor.component.html
  76. 12
      frontend/app/features/content/shared/forms/field-editor.component.scss
  77. 2
      frontend/app/features/content/shared/forms/iframe-editor.component.html
  78. 2
      frontend/app/features/content/shared/forms/iframe-editor.component.scss
  79. 169
      frontend/app/features/content/shared/forms/iframe-editor.component.ts
  80. 28
      frontend/app/features/content/shared/forms/stock-photo-editor.component.html
  81. 44
      frontend/app/features/content/shared/forms/stock-photo-editor.component.scss
  82. 2
      frontend/app/features/content/shared/list/content-list-field.component.html
  83. 10
      frontend/app/features/content/shared/list/content-value-editor.component.html
  84. 2
      frontend/app/features/content/shared/list/content-value.component.html
  85. 8
      frontend/app/features/content/shared/list/content-value.component.scss
  86. 8
      frontend/app/features/content/shared/list/content.component.html
  87. 6
      frontend/app/features/content/shared/list/content.component.scss
  88. 2
      frontend/app/features/content/shared/preview-button.component.html
  89. 20
      frontend/app/features/content/shared/references/content-creator.component.html
  90. 14
      frontend/app/features/content/shared/references/content-creator.component.scss
  91. 2
      frontend/app/features/content/shared/references/content-selector-item.component.html
  92. 18
      frontend/app/features/content/shared/references/content-selector.component.html
  93. 10
      frontend/app/features/content/shared/references/content-selector.component.scss
  94. 6
      frontend/app/features/content/shared/references/reference-item.component.html
  95. 8
      frontend/app/features/content/shared/references/reference-item.component.scss
  96. 20
      frontend/app/features/content/shared/references/references-editor.component.scss
  97. 2
      frontend/app/features/dashboard/pages/cards/api-calls-card.component.html
  98. 8
      frontend/app/features/dashboard/pages/cards/api-performance-card.component.html
  99. 8
      frontend/app/features/dashboard/pages/cards/api-traffic-card.component.html
  100. 6
      frontend/app/features/dashboard/pages/dashboard-config.component.html

2
README.md

@ -1,6 +1,6 @@
![Squidex Logo](https://raw.githubusercontent.com/Squidex/squidex/master/media/logo-wide.png "Squidex")
# What is Squidex?
# What is Squidex??
Squidex is an open source headless CMS and content management hub. In contrast to a traditional CMS Squidex provides a rich API with OData filter and Swagger definitions. It is up to you to build your UI on top of it. It can be website, a native app or just another server. We build it with ASP.NET Core and CQRS and is tested for Windows and Linux on modern browsers.

68
backend/i18n/frontend_en.json

@ -42,8 +42,6 @@
"apps.removeImageFailed": "Failed to remove app image. Please reload.",
"apps.updateFailed": "Failed to update app. Please reload.",
"apps.updateSettingsFailed": "Faield to update UI settings. Please reload.",
"apps.upgradeHintCurrent": "You are on the {plan} plan.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Drop an file to replace the app image. Use a square size.",
"apps.uploadImageButton": "Upload File",
"apps.uploadImageFailed": "Failed to upload image. Please reload.",
@ -52,19 +50,21 @@
"apps.welcomeTitle": "Hi {user}",
"appSettings.editors.deleteConfirmText": "Do you really want to remove this Editor URL?",
"appSettings.editors.deleteConfirmTitle": "Delete Editor URL",
"appSettings.editors.description": "Manage the URLs to custom editors to use them in the schema designer.",
"appSettings.editors.empty": "No Editor URL created yet.",
"appSettings.editors.title": "Custom Editors",
"appSettings.hideScheduler": "Hide dialog for scheduled publishing",
"appSettings.patterns.deleteConfirmText": "Do you really want to remove this pattern?",
"appSettings.patterns.deleteConfirmTitle": "Delete pattern",
"appSettings.patterns.description": "Patterns are reusable regular expressions for string field validation.",
"appSettings.patterns.empty": "No pattern created yet.",
"appSettings.patterns.title": "Patterns",
"appSettings.refreshTooltip": "Refresh UI Settings (CTRL + SHIFT + R)",
"appSettings.refreshTooltip": "Refresh UI Settings",
"appSettings.reloaded": "UI Settings reloaded.",
"appSettings.title": "UI Settings",
"assets.createFolder": "Create Folder",
"assets.createFolderFailed": "Failed to create asset folder. Please reload.",
"assets.createFolderTooltip": "Create new folder (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "Create new folder",
"assets.deleteConfirmText": "Do you really want to delete the asset?",
"assets.deleteConfirmTitle": "Delete asset",
"assets.deleteFailed": "Failed to delete asset. Please reload.",
@ -77,6 +77,7 @@
"assets.downloadVersion": "Download this Version",
"assets.dropToUpdate": "Drop to update",
"assets.duplicateFile": "Asset has already been uploaded.",
"assets.edit": "Edit Asset",
"assets.editor.flipHorizontally": "Flip Horizontally",
"assets.editor.flipVertically": "Flip Vertically",
"assets.editor.focusPointLabel": "Select position of focus point",
@ -95,7 +96,7 @@
"assets.metadataAdd": "Add Metadata",
"assets.moveFailed": "Failed to move asset. Please reload.",
"assets.protected": "Protected",
"assets.refreshTooltip": "Refresh Assets (CTRL + SHIFT + R)",
"assets.refreshTooltip": "Refresh Assets",
"assets.reloaded": "Assets reloaded.",
"assets.removeConfirmText": "Do you really want to remove the asset?",
"assets.removeConfirmTitle": "Remove asset",
@ -136,7 +137,7 @@
"backups.empty": "No backups created yet.",
"backups.loadFailed": "Failed to load backups.",
"backups.maximumReached": "Your have reached the maximum number of backups: 10.",
"backups.refreshTooltip": "Refresh backups (CTRL + SHIFT + R)",
"backups.refreshTooltip": "Refresh backups",
"backups.reloaded": "Backups reloaded.",
"backups.restore": "Restore Backup",
"backups.restoreFailed": "Failed to start restore.",
@ -153,6 +154,8 @@
"backups.startedLabel": "Started",
"backups.startFailed": "Failed to start backup.",
"clients.add": "Add Client",
"clients.add.description": "Add a client to give other applications access to your content.",
"clients.add.title": "Add a new Client",
"clients.addFailed": "Failed to add client. Please reload.",
"clients.allowAnonymous": "Allow anonymous access.",
"clients.allowAnonymousHint": "Allow access to the API without an access token to all resources that are configured via the role of this client. Do not give more than one client anonymous access.",
@ -191,7 +194,7 @@
"clients.deleteConfirmTitle": "Revoke client",
"clients.empty": "No client created yet.",
"clients.loadFailed": "Failed to load clients. Please reload.",
"clients.refreshTooltip": "Refresh clients (CTRL + SHIFT + R)",
"clients.refreshTooltip": "Refresh clients",
"clients.reloaded": "Clients reloaded.",
"clients.revokeFailed": "Failed to revoke client. Please reload.",
"clients.tokenFailed": "Failed to create token. Please retry.",
@ -236,6 +239,7 @@
"common.contributors": "Contributors",
"common.create": "Create",
"common.created": "Created",
"common.dashboard": "Dasboard",
"common.date": "Date",
"common.dateTimeEditor.local": "Local",
"common.dateTimeEditor.now": "Now",
@ -249,6 +253,7 @@
"common.disabled": "Disabled",
"common.displayName": "Display Name",
"common.edit": "Edit",
"common.editing": "Editing",
"common.email": "Email",
"common.enabled": "Enabled",
"common.error": "Error",
@ -290,10 +295,12 @@
"common.mapHide": "Hide map",
"common.mapShow": "Show map",
"common.message": "Message",
"common.more": "More",
"common.name": "Name",
"common.no": "No",
"common.nothingChanged": "Nothing has been changed.",
"common.noValue": "- No value -",
"common.openAPI": "Open API",
"common.or": "or",
"common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}",
"common.password": "Password",
@ -328,11 +335,11 @@
"common.rules": "Rules",
"common.sampleCodeLabel": "Sample Code at",
"common.save": "Save",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemas",
"common.search": "Search",
"common.searchGoogleMaps": "Search Google Maps",
"common.searchResults": "Search Results",
"common.security": "Security",
"common.separateByLine": "Separate by line",
"common.settings": "Settings",
"common.sidebar": "Sidebar Extension",
@ -388,7 +395,7 @@
"contents.contentTab.references": "References",
"contents.contentTab.referencing": "Referencing",
"contents.create": "New",
"contents.createContentTooltip": "New Content (CTRL + SHIFT + G)",
"contents.createContentTooltip": "New Content",
"contents.created": "Content created successfully.",
"contents.createdByFieldDescription": "The user who created the content item.",
"contents.createFailed": "Failed to create content. Please reload.",
@ -432,7 +439,7 @@
"contents.referencesLink": "Link selected contents ({count})",
"contents.referencesSelectExisting": "Select Existing",
"contents.referencesSelectSchema": "Select {schema}",
"contents.refreshTooltip": "Refresh Contents (CTRL + SHIFT + R)",
"contents.refreshTooltip": "Refresh Contents",
"contents.reloaded": "Contents reloaded.",
"contents.removeConfirmText": "Do you really want to remove the content?",
"contents.removeConfirmTitle": "Remove content",
@ -442,7 +449,7 @@
"contents.scheduledTo": "to",
"contents.schemasPageTitle": "Contents",
"contents.searchPlaceholder": "Fulltext search",
"contents.searchSchemasPlaceholder": "Search for schemas...",
"contents.searchSchemasPlaceholder": "Search",
"contents.selectionCount": "{count} items selected",
"contents.statusFieldDescription": "The status of the content item.",
"contents.statusQueries": "Status Queries",
@ -476,6 +483,7 @@
"contents.viewLatest": "View latest",
"contents.viewReset": "Reset Default View",
"contributors.add": "Add Contributor",
"contributors.add.title": "Add or invite contributor",
"contributors.addFailed": "Failed to add contributors. Please reload.",
"contributors.contributorAssigned": "A new user with the entered email address has been created and assigned as contributor.",
"contributors.contributorAssignedExisting": "User has been assigned",
@ -494,7 +502,7 @@
"contributors.importTitle": "Import contributors",
"contributors.loadFailed": "Failed to load contributors. Please reload.",
"contributors.planHint": "Your plan allows up to {maxContributors} contributors.",
"contributors.refreshTooltip": "Refresh contributors (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "Refresh contributors",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Search",
"contributors.userNotFound": "The user does not exist.",
@ -542,7 +550,7 @@
"eventConsumers.loadFailed": "Failed to load event consumers. Please reload.",
"eventConsumers.pageTitle": "Event Consumers",
"eventConsumers.position": "Position",
"eventConsumers.refreshTooltip": "Refresh event consumers (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "Refresh event consumers",
"eventConsumers.reloaded": "Event Consumers reloaded.",
"eventConsumers.resetFailed": "Failed to reset event consumer. Please reload.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
@ -554,6 +562,8 @@
"history.loadFailed": "Failed to load history. Please reload.",
"history.title": "Activity",
"languages.add": "Add Language",
"languages.add.description": "Add a new language that you want to support for your content.",
"languages.add.title": "Add a new Language",
"languages.addFailed": "Failed to add language. Please reload.",
"languages.deleteConfirmText": "Do you really want to remove the language?",
"languages.deleteConfirmTitle": "Remove language",
@ -563,7 +573,7 @@
"languages.masterHint": "Other languages fall back to the master if no fallback is defined.",
"languages.optional": "Is Optional",
"languages.optionalHint": "Values for optional languages must not be entered, even if field is required.",
"languages.refreshTooltip": "Refresh languages (CTRL + SHIFT + R)",
"languages.refreshTooltip": "Refresh languages",
"languages.reloaded": "Languages reloaded.",
"languages.updateFailed": "Failed to change language. Please reload.",
"news.headline": "What's new?",
@ -583,16 +593,21 @@
"plans.notPlanOwner": "You have not created the subscription. Therefore you cannot change the plan.",
"plans.perMonth": "Per Month",
"plans.perYear": "Per Year",
"plans.refreshTooltip": "Refresh Plans (CTRL + SHIFT + R)",
"plans.refreshTooltip": "Refresh Plans",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Selected",
"profile.title": "Profile",
"profile.userEmail": "Signed in with",
"roles.add": "Add role",
"roles.add.description": "Add a new role if you need custom permission and policies.",
"roles.add.title": "Add a custom Role",
"roles.addFailed": "Failed to add role. Please reload.",
"roles.customRoles": "Custom roles",
"roles.default.owner": "Can do everything, including deleting the app.",
"roles.default.reader": "Can only read assets and contents.",
"roles.defaults.developer": "Can use the API view, edit assets, contents, schemas, rules, workflows and appSettings.patterns.",
"roles.defaultRoles": "Default roles",
"roles.defaultRoles.hint": "Default roles cannot be deleted and are always part of your app.",
"roles.defaults.developer": "Can use the API view, edit assets, contents, schemas, rules, workflows and settings.",
"roles.defaults.editor": "Can edit assets and contents and view workflows.",
"roles.deleteConfirmText": "Delete role",
"roles.deleteConfirmTitle": "Do you really want to delete the role?",
@ -608,7 +623,7 @@
"roles.properties.hideSchemas": "Hide Schemas",
"roles.properties.hideSettings": "Hide Settings",
"roles.propertiesDescription": "Properties describe the behavior of the Management UI, but do not provide security for the API.",
"roles.refreshTooltip": "Refresh roles (CTRL + SHIFT + R)",
"roles.refreshTooltip": "Refresh roles",
"roles.reloaded": "Roles reloaded.",
"roles.revokeFailed": "Failed to revoke role. Please reload.",
"roles.roleNamePlaceholder": "Enter role name",
@ -618,7 +633,7 @@
"rules.cancelFailed": "Failed to cancel rule. Please reload.",
"rules.create": "New Rule",
"rules.createFailed": "Failed to create rule. Please reload.",
"rules.createTooltip": "New Rule (CTRL + SHIFT + G)",
"rules.createTooltip": "New Rule",
"rules.deleteConfirmText": "Do you really want to delete the rule?",
"rules.deleteConfirmTitle": "Delete rule",
"rules.deleteFailed": "Failed to delete rule. Please reload.",
@ -629,8 +644,8 @@
"rules.listPageTitle": "Rules",
"rules.loadFailed": "Failed to load Rules. Please reload.",
"rules.readMore": "Read More",
"rules.refreshEventsTooltip": "Refresh Events (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Refresh Rules (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "Refresh Events",
"rules.refreshTooltip": "Refresh Rules",
"rules.reloaded": "Rules reloaded.",
"rules.restarted": "Rule will start to run in a few seconds.",
"rules.ruleEvents.cancelFailed": "Failed to cancel rule event. Please reload.",
@ -680,7 +695,7 @@
"schemas.create": "Create Schema",
"schemas.createCategory": "Create new category...",
"schemas.createFailed": "Failed to create schema. Please reload.",
"schemas.createSchemaTooltip": "New Schema (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "New Schema",
"schemas.deleteConfirmText": "Do you really want to delete the schema?",
"schemas.deleteConfirmTitle": "Delete schema",
"schemas.deleteFailed": "Failed to delete schema. Please reload.",
@ -842,7 +857,7 @@
"schemas.schemaNameHint": "You can only use letters, numbers and dashes and not more than 40 characters.",
"schemas.schemaNameValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"schemas.schemaTagsHint": "Tags to annotate your schema for automation processes.",
"schemas.searchPlaceholder": "Search for schemas...",
"schemas.searchPlaceholder": "Search...",
"schemas.showFieldFailed": "Failed to show field. Please reload.",
"schemas.synchronized": "Schema synchronized successfully.",
"schemas.synchronizeFailed": "Failed to synchronize schema. Please reload.",
@ -911,7 +926,7 @@
"users.createFailed": "Failed to create user. Please reload.",
"users.createPageTitle": "Create User",
"users.createTitle": "New User",
"users.createTooltip": "New User (CTRL + N)",
"users.createTooltip": "New User",
"users.deleteConfirmText": "Do you really want to delete this user?",
"users.deleteConfirmTitle": "Delete user",
"users.deleteFailed": "Failed to delete user. Please reload.",
@ -924,7 +939,7 @@
"users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Lock User",
"users.passwordConfirmValidationMessage": "Passwords must be the same.",
"users.refreshTooltip": "Refresh Users (CTRL + SHIFT + R)",
"users.refreshTooltip": "Refresh Users",
"users.reloaded": "Users reloaded.",
"users.search": "Search for user",
"users.unlockFailed": "Failed to unlock user. Please reload.",
@ -944,7 +959,6 @@
"validation.min": "{field|upper} must be greater or equal to '{min}'.",
"validation.minlength": "{field|upper} must have at least {requiredlength} item(s).",
"validation.minlengthstring": "{field|upper} must have at least {requiredlength} character(s).",
"validation.notAnValidSvg": "The SVG is malicious and contains script tags.",
"validation.pattern": "{field|upper} does not match to the pattern.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is required.",
@ -954,6 +968,8 @@
"validation.validdatetime": "{field|upper} is not a valid date time.",
"validation.validvalues": "{field|upper} is not a valid value.",
"workflows.add": "Add Workflow",
"workflows.add.description": "The workflow name is only used in the UI and not shown to editors.",
"workflows.add.title": "Add a new workflow",
"workflows.addStep": "Add Step",
"workflows.createFailed": "Failed to create workflow. Please reload.",
"workflows.deleteConfirmText": "Do you really want to remove the workflow?",
@ -964,7 +980,7 @@
"workflows.notNamed": "Unnamed Workflow",
"workflows.preventUpdates": "Prevent updates",
"workflows.publishedNotRemovable": "Cannot be removed",
"workflows.refreshTooltip": "Refresh workflows (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "Refresh workflows",
"workflows.reloaded": "Workflows reloaded.",
"workflows.saved": "Workflow has been saved.",
"workflows.schemasHint": "Restrict this workflow to specific schemas or keep it empty for all schemas.",

62
backend/i18n/frontend_it.json

@ -42,8 +42,6 @@
"apps.removeImageFailed": "Non è stato possibile rimuovere l'immagine dell'app. Per favore ricarica.",
"apps.updateFailed": "Non è stato possibile aggiornare l'app. Per favore ricarica.",
"apps.updateSettingsFailed": "Faield to update UI settings. Please reload.",
"apps.upgradeHintCurrent": "Tu sei nel piano {plan}.",
"apps.upgradeHintUpgrade": "Aggiorna!",
"apps.uploadImage": "Trascina il file per sostituire l'immagine dell'app. Utilizza una dimensione quadrata.",
"apps.uploadImageButton": "Carica il File",
"apps.uploadImageFailed": "Non è stato possibile caricare l'immagine. Per favore ricarica.",
@ -52,19 +50,21 @@
"apps.welcomeTitle": "Ciao {user}",
"appSettings.editors.deleteConfirmText": "Do you really want to remove this Editor URL?",
"appSettings.editors.deleteConfirmTitle": "Delete Editor URL",
"appSettings.editors.description": "Manage the URLs to custom editors to use them in the schema designer.",
"appSettings.editors.empty": "No Editor URL created yet.",
"appSettings.editors.title": "Custom Editors",
"appSettings.hideScheduler": "Hide dialog for scheduled publishing",
"appSettings.patterns.deleteConfirmText": "Sei sicuro di voler rimuovere il pattern?",
"appSettings.patterns.deleteConfirmTitle": "Cancella il pattern",
"appSettings.patterns.description": "Patterns are reusable regular expressions for string field validation.",
"appSettings.patterns.empty": "Nessun pattern è stato ancora creato.",
"appSettings.patterns.title": "Patterns",
"appSettings.refreshTooltip": "Refresh UI Settings (CTRL + SHIFT + R)",
"appSettings.refreshTooltip": "Refresh UI Settings",
"appSettings.reloaded": "UI Settings reloaded.",
"appSettings.title": "UI Settings",
"assets.createFolder": "Crea cartella",
"assets.createFolderFailed": "Non è stato possibile creare la cartella degli asset. Per favore ricarica.",
"assets.createFolderTooltip": "Crea una nuova cartella (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "Crea una nuova cartella",
"assets.deleteConfirmText": "Sei sicuro di voler cancellare la risorsa?",
"assets.deleteConfirmTitle": "Elimina la risorsa",
"assets.deleteFailed": "Non è stato possibile cancellare la risorsa. Per favore ricarica.",
@ -77,6 +77,7 @@
"assets.downloadVersion": "Scarica questa versione",
"assets.dropToUpdate": "Trascina il file per aggiornare",
"assets.duplicateFile": "La risorsa è già stata caricata.",
"assets.edit": "Edit Asset",
"assets.editor.flipHorizontally": "Capovolgi orizzontalmente",
"assets.editor.flipVertically": "Capovolgi verticalmente",
"assets.editor.focusPointLabel": "Clicca sull'immagine per impostare il focus",
@ -95,7 +96,7 @@
"assets.metadataAdd": "Aggiungi un metadato",
"assets.moveFailed": "Non è stato possibile spostare la risorsa. Per favore ricarica.",
"assets.protected": "Protetto",
"assets.refreshTooltip": "Aggiorna le risorse (CTRL + SHIFT + R)",
"assets.refreshTooltip": "Aggiorna le risorse",
"assets.reloaded": "Risorse ricaricate.",
"assets.removeConfirmText": "Sei sicuro di voler cancellare la risorsa?",
"assets.removeConfirmTitle": "Risorsa cancellata",
@ -136,7 +137,7 @@
"backups.empty": "Nessun backup è stato ancora creato.",
"backups.loadFailed": "Non è stato possibile caricare i backup.",
"backups.maximumReached": "Hai raggiunto il numero massimo di backup: 10.",
"backups.refreshTooltip": "Aggiorna i backup (CTRL + SHIFT + R)",
"backups.refreshTooltip": "Aggiorna i backup",
"backups.reloaded": "Backup aggiornati.",
"backups.restore": "Backup ripristinato",
"backups.restoreFailed": "Non è stato possibile avviare il ripristino.",
@ -153,6 +154,8 @@
"backups.startedLabel": "Avviato",
"backups.startFailed": "Non è stato possibile avviare il backup.",
"clients.add": "Aggiungi un Client",
"clients.add.description": "Add a client to give other applications access to your content.",
"clients.add.title": "Add a new Client",
"clients.addFailed": "Non è stato possibile aggiungere un client. Per favore ricarica.",
"clients.allowAnonymous": "Consenti l'accesso anonimo.",
"clients.allowAnonymousHint": "Consenti l'accesso alle API senza token di accesso a tutte le risorse che sono configurate per il ruolo di questo client. È possibile avere un solo client impostato con accesso anonimo.",
@ -191,7 +194,7 @@
"clients.deleteConfirmTitle": "Rimuovere il client",
"clients.empty": "Nessun client ancora creato.",
"clients.loadFailed": "Non è stato possibile caricare i client. Per favore ricarica.",
"clients.refreshTooltip": "Aggiorna i client (CTRL + SHIFT + R)",
"clients.refreshTooltip": "Aggiorna i client",
"clients.reloaded": "Client ricaricati.",
"clients.revokeFailed": "Non è stato possibile rimuovere il client. Per favore ricarica.",
"clients.tokenFailed": "Non è stato possibile creare il token. Per favore riprova.",
@ -236,6 +239,7 @@
"common.contributors": "Collaboratori",
"common.create": "Crea",
"common.created": "Creato",
"common.dashboard": "Dasboard",
"common.date": "Data",
"common.dateTimeEditor.local": "Locale",
"common.dateTimeEditor.now": "Data e Ora attuale",
@ -249,6 +253,7 @@
"common.disabled": "Disabled",
"common.displayName": "Nome visualizzato",
"common.edit": "Modifica",
"common.editing": "Editing",
"common.email": "Email",
"common.enabled": "Enabled",
"common.error": "Errore",
@ -290,10 +295,12 @@
"common.mapHide": "Nascondi la mappa",
"common.mapShow": "Mostra la mappa",
"common.message": "Messaggio",
"common.more": "More",
"common.name": "Nome",
"common.no": "No",
"common.nothingChanged": "Non è stato cambiato niente.",
"common.noValue": "- Nessun valore -",
"common.openAPI": "Open API",
"common.or": "o",
"common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}",
"common.password": "Password",
@ -328,11 +335,11 @@
"common.rules": "Regole",
"common.sampleCodeLabel": "Esempio di codice per",
"common.save": "Salva",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemi",
"common.search": "Search",
"common.searchGoogleMaps": "Cerca su Google Maps",
"common.searchResults": "Risultati di ricerca",
"common.security": "Security",
"common.separateByLine": "Separato dalla linea",
"common.settings": "Impostazioni",
"common.sidebar": "Estensione della barra di navigazione laterale",
@ -388,7 +395,7 @@
"contents.contentTab.references": "Collegato a",
"contents.contentTab.referencing": "Collegato da",
"contents.create": "Nuovo",
"contents.createContentTooltip": "Nuovo contenuto (CTRL + SHIFT + G)",
"contents.createContentTooltip": "Nuovo contenuto",
"contents.created": "Contenuto creato con successo.",
"contents.createdByFieldDescription": "L'utente che ha creato l'elemento del contenuto.",
"contents.createFailed": "Non è stato possibile creare il contenuto. Per favore ricarica.",
@ -432,7 +439,7 @@
"contents.referencesLink": "Collega i contenuti selezionati ({count})",
"contents.referencesSelectExisting": "Seleziona da contenuti esistenti",
"contents.referencesSelectSchema": "Seleziona {schema}",
"contents.refreshTooltip": "Aggiorna i contenuti (CTRL + SHIFT + R)",
"contents.refreshTooltip": "Aggiorna i contenuti",
"contents.reloaded": "Contenuti aggiornati.",
"contents.removeConfirmText": "Sei sicuro di voler rimuovere il contenuto?",
"contents.removeConfirmTitle": "Cancella il contenuto",
@ -476,6 +483,7 @@
"contents.viewLatest": "Visualizza l'ultima",
"contents.viewReset": "Imposta la visualizzazione predefinita",
"contributors.add": "Aggiungi un collaboratore",
"contributors.add.title": "Add or invite contributor",
"contributors.addFailed": "Non è stato possibile aggiungere collaboratori. Per favore ricarica.",
"contributors.contributorAssigned": "Un nuovo utente, con indirizzo email, è stato creato e aggiunto come collaboratore.",
"contributors.contributorAssignedExisting": "L'utente è stato assegnato",
@ -494,7 +502,7 @@
"contributors.importTitle": "Importa collaboratori",
"contributors.loadFailed": "Non è stato possibile caricare contributors. Per favore ricarica.",
"contributors.planHint": "Il tuo piano prevede un numero massimo di {maxContributors} collaboratori.",
"contributors.refreshTooltip": "Aggiorna i collaboratori (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "Aggiorna i collaboratori",
"contributors.reloaded": "Collaboratori aggiornati.",
"contributors.search": "Cerca",
"contributors.userNotFound": "L'utente non esiste.",
@ -542,7 +550,7 @@
"eventConsumers.loadFailed": "Non è stato possibile caricare event consumers. Per favore ricarica.",
"eventConsumers.pageTitle": "Eventi degli utenti",
"eventConsumers.position": "Posizione",
"eventConsumers.refreshTooltip": "Aggiorna gli eventi degli utenti (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "Aggiorna gli eventi degli utenti",
"eventConsumers.reloaded": "Eventi degli utenti aggiornati.",
"eventConsumers.resetFailed": "Non è stato possibile ripristinare gli eventi degli utenti. Per favore ricarica.",
"eventConsumers.resetTooltip": "Ripristina gli event degli utenti",
@ -554,6 +562,8 @@
"history.loadFailed": "Non è stato possibile caricare la cronologia. Per favore ricarica.",
"history.title": "Attività",
"languages.add": "Aggiungi lingua",
"languages.add.description": "Add a new language that you want to support for your content.",
"languages.add.title": "Add a new Language",
"languages.addFailed": "Non è stato possibile aggiungere la lingua. Per favore ricarica.",
"languages.deleteConfirmText": "Sei sicuro di voler rimuovere la lingua?",
"languages.deleteConfirmTitle": "Rimuovi la lingua",
@ -563,7 +573,7 @@
"languages.masterHint": "Se non è stata impostata nessuna lingua come alternativa, le altre lingue hanno la lingua principale come alternativa.",
"languages.optional": "È Opzionale",
"languages.optionalHint": "Se sono presenti campi obbligatori questi non devono essere compilati anche per le lingue opzionali.",
"languages.refreshTooltip": "Aggiorna le lingue (CTRL + SHIFT + R)",
"languages.refreshTooltip": "Aggiorna le lingue",
"languages.reloaded": "Lingue ricaricate.",
"languages.updateFailed": "Non è stato possibile cambiare la lingua. Per favore ricarica.",
"news.headline": "Che cosa c'è di nuovo?",
@ -583,15 +593,20 @@
"plans.notPlanOwner": "Non hai creato nessun abbonamento, pertanto non è possibile cambiare il piano.",
"plans.perMonth": "Al mese",
"plans.perYear": "all'anno",
"plans.refreshTooltip": "Aggiorna i piani (CTRL + SHIFT + R)",
"plans.refreshTooltip": "Aggiorna i piani",
"plans.reloaded": "Piano aggiornati.",
"plans.selected": "Selezionato",
"profile.title": "Profilo",
"profile.userEmail": "Accesso con",
"roles.add": "Aggiungi un ruolo",
"roles.add.description": "Add a new role if you need custom permission and policies.",
"roles.add.title": "Add a custom Role",
"roles.addFailed": "Non è stato possibile aggiungere il ruolo. Per favore ricarica.",
"roles.customRoles": "Custom roles",
"roles.default.owner": "Hai come amministratore tutte le funzionalità, compreso cancellare le app.",
"roles.default.reader": "Hai un'utenza in sola lettura sia per i contenuti che per le risorse.",
"roles.defaultRoles": "Default roles",
"roles.defaultRoles.hint": "Default roles cannot be deleted and are always part of your app.",
"roles.defaults.developer": "Hai un'utenza che può visualizzare le API, modificare le risorse, i contenuti, gli schema, le regole, i workflow e i pattern.",
"roles.defaults.editor": "Hai un'utenza che può modificare le risorse, i contenuti e visualizzare i workflow.",
"roles.deleteConfirmText": "Cancella il ruolo",
@ -608,7 +623,7 @@
"roles.properties.hideSchemas": "Nascondi gli Schemi",
"roles.properties.hideSettings": "Nascondi le impostazioni",
"roles.propertiesDescription": "Le proprietà descrivono il comportamento nelle Interfacce Utente, ma non garantiscono la sicurezza per le API.",
"roles.refreshTooltip": "Aggiorna i ruoli (CTRL + SHIFT + R)",
"roles.refreshTooltip": "Aggiorna i ruoli",
"roles.reloaded": "Ruoli ricaricati.",
"roles.revokeFailed": "Non è stato possibile rimuovere il ruolo. Per favore ricarica.",
"roles.roleNamePlaceholder": "Inserisci il nome del ruolo",
@ -618,7 +633,7 @@
"rules.cancelFailed": "Non è stato possibile eliminare la regola. Per favore ricarica.",
"rules.create": "Crea un nuova Regola",
"rules.createFailed": "Non è stato possibile creare una nuova regola. Per favore ricarica.",
"rules.createTooltip": "Nuova regola (CTRL + SHIFT + G)",
"rules.createTooltip": "Nuova regola",
"rules.deleteConfirmText": "Sei sicuro di voler eliminare la regola?",
"rules.deleteConfirmTitle": "Cancella la regola",
"rules.deleteFailed": "Non è stato possibile eliminare la regola. Per favore ricarica.",
@ -629,8 +644,8 @@
"rules.listPageTitle": "Regole",
"rules.loadFailed": "Non è stato possibile caricare le regole. Per favore ricarica.",
"rules.readMore": "Leggi di più",
"rules.refreshEventsTooltip": "Aggiorna gli Eventi (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Aggiorna le Regole (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "Aggiorna gli Eventi",
"rules.refreshTooltip": "Aggiorna le Regole",
"rules.reloaded": "Regole ricaricate.",
"rules.restarted": "La Regola sarà eseguita fra pochi secondi.",
"rules.ruleEvents.cancelFailed": "Non è stato possibile cancellare l'evento della regola. Per favore ricarica.",
@ -680,7 +695,7 @@
"schemas.create": "Crea uno Schema",
"schemas.createCategory": "Crea una nuova categoria...",
"schemas.createFailed": "Non è stato possibile creare lo schema. Per favore ricarica.",
"schemas.createSchemaTooltip": "Nuovo Schema (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "Nuovo Schema",
"schemas.deleteConfirmText": "Sei sicuro di voler eliminare lo schema?",
"schemas.deleteConfirmTitle": "Cancella lo schema",
"schemas.deleteFailed": "Non è stato possibile cancellare lo schema. Per favore ricarica.",
@ -911,7 +926,7 @@
"users.createFailed": "Non è stato possibile creare l'utente. Per favore ricarica.",
"users.createPageTitle": "Crea un utente",
"users.createTitle": "Nuovo utente",
"users.createTooltip": "Nuovo utente (CTRL + N)",
"users.createTooltip": "Nuovo utente",
"users.deleteConfirmText": "Sei sicuro di voler eliminare questo utente?",
"users.deleteConfirmTitle": "Elimina utente",
"users.deleteFailed": "Non è stato possibile eliminare l'utente. Per favore ricarica.",
@ -924,7 +939,7 @@
"users.lockFailed": "Non è stato possibile bloccare l'utente. Per favore ricarica.",
"users.lockTooltip": "Utente bloccato",
"users.passwordConfirmValidationMessage": "Le password devono essere uguali.",
"users.refreshTooltip": "Aggiorna gli Utenti (CTRL + SHIFT + R)",
"users.refreshTooltip": "Aggiorna gli Utenti",
"users.reloaded": "Utenti ricaricati.",
"users.search": "Cerca l'utente",
"users.unlockFailed": "Non è stato possibile sbloccare l'utente. Per favore ricarica.",
@ -944,7 +959,6 @@
"validation.min": "{field|upper} deve essere maggiore o uguale a '{min}'.",
"validation.minlength": "{field|upper} deve avere almeno {requiredlength} elemento(i).",
"validation.minlengthstring": "{field|upper} deve avere almeno {requiredlength} carattere(i).",
"validation.notAnValidSvg": "The SVG is malicious and contains script tags.",
"validation.pattern": "{field|upper} non corrisponde al pattern.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} è obbligatorio.",
@ -954,6 +968,8 @@
"validation.validdatetime": "{field|upper} non è una data e ora valida.",
"validation.validvalues": "{field|upper} non è un valore valido.",
"workflows.add": "Aggiungi un Workflow",
"workflows.add.description": "The workflow name is only used in the UI and not shown to editors.",
"workflows.add.title": "Add a new workflow",
"workflows.addStep": "Aggiungi uno Step",
"workflows.createFailed": "Non è stato possibile creare un workflow. Per favore ricarica.",
"workflows.deleteConfirmText": "Sei sicuro di voler eliminare il workflow?",
@ -964,7 +980,7 @@
"workflows.notNamed": "Workflow senza nome",
"workflows.preventUpdates": "Impedisci gli aggiornamenti",
"workflows.publishedNotRemovable": "Non è possibile rimuoverlo",
"workflows.refreshTooltip": "Aggiorna i workflow (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "Aggiorna i workflow",
"workflows.reloaded": "Workflow ricaricati.",
"workflows.saved": "Il Workflow è stato salvato.",
"workflows.schemasHint": "Limita questo workflow ad uno schema specifico, o lascialo bianco per applicarlo a tutti gli schemi.",

62
backend/i18n/frontend_nl.json

@ -42,8 +42,6 @@
"apps.removeImageFailed": "Verwijderen van app-afbeelding is mislukt. Laad opnieuw.",
"apps.updateFailed": "Update app mislukt. Laad opnieuw.",
"apps.updateSettingsFailed": "Faield to update UI settings. Please reload.",
"apps.upgradeHintCurrent": "Je zit in het plan {plan}.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Zet een bestand neer om de app-afbeelding te vervangen. Gebruik een vierkant formaat.",
"apps.uploadImageButton": "Upload bestand",
"apps.uploadImageFailed": "Uploaden van afbeelding is mislukt. Laad opnieuw.",
@ -52,19 +50,21 @@
"apps.welcomeTitle": "Hallo {user}",
"appSettings.editors.deleteConfirmText": "Do you really want to remove this Editor URL?",
"appSettings.editors.deleteConfirmTitle": "Delete Editor URL",
"appSettings.editors.description": "Manage the URLs to custom editors to use them in the schema designer.",
"appSettings.editors.empty": "No Editor URL created yet.",
"appSettings.editors.title": "Custom Editors",
"appSettings.hideScheduler": "Hide dialog for scheduled publishing",
"appSettings.patterns.deleteConfirmText": "Wil je dit patroon echt verwijderen?",
"appSettings.patterns.deleteConfirmTitle": "Verwijder patroon",
"appSettings.patterns.description": "Patterns are reusable regular expressions for string field validation.",
"appSettings.patterns.empty": "Nog geen patroon gemaakt.",
"appSettings.patterns.title": "Patterns",
"appSettings.refreshTooltip": "Refresh UI Settings (CTRL + SHIFT + R)",
"appSettings.refreshTooltip": "Refresh UI Settings",
"appSettings.reloaded": "UI Settings reloaded.",
"appSettings.title": "UI Settings",
"assets.createFolder": "Map maken",
"assets.createFolderFailed": "Maken van een map is mislukt. Laad opnieuw.",
"assets.createFolderTooltip": "Nieuwe map maken (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "Nieuwe map maken",
"assets.deleteConfirmText": "Weet je zeker dat je het item wilt verwijderen?",
"assets.deleteConfirmTitle": "Item verwijderen",
"assets.deleteFailed": "Verwijderen van item is mislukt. Laad opnieuw.",
@ -77,6 +77,7 @@
"assets.downloadVersion": "Download deze versie",
"assets.dropToUpdate": "Zet neer om te updaten",
"assets.duplicateFile": "Asset is al geüpload.",
"assets.edit": "Edit Asset",
"assets.editor.flipHorizontally": "Horizontaal spiegelen",
"assets.editor.flipVertically": "Verticaal spiegelen",
"assets.editor.focusPointLabel": "Selecteer positie van focuspunt",
@ -95,7 +96,7 @@
"assets.metadataAdd": "Metadata toevoegen",
"assets.moveFailed": "Verplaatsen van item is mislukt. Laad opnieuw.",
"assets.protected": "Beschermd",
"assets.refreshTooltip": "Bestanden vernieuwen (CTRL + SHIFT + R)",
"assets.refreshTooltip": "Bestanden vernieuwen",
"assets.reloaded": "Bestanden herladen.",
"assets.removeConfirmText": "Wil je het bestand echt verwijderen?",
"assets.removeConfirmTitle": "Verwijder bestand",
@ -136,7 +137,7 @@
"backups.empty": "Nog geen back-ups gemaakt.",
"backups.loadFailed": "Laden van back-ups is mislukt.",
"backups.maximumReached": "Je hebt het maximale aantal back-ups bereikt: 10",
"backups.refreshTooltip": "Vernieuw back-ups (CTRL + SHIFT + R)",
"backups.refreshTooltip": "Vernieuw back-ups",
"backups.reloaded": "Back-ups herladen.",
"backups.restore": "Back-up herstellen",
"backups.restoreFailed": "Starten van herstel is mislukt.",
@ -153,6 +154,8 @@
"backups.startedLabel": "Gestart",
"backups.startFailed": "Starten van back-up is mislukt.",
"clients.add": "Client toevoegen",
"clients.add.description": "Add a client to give other applications access to your content.",
"clients.add.title": "Add a new Client",
"clients.addFailed": "Toevoegen van client is mislukt. Laad opnieuw.",
"clients.allowAnonymous": "Sta anonieme toegang toe.",
"clients.allowAnonymousHint": "Sta toegang tot de API toe zonder toegangstoken voor alle bronnen die zijn geconfigureerd via de rol van deze client. Geef niet meer dan één client anonieme toegang.",
@ -191,7 +194,7 @@
"clients.deleteConfirmTitle": "Client intrekken",
"clients.empty": "Nog geen client aangemaakt.",
"clients.loadFailed": "Kan clients niet laden. Laad opnieuw.",
"clients.refreshTooltip": "Ververs clients (CTRL + SHIFT + R)",
"clients.refreshTooltip": "Ververs clients",
"clients.reloaded": "Clients herladen.",
"clients.revokeFailed": "Kan client niet intrekken. Laad opnieuw.",
"clients.tokenFailed": "Maken van token is mislukt. Probeer het opnieuw.",
@ -236,6 +239,7 @@
"common.contributors": "Bijdragers",
"common.create": "Maken",
"common.created": "Gemaakt",
"common.dashboard": "Dasboard",
"common.date": "Datum",
"common.dateTimeEditor.local": "Lokaal",
"common.dateTimeEditor.now": "Nu",
@ -249,6 +253,7 @@
"common.disabled": "Disabled",
"common.displayName": "Weergavenaam",
"common.edit": "Bewerken",
"common.editing": "Editing",
"common.email": "E-mail",
"common.enabled": "Enabled",
"common.error": "Fout",
@ -290,10 +295,12 @@
"common.mapHide": "Verberg kaart",
"common.mapShow": "Toon kaart",
"common.message": "Bericht",
"common.more": "More",
"common.name": "Naam",
"common.no": "Nee",
"common.nothingChanged": "Er is niets veranderd.",
"common.noValue": "- Geen waarde -",
"common.openAPI": "Open API",
"common.or": "of",
"common.pagerInfo": "{itemFirst} - {itemLast} van {numberOfItems}",
"common.password": "Wachtwoord",
@ -328,11 +335,11 @@
"common.rules": "Regels",
"common.sampleCodeLabel": "Voorbeeldcode bij",
"common.save": "Opslaan",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schema's",
"common.search": "Search",
"common.searchGoogleMaps": "Zoeken in Google Maps",
"common.searchResults": "Zoekresultaten",
"common.security": "Security",
"common.separateByLine": "Scheiden op regel",
"common.settings": "Instellingen",
"common.sidebar": "Zijbalk Uitbreiding",
@ -388,7 +395,7 @@
"contents.contentTab.references": "References",
"contents.contentTab.referencing": "Referencing",
"contents.create": "Nieuw",
"contents.createContentTooltip": "Nieuwe inhoud (CTRL + SHIFT + G)",
"contents.createContentTooltip": "Nieuwe inhoud",
"contents.created": "Inhoud succesvol aangemaakt.",
"contents.createdByFieldDescription": "De gebruiker die het inhoudsitem heeft gemaakt.",
"contents.createFailed": "Maken van inhoud is mislukt. Laad opnieuw.",
@ -432,7 +439,7 @@
"contents.referencesLink": "Link geselecteerde inhoud ({count})",
"contents.referencesSelectExisting": "Selecteer bestaande",
"contents.referencesSelectSchema": "Selecteer {schema}",
"contents.refreshTooltip": "Ververs inhoud (CTRL + SHIFT + R)",
"contents.refreshTooltip": "Ververs inhoud",
"contents.reloaded": "Inhoud opnieuw geladen.",
"contents.removeConfirmText": "Wil je de inhoud echt verwijderen?",
"contents.removeConfirmTitle": "Verwijder inhoud",
@ -476,6 +483,7 @@
"contents.viewLatest": "Bekijk laatste",
"contents.viewReset": "Standaardweergave herstellen",
"contributors.add": "Bijdrager toevoegen",
"contributors.add.title": "Add or invite contributor",
"contributors.addFailed": "Toevoegen van bijdragers is mislukt. Laad opnieuw.",
"contributors.contributorAssigned": "Een nieuwe gebruiker met het ingevoerde e-mailadres is aangemaakt en toegewezen als bijdrager.",
"contributors.contributorAssignedExisting": "Gebruiker is toegewezen",
@ -494,7 +502,7 @@
"contributors.importTitle": "Bijdragers importeren",
"contributors.loadFailed": "Laden van bijdragers is mislukt. Laad opnieuw.",
"contributors.planHint": "Uw plan staat maximaal {maxContributors} bijdragers toe.",
"contributors.refreshTooltip": "Bijdragers vernieuwen (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "Bijdragers vernieuwen",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Zoeken",
"contributors.userNotFound": "De gebruiker bestaat niet.",
@ -542,7 +550,7 @@
"eventConsumers.loadFailed": "Kan gebeurtenisgebruikers niet laden. Laad opnieuw.",
"eventConsumers.pageTitle": "Evenementconsumenten",
"eventConsumers.position": "Positie",
"eventConsumers.refreshTooltip": "Ververs evenementgebruikers (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "Ververs evenementgebruikers",
"eventConsumers.reloaded": "Evenementconsumenten herladen.",
"eventConsumers.resetFailed": "Kan gebeurtenisgebruiker niet resetten. Laad opnieuw.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
@ -554,6 +562,8 @@
"history.loadFailed": "Kan geschiedenis niet laden. Laad opnieuw.",
"history.title": "Activiteit",
"languages.add": "Taal toevoegen",
"languages.add.description": "Add a new language that you want to support for your content.",
"languages.add.title": "Add a new Language",
"languages.addFailed": "Toevoegen van taal is mislukt. Laad opnieuw.",
"languages.deleteConfirmText": "Wil je de taal echt verwijderen?",
"languages.deleteConfirmTitle": "Verwijder taal",
@ -563,7 +573,7 @@
"languages.masterHint": "Andere talen vallen terug op de master als er geen fallback is gedefinieerd.",
"languages.optional": "Is optioneel",
"languages.optionalHint": "Waarden voor optionele talen mogen niet worden ingevoerd, zelfs niet als dit veld vereist is.",
"languages.refreshTooltip": "Ververs talen (CTRL + SHIFT + R)",
"languages.refreshTooltip": "Ververs talen",
"languages.reloaded": "Talen herladen.",
"languages.updateFailed": "Het wijzigen van de taal is mislukt. Laad opnieuw.",
"news.headline": "Wat is er nieuw?",
@ -583,15 +593,20 @@
"plans.notPlanOwner": "Je hebt geen abonnement aangemaakt. Daarom kun je het plan niet wijzigen.",
"plans.perMonth": "Per maand",
"plans.perYear": "Per jaar",
"plans.refreshTooltip": "Plannen vernieuwen (CTRL + SHIFT + R)",
"plans.refreshTooltip": "Plannen vernieuwen",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Geselecteerd",
"profile.title": "Profiel",
"profile.userEmail": "Aangemeld met",
"roles.add": "Rol toevoegen",
"roles.add.description": "Add a new role if you need custom permission and policies.",
"roles.add.title": "Add a custom Role",
"roles.addFailed": "Toevoegen van rol is mislukt. Laad opnieuw.",
"roles.customRoles": "Custom roles",
"roles.default.owner": "Kan alles doen, inclusief het verwijderen van de app.",
"roles.default.reader": "Kan alleen items en inhoud lezen.",
"roles.defaultRoles": "Default roles",
"roles.defaultRoles.hint": "Default roles cannot be deleted and are always part of your app.",
"roles.defaults.developer": "Kan de API-weergave gebruiken, middelen, inhoud, schema's, regels, workflows en patronen bewerken.",
"roles.defaults.editor": "Kan middelen en inhoud bewerken en workflows bekijken.",
"roles.deleteConfirmText": "Rol verwijderen",
@ -608,7 +623,7 @@
"roles.properties.hideSchemas": "Verberg schema's",
"roles.properties.hideSettings": "Verberg instellingen",
"roles.propertiesDescription": " Eigenschappen beschrijven het gedrag van de beheerinterface, maar bieden geen beveiliging voor de API. ",
"roles.refreshTooltip": "Ververs rollen (CTRL + SHIFT + R)",
"roles.refreshTooltip": "Ververs rollen",
"roles.reloaded": "Rollen opnieuw geladen.",
"roles.revokeFailed": "Kan rol niet intrekken. Laad opnieuw.",
"roles.roleNamePlaceholder": "Voer de rolnaam in",
@ -618,7 +633,7 @@
"rules.cancelFailed": "Annuleren van regel is mislukt. Laad opnieuw.",
"rules.create": "Maak een nieuwe regel",
"rules.createFailed": "Maken van regel is mislukt. Laad opnieuw.",
"rules.createTooltip": "Nieuwe regel (CTRL + SHIFT + G)",
"rules.createTooltip": "Nieuwe regel",
"rules.deleteConfirmText": "Wil je de regel echt verwijderen?",
"rules.deleteConfirmTitle": "Regel verwijderen",
"rules.deleteFailed": "Verwijderen van regel is mislukt. Laad opnieuw.",
@ -629,8 +644,8 @@
"rules.listPageTitle": "Regels",
"rules.loadFailed": "Laden van regels is mislukt. Laad opnieuw.",
"rules.readMore": "Lees meer",
"rules.refreshEventsTooltip": "Ververs evenementen (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Vernieuwingsregels (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "Ververs evenementen",
"rules.refreshTooltip": "Vernieuwingsregels",
"rules.reloaded": "Regels herladen.",
"rules.restarted": "Regel begint over een paar seconden te lopen.",
"rules.ruleEvents.cancelFailed": "Annuleren van regelgebeurtenis is mislukt. Laad opnieuw.",
@ -680,7 +695,7 @@
"schemas.create": "Schema maken",
"schemas.createCategory": "Nieuwe categorie maken ...",
"schemas.createFailed": "Kan schema niet maken. Laad opnieuw.",
"schemas.createSchemaTooltip": "Nieuw schema (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "Nieuw schema",
"schemas.deleteConfirmText": "Weet je zeker dat je het schema wilt verwijderen?",
"schemas.deleteConfirmTitle": "Schema verwijderen",
"schemas.deleteFailed": "Kan schema niet verwijderen. Laad opnieuw.",
@ -911,7 +926,7 @@
"users.createFailed": "Aanmaken van gebruiker mislukt. Laad opnieuw.",
"users.createPageTitle": "Gebruiker aanmaken",
"users.createTitle": "Nieuwe gebruiker",
"users.createTooltip": "Nieuwe gebruiker (CTRL + N)",
"users.createTooltip": "Nieuwe gebruiker",
"users.deleteConfirmText": "Do you really want to delete this user?",
"users.deleteConfirmTitle": "Delete user",
"users.deleteFailed": "Failed to delete user. Please reload.",
@ -924,7 +939,7 @@
"users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Gebruiker vergrendelen",
"users.passwordConfirmValidationMessage": "Wachtwoorden moeten hetzelfde zijn.",
"users.refreshTooltip": "Ververs gebruikers (CTRL + SHIFT + R)",
"users.refreshTooltip": "Ververs gebruikers",
"users.reloaded": "Gebruikers herladen.",
"users.search": "Zoeken naar gebruiker",
"users.unlockFailed": "Failed to unlock user. Please reload.",
@ -944,7 +959,6 @@
"validation.min": "{field|upper} moet groter zijn dan of gelijk zijn aan '{min}'.",
"validation.minlength": "{field|upper} moet minimaal {requiredlength} item (s) bevatten.",
"validation.minlengthstring": "{field|upper} moet minimaal {requiredlength} teken (s) bevatten.",
"validation.notAnValidSvg": "The SVG is malicious and contains script tags.",
"validation.pattern": "{field|upper} komt niet overeen met het patroon.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is vereist.",
@ -954,6 +968,8 @@
"validation.validdatetime": "{field|upper} is geen geldige datum en tijd.",
"validation.validvalues": "{field|upper} is geen geldige waarde.",
"workflows.add": "Workflow toevoegen",
"workflows.add.description": "The workflow name is only used in the UI and not shown to editors.",
"workflows.add.title": "Add a new workflow",
"workflows.addStep": "Stap toevoegen",
"workflows.createFailed": "Maken van workflow mislukt. Laad opnieuw.",
"workflows.deleteConfirmText": "Wil je de workflow echt verwijderen?",
@ -964,7 +980,7 @@
"workflows.notNamed": "Naamloze workflow",
"workflows.preventUpdates": "Updates voorkomen",
"workflows.publishedNotRemovable": "Kan niet worden verwijderd",
"workflows.refreshTooltip": "Werkstromen vernieuwen (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "Werkstromen vernieuwen",
"workflows.reloaded": "Workflows opnieuw geladen.",
"workflows.saved": "Workflow is opgeslagen.",
"workflows.schemasHint": "Beperk deze workflow tot specifieke schema's of laat het leeg voor alle schema's.",

64
backend/i18n/frontend_zh.json

@ -42,8 +42,6 @@
"apps.removeImageFailed": "删除应用图片失败。请重新加载。",
"apps.updateFailed": "更新应用失败。请重新加载。",
"apps.updateSettingsFailed": "更新界面设置失败。请重新加载。",
"apps.upgradeHintCurrent": "你在 {plan} 计划中。",
"apps.upgradeHintUpgrade": "升级!",
"apps.uploadImage": "拖放文件以替换应用图片。使用正方形大小。",
"apps.uploadImageButton": "上传文件",
"apps.uploadImageFailed": "上传图片失败,请重新加载。",
@ -52,19 +50,21 @@
"apps.welcomeTitle": "Hi {user}",
"appSettings.editors.deleteConfirmText": "你真的要删除这个编辑器 URL 吗?",
"appSettings.editors.deleteConfirmTitle": "删除编辑器 URL",
"appSettings.editors.description": "Manage the URLs to custom editors to use them in the schema designer.",
"appSettings.editors.empty": "尚未创建编辑器 URL。",
"appSettings.editors.title": "自定义编辑器",
"appSettings.hideScheduler": "隐藏预定发布对话框",
"appSettings.patterns.deleteConfirmText": "你真的要删除这个模式吗?",
"appSettings.patterns.deleteConfirmTitle": "删除模式",
"appSettings.patterns.description": "Patterns are reusable regular expressions for string field validation.",
"appSettings.patterns.empty": "尚未创建模式。",
"appSettings.patterns.title": "模式",
"appSettings.refreshTooltip": "刷新 UI 设置 (CTRL + SHIFT + R)",
"appSettings.refreshTooltip": "刷新 UI 设置",
"appSettings.reloaded": "UI 设置重新加载。",
"appSettings.title": "界面设置",
"assets.createFolder": "创建文件夹",
"assets.createFolderFailed": "资源文件夹创建失败,请重新加载。",
"assets.createFolderTooltip": "创建新文件夹 (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "创建新文件夹",
"assets.deleteConfirmText": "你真的要删除资源吗?",
"assets.deleteConfirmTitle": "删除资源",
"assets.deleteFailed": "资源删除失败,请重新加载。",
@ -77,7 +77,8 @@
"assets.downloadVersion": "下载此版本",
"assets.dropToUpdate": "下拉更新",
"assets.duplicateFile": "资源已经上传。",
"assets.editor.flipHorizontally": "水平翻转",
"assets.edit": "Edit Asset",
"assets.editor.flipHorizontally": "Flip Horizontally",
"assets.editor.flipVertically": "垂直翻转",
"assets.editor.focusPointLabel": "选择焦点位置",
"assets.editor.focusPointPreview": "不同尺寸的预览",
@ -95,7 +96,7 @@
"assets.metadataAdd": "添加元数据",
"assets.moveFailed": "资源移动失败。请重新加载。",
"assets.protected": "受保护",
"assets.refreshTooltip": "刷新资源 (CTRL + SHIFT + R)",
"assets.refreshTooltip": "刷新资源",
"assets.reloaded": "资源重新加载。",
"assets.removeConfirmText": "你真的要移除资源吗?",
"assets.removeConfirmTitle": "移除资源",
@ -136,7 +137,7 @@
"backups.empty": "尚未创建备份。",
"backups.loadFailed": "加载备份失败。",
"backups.maximumReached": "您已达到最大备份数:10。",
"backups.refreshTooltip": "刷新备份 (CTRL + SHIFT + R)",
"backups.refreshTooltip": "刷新备份",
"backups.reloaded": "备份已重新加载。",
"backups.restore": "恢复备份",
"backups.restoreFailed": "无法开始恢复。",
@ -153,6 +154,8 @@
"backups.startedLabel": "开始",
"backups.startFailed": "启动备份失败。",
"clients.add": "添加客户端",
"clients.add.description": "Add a client to give other applications access to your content.",
"clients.add.title": "Add a new Client",
"clients.addFailed": "添加客户端失败,请重新加载。",
"clients.allowAnonymous": "允许匿名访问。",
"clients.allowAnonymousHint": "允许在没有访问令牌的情况下访问通过此客户端角色配置的所有资源的 API。不要给多个客户端匿名访问。",
@ -191,7 +194,7 @@
"clients.deleteConfirmTitle": "撤销客户端",
"clients.empty": "尚未创建客户端。",
"clients.loadFailed": "加载客户端失败。请重新加载。",
"clients.refreshTooltip": "刷新客户端 (CTRL + SHIFT + R)",
"clients.refreshTooltip": "刷新客户端",
"clients.reloaded": "客户端重新加载。",
"clients.revokeFailed": "撤销客户端失败。请重新加载。",
"clients.tokenFailed": "创建令牌失败。请重试。",
@ -236,6 +239,7 @@
"common.contributors": "贡献者",
"common.create": "创建",
"common.created": "创建",
"common.dashboard": "Dasboard",
"common.date": "日期",
"common.dateTimeEditor.local": "本地",
"common.dateTimeEditor.now": "现在",
@ -249,6 +253,7 @@
"common.disabled": "已禁用",
"common.displayName": "显示名称",
"common.edit": "编辑",
"common.editing": "Editing",
"common.email": "电子邮件",
"common.enabled": "已启用",
"common.error": "错误",
@ -290,10 +295,12 @@
"common.mapHide": "隐藏地图",
"common.mapShow": "显示地图",
"common.message": "消息",
"common.more": "More",
"common.name": "名称",
"common.no": "不",
"common.nothingChanged": "什么都没有改变。",
"common.noValue": "- 无值 -",
"common.openAPI": "Open API",
"common.or": "或",
"common.pagerInfo": "{itemFirst}-{itemLast} 的 {numberOfItems}",
"common.password": "密码",
@ -328,11 +335,11 @@
"common.rules": "规则",
"common.sampleCodeLabel": "示例代码在",
"common.save": "保存",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemas",
"common.search": "搜索",
"common.searchGoogleMaps": "搜索谷歌地图",
"common.searchResults": "搜索结果",
"common.security": "Security",
"common.separateByLine": "按行分隔",
"common.settings": "设置",
"common.sidebar": "侧边栏扩展",
@ -388,7 +395,7 @@
"contents.contentTab.references": "参考资料",
"contents.contentTab.referencing": "引用",
"contents.create": "新建",
"contents.createContentTooltip": "新建内容 (CTRL + SHIFT + G)",
"contents.createContentTooltip": "新建内容",
"contents.created": "内容创建成功。",
"contents.createdByFieldDescription": "创建内容项的用户。",
"contents.createFailed": "创建内容失败,请重新加载。",
@ -432,7 +439,7 @@
"contents.referencesLink": "链接所选内容 ({count})",
"contents.referencesSelectExisting": "选择现有",
"contents.referencesSelectSchema": "选择 {schema}",
"contents.refreshTooltip": "刷新内容 (CTRL + SHIFT + R)",
"contents.refreshTooltip": "刷新内容",
"contents.reloaded": "内容已重新加载。",
"contents.removeConfirmText": "您真的要删除内容吗?",
"contents.removeConfirmTitle": "删除内容",
@ -476,6 +483,7 @@
"contents.viewLatest": "查看最新",
"contents.viewReset": "重置默认视图",
"contributors.add": "添加贡献者",
"contributors.add.title": "Add or invite contributor",
"contributors.addFailed": "添加贡献者失败。请重新加载。",
"contributors.contributorAssigned": "一个具有输入电子邮件地址的新用户已被创建并被指定为贡献者。",
"contributors.contributorAssignedExisting": "用户已被分配",
@ -494,7 +502,7 @@
"contributors.importTitle": "导入贡献者",
"contributors.loadFailed": "加载贡献者失败。请重新加载。",
"contributors.planHint": "您的计划允许最多 {maxContributors} 个贡献者。",
"contributors.refreshTooltip": "刷新贡献者 (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "刷新贡献者",
"contributors.reloaded": "贡献者重新加载。",
"contributors.search": "搜索",
"contributors.userNotFound": "用户不存在。",
@ -542,7 +550,7 @@
"eventConsumers.loadFailed": "加载事件消费者失败。请重新加载。",
"eventConsumers.pageTitle": "事件消费者",
"eventConsumers.position": "位置",
"eventConsumers.refreshTooltip": "刷新事件消费者 (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "刷新事件消费者",
"eventConsumers.reloaded": "事件消费者重新加载。",
"eventConsumers.resetFailed": "无法重置事件消费者。请重新加载。",
"eventConsumers.resetTooltip": "重置事件消费者",
@ -554,6 +562,8 @@
"history.loadFailed": "加载历史记录失败。请重新加载。",
"history.title": "活动",
"languages.add": "添加语言",
"languages.add.description": "Add a new language that you want to support for your content.",
"languages.add.title": "Add a new Language",
"languages.addFailed": "添加语言失败。请重新加载。",
"languages.deleteConfirmText": "你真的要删除语言吗?",
"languages.deleteConfirmTitle": "删除语言",
@ -563,7 +573,7 @@
"languages.masterHint": "如果没有定义回退,其他语言回退到母版。",
"languages.optional": "是可选的",
"languages.optionalHint": "不得输入可选语言的值,即使字段是必需的。",
"languages.refreshTooltip": "刷新语言 (CTRL + SHIFT + R)",
"languages.refreshTooltip": "刷新语言",
"languages.reloaded": "语言已重新加载。",
"languages.updateFailed": "更改语言失败。请重新加载。",
"news.headline": "有什么新鲜事?",
@ -583,15 +593,20 @@
"plans.notPlanOwner": "您尚未创建订阅。因此您无法更改计划。",
"plans.perMonth": "每月",
"plans.perYear": "每年",
"plans.refreshTooltip": "刷新计划 (CTRL + SHIFT + R)",
"plans.refreshTooltip": "刷新计划",
"plans.reloaded": "计划重新加载。",
"plans.selected": "已选择",
"profile.title": "个人资料",
"profile.userEmail": "登录方式",
"roles.add": "添加角色",
"roles.add.description": "Add a new role if you need custom permission and policies.",
"roles.add.title": "Add a custom Role",
"roles.addFailed": "添加角色失败,请重新加载。",
"roles.customRoles": "Custom roles",
"roles.default.owner": "可以做任何事情,包括删除应用程序。",
"roles.default.reader": "只能读取资源和内容。",
"roles.defaultRoles": "Default roles",
"roles.defaultRoles.hint": "Default roles cannot be deleted and are always part of your app.",
"roles.defaults.developer": "可以使用 API 视图,编辑资源、内容、Schemas、规则、工作流和 appSettings.patterns。",
"roles.defaults.editor": "可以编辑资源和内容并查看工作流程。",
"roles.deleteConfirmText": "删除角色",
@ -608,7 +623,7 @@
"roles.properties.hideSchemas": "隐藏Schemas",
"roles.properties.hideSettings": "隐藏设置",
"roles.propertiesDescription": "属性描述管理 UI 的行为,但不为 API 提供安全性。",
"roles.refreshTooltip": "刷新角色 (CTRL + SHIFT + R)",
"roles.refreshTooltip": "刷新角色",
"roles.reloaded": "重新加载角色。",
"roles.revokeFailed": "撤销角色失败,请重新加载。",
"roles.roleNamePlaceholder": "输入角色名称",
@ -618,7 +633,7 @@
"rules.cancelFailed": "取消规则失败,请重新加载。",
"rules.create": "新规则",
"rules.createFailed": "创建规则失败。请重新加载。",
"rules.createTooltip": "新规则 (CTRL + SHIFT + G)",
"rules.createTooltip": "新规则",
"rules.deleteConfirmText": "你真的要删除规则吗?",
"rules.deleteConfirmTitle": "删除规则",
"rules.deleteFailed": "删除规则失败,请重新加载。",
@ -629,8 +644,8 @@
"rules.listPageTitle": "规则",
"rules.loadFailed": "加载规则失败。请重新加载。",
"rules.readMore": "阅读更多",
"rules.refreshEventsTooltip": "刷新事件 (CTRL + SHIFT + R)",
"rules.refreshTooltip": "刷新规则 (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "刷新事件",
"rules.refreshTooltip": "刷新规则",
"rules.reloaded": "规则重新加载。",
"rules.restarted": "规则将在几秒钟后开始运行。",
"rules.ruleEvents.cancelFailed": "取消规则事件失败。请重新加载。",
@ -680,7 +695,7 @@
"schemas.create": "Create Schema",
"schemas.createCategory": "创建新类别...",
"schemas.createFailed": "无法创建Schemas。请重新加载。",
"schemas.createSchemaTooltip": "新Schemas (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "新Schemas",
"schemas.deleteConfirmText": "您真的要删除Schemas吗?",
"schemas.deleteConfirmTitle": "删除Schemas",
"schemas.deleteFailed": "删除Schemas失败。请重新加载。",
@ -911,7 +926,7 @@
"users.createFailed": "创建用户失败,请重新加载。",
"users.createPageTitle": "创建用户",
"users.createTitle": "新用户",
"users.createTooltip": "新用户 (CTRL + N)",
"users.createTooltip": "新用户",
"users.deleteConfirmText": "你真的要删除这个用户吗?",
"users.deleteConfirmTitle": "删除用户",
"users.deleteFailed": "删除用户失败,请重新加载。",
@ -924,7 +939,7 @@
"users.lockFailed": "锁定用户失败。请重新加载。",
"users.lockTooltip": "锁定用户",
"users.passwordConfirmValidationMessage": "密码必须相同。",
"users.refreshTooltip": "刷新用户 (CTRL + SHIFT + R)",
"users.refreshTooltip": "刷新用户",
"users.reloaded": "用户重新加载。",
"users.search": "搜索用户",
"users.unlockFailed": "解锁用户失败。请重新加载。",
@ -944,7 +959,6 @@
"validation.min": "{field|upper} 必须大于或等于 '{min}'。",
"validation.minlength": "{field|upper} 必须至少有 {requiredlength} 项。",
"validation.minlengthstring": "{field|upper} 必须至少有 {requiredlength} 个字符。",
"validation.notAnValidSvg": "The SVG is malicious and contains script tags.",
"validation.pattern": "{field|upper} 与模式不匹配。",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} 是必需的。",
@ -954,6 +968,8 @@
"validation.validdatetime": "{field|upper} 不是有效的日期时间。",
"validation.validvalues": "{field|upper} 不是一个有效值。",
"workflows.add": "添加工作流",
"workflows.add.description": "The workflow name is only used in the UI and not shown to editors.",
"workflows.add.title": "Add a new workflow",
"workflows.addStep": "添加步骤",
"workflows.createFailed": "创建工作流失败。请重新加载。",
"workflows.deleteConfirmText": "你真的要删除工作流吗?",
@ -964,7 +980,7 @@
"workflows.notNamed": "未命名的工作流程",
"workflows.preventUpdates": "防止更新",
"workflows.publishedNotRemovable": "无法删除",
"workflows.refreshTooltip": "刷新工作流 (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "刷新工作流",
"workflows.reloaded": "工作流已重新加载。",
"workflows.saved": "工作流已保存。",
"workflows.schemasHint": "将此工作流限制为特定Schemas或将其保留为所有Schemas的空。",

1
backend/i18n/source/backend_en.json

@ -361,6 +361,7 @@
"validation.lessEqualsThan": "{property|upper} must be less or equal to {other|lower}.",
"validation.lessThan": "{property|upper} must be less than {other|lower}.",
"validation.notAnImage": "Picture is not a valid image.",
"validation.notAnValidSvg": "The SVG is malicious and contains script tags.",
"validation.onlyOneFile": "Can only upload one file.",
"validation.required": "{property|upper} is required.",
"validation.requiredBoth": "If {property1|lower} or {property2|lower} is used both must be defined.",

68
backend/i18n/source/frontend_en.json

@ -42,8 +42,6 @@
"apps.removeImageFailed": "Failed to remove app image. Please reload.",
"apps.updateFailed": "Failed to update app. Please reload.",
"apps.updateSettingsFailed": "Faield to update UI settings. Please reload.",
"apps.upgradeHintCurrent": "You are on the {plan} plan.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Drop an file to replace the app image. Use a square size.",
"apps.uploadImageButton": "Upload File",
"apps.uploadImageFailed": "Failed to upload image. Please reload.",
@ -52,19 +50,21 @@
"apps.welcomeTitle": "Hi {user}",
"appSettings.editors.deleteConfirmText": "Do you really want to remove this Editor URL?",
"appSettings.editors.deleteConfirmTitle": "Delete Editor URL",
"appSettings.editors.description": "Manage the URLs to custom editors to use them in the schema designer.",
"appSettings.editors.empty": "No Editor URL created yet.",
"appSettings.editors.title": "Custom Editors",
"appSettings.hideScheduler": "Hide dialog for scheduled publishing",
"appSettings.patterns.deleteConfirmText": "Do you really want to remove this pattern?",
"appSettings.patterns.deleteConfirmTitle": "Delete pattern",
"appSettings.patterns.description": "Patterns are reusable regular expressions for string field validation.",
"appSettings.patterns.empty": "No pattern created yet.",
"appSettings.patterns.title": "Patterns",
"appSettings.refreshTooltip": "Refresh UI Settings (CTRL + SHIFT + R)",
"appSettings.refreshTooltip": "Refresh UI Settings",
"appSettings.reloaded": "UI Settings reloaded.",
"appSettings.title": "UI Settings",
"assets.createFolder": "Create Folder",
"assets.createFolderFailed": "Failed to create asset folder. Please reload.",
"assets.createFolderTooltip": "Create new folder (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "Create new folder",
"assets.deleteConfirmText": "Do you really want to delete the asset?",
"assets.deleteConfirmTitle": "Delete asset",
"assets.deleteFailed": "Failed to delete asset. Please reload.",
@ -77,6 +77,7 @@
"assets.downloadVersion": "Download this Version",
"assets.dropToUpdate": "Drop to update",
"assets.duplicateFile": "Asset has already been uploaded.",
"assets.edit": "Edit Asset",
"assets.editor.flipHorizontally": "Flip Horizontally",
"assets.editor.flipVertically": "Flip Vertically",
"assets.editor.focusPointLabel": "Select position of focus point",
@ -95,7 +96,7 @@
"assets.metadataAdd": "Add Metadata",
"assets.moveFailed": "Failed to move asset. Please reload.",
"assets.protected": "Protected",
"assets.refreshTooltip": "Refresh Assets (CTRL + SHIFT + R)",
"assets.refreshTooltip": "Refresh Assets",
"assets.reloaded": "Assets reloaded.",
"assets.removeConfirmText": "Do you really want to remove the asset?",
"assets.removeConfirmTitle": "Remove asset",
@ -136,7 +137,7 @@
"backups.empty": "No backups created yet.",
"backups.loadFailed": "Failed to load backups.",
"backups.maximumReached": "Your have reached the maximum number of backups: 10.",
"backups.refreshTooltip": "Refresh backups (CTRL + SHIFT + R)",
"backups.refreshTooltip": "Refresh backups",
"backups.reloaded": "Backups reloaded.",
"backups.restore": "Restore Backup",
"backups.restoreFailed": "Failed to start restore.",
@ -153,6 +154,8 @@
"backups.startedLabel": "Started",
"backups.startFailed": "Failed to start backup.",
"clients.add": "Add Client",
"clients.add.description": "Add a client to give other applications access to your content.",
"clients.add.title": "Add a new Client",
"clients.addFailed": "Failed to add client. Please reload.",
"clients.allowAnonymous": "Allow anonymous access.",
"clients.allowAnonymousHint": "Allow access to the API without an access token to all resources that are configured via the role of this client. Do not give more than one client anonymous access.",
@ -191,7 +194,7 @@
"clients.deleteConfirmTitle": "Revoke client",
"clients.empty": "No client created yet.",
"clients.loadFailed": "Failed to load clients. Please reload.",
"clients.refreshTooltip": "Refresh clients (CTRL + SHIFT + R)",
"clients.refreshTooltip": "Refresh clients",
"clients.reloaded": "Clients reloaded.",
"clients.revokeFailed": "Failed to revoke client. Please reload.",
"clients.tokenFailed": "Failed to create token. Please retry.",
@ -236,6 +239,7 @@
"common.contributors": "Contributors",
"common.create": "Create",
"common.created": "Created",
"common.dashboard": "Dasboard",
"common.date": "Date",
"common.dateTimeEditor.local": "Local",
"common.dateTimeEditor.now": "Now",
@ -249,6 +253,7 @@
"common.disabled": "Disabled",
"common.displayName": "Display Name",
"common.edit": "Edit",
"common.editing": "Editing",
"common.email": "Email",
"common.enabled": "Enabled",
"common.error": "Error",
@ -290,10 +295,12 @@
"common.mapHide": "Hide map",
"common.mapShow": "Show map",
"common.message": "Message",
"common.more": "More",
"common.name": "Name",
"common.no": "No",
"common.nothingChanged": "Nothing has been changed.",
"common.noValue": "- No value -",
"common.openAPI": "Open API",
"common.or": "or",
"common.pagerInfo": "{itemFirst}-{itemLast} of {numberOfItems}",
"common.password": "Password",
@ -328,11 +335,11 @@
"common.rules": "Rules",
"common.sampleCodeLabel": "Sample Code at",
"common.save": "Save",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemas",
"common.search": "Search",
"common.searchGoogleMaps": "Search Google Maps",
"common.searchResults": "Search Results",
"common.security": "Security",
"common.separateByLine": "Separate by line",
"common.settings": "Settings",
"common.sidebar": "Sidebar Extension",
@ -388,7 +395,7 @@
"contents.contentTab.references": "References",
"contents.contentTab.referencing": "Referencing",
"contents.create": "New",
"contents.createContentTooltip": "New Content (CTRL + SHIFT + G)",
"contents.createContentTooltip": "New Content",
"contents.created": "Content created successfully.",
"contents.createdByFieldDescription": "The user who created the content item.",
"contents.createFailed": "Failed to create content. Please reload.",
@ -432,7 +439,7 @@
"contents.referencesLink": "Link selected contents ({count})",
"contents.referencesSelectExisting": "Select Existing",
"contents.referencesSelectSchema": "Select {schema}",
"contents.refreshTooltip": "Refresh Contents (CTRL + SHIFT + R)",
"contents.refreshTooltip": "Refresh Contents",
"contents.reloaded": "Contents reloaded.",
"contents.removeConfirmText": "Do you really want to remove the content?",
"contents.removeConfirmTitle": "Remove content",
@ -442,7 +449,7 @@
"contents.scheduledTo": "to",
"contents.schemasPageTitle": "Contents",
"contents.searchPlaceholder": "Fulltext search",
"contents.searchSchemasPlaceholder": "Search for schemas...",
"contents.searchSchemasPlaceholder": "Search",
"contents.selectionCount": "{count} items selected",
"contents.statusFieldDescription": "The status of the content item.",
"contents.statusQueries": "Status Queries",
@ -476,6 +483,7 @@
"contents.viewLatest": "View latest",
"contents.viewReset": "Reset Default View",
"contributors.add": "Add Contributor",
"contributors.add.title": "Add or invite contributor",
"contributors.addFailed": "Failed to add contributors. Please reload.",
"contributors.contributorAssigned": "A new user with the entered email address has been created and assigned as contributor.",
"contributors.contributorAssignedExisting": "User has been assigned",
@ -494,7 +502,7 @@
"contributors.importTitle": "Import contributors",
"contributors.loadFailed": "Failed to load contributors. Please reload.",
"contributors.planHint": "Your plan allows up to {maxContributors} contributors.",
"contributors.refreshTooltip": "Refresh contributors (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "Refresh contributors",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Search",
"contributors.userNotFound": "The user does not exist.",
@ -542,7 +550,7 @@
"eventConsumers.loadFailed": "Failed to load event consumers. Please reload.",
"eventConsumers.pageTitle": "Event Consumers",
"eventConsumers.position": "Position",
"eventConsumers.refreshTooltip": "Refresh event consumers (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "Refresh event consumers",
"eventConsumers.reloaded": "Event Consumers reloaded.",
"eventConsumers.resetFailed": "Failed to reset event consumer. Please reload.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
@ -554,6 +562,8 @@
"history.loadFailed": "Failed to load history. Please reload.",
"history.title": "Activity",
"languages.add": "Add Language",
"languages.add.description": "Add a new language that you want to support for your content.",
"languages.add.title": "Add a new Language",
"languages.addFailed": "Failed to add language. Please reload.",
"languages.deleteConfirmText": "Do you really want to remove the language?",
"languages.deleteConfirmTitle": "Remove language",
@ -563,7 +573,7 @@
"languages.masterHint": "Other languages fall back to the master if no fallback is defined.",
"languages.optional": "Is Optional",
"languages.optionalHint": "Values for optional languages must not be entered, even if field is required.",
"languages.refreshTooltip": "Refresh languages (CTRL + SHIFT + R)",
"languages.refreshTooltip": "Refresh languages",
"languages.reloaded": "Languages reloaded.",
"languages.updateFailed": "Failed to change language. Please reload.",
"news.headline": "What's new?",
@ -583,16 +593,21 @@
"plans.notPlanOwner": "You have not created the subscription. Therefore you cannot change the plan.",
"plans.perMonth": "Per Month",
"plans.perYear": "Per Year",
"plans.refreshTooltip": "Refresh Plans (CTRL + SHIFT + R)",
"plans.refreshTooltip": "Refresh Plans",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Selected",
"profile.title": "Profile",
"profile.userEmail": "Signed in with",
"roles.add": "Add role",
"roles.add.description": "Add a new role if you need custom permission and policies.",
"roles.add.title": "Add a custom Role",
"roles.addFailed": "Failed to add role. Please reload.",
"roles.customRoles": "Custom roles",
"roles.default.owner": "Can do everything, including deleting the app.",
"roles.default.reader": "Can only read assets and contents.",
"roles.defaults.developer": "Can use the API view, edit assets, contents, schemas, rules, workflows and appSettings.patterns.",
"roles.defaultRoles": "Default roles",
"roles.defaultRoles.hint": "Default roles cannot be deleted and are always part of your app.",
"roles.defaults.developer": "Can use the API view, edit assets, contents, schemas, rules, workflows and settings.",
"roles.defaults.editor": "Can edit assets and contents and view workflows.",
"roles.deleteConfirmText": "Delete role",
"roles.deleteConfirmTitle": "Do you really want to delete the role?",
@ -608,7 +623,7 @@
"roles.properties.hideSchemas": "Hide Schemas",
"roles.properties.hideSettings": "Hide Settings",
"roles.propertiesDescription": "Properties describe the behavior of the Management UI, but do not provide security for the API.",
"roles.refreshTooltip": "Refresh roles (CTRL + SHIFT + R)",
"roles.refreshTooltip": "Refresh roles",
"roles.reloaded": "Roles reloaded.",
"roles.revokeFailed": "Failed to revoke role. Please reload.",
"roles.roleNamePlaceholder": "Enter role name",
@ -618,7 +633,7 @@
"rules.cancelFailed": "Failed to cancel rule. Please reload.",
"rules.create": "New Rule",
"rules.createFailed": "Failed to create rule. Please reload.",
"rules.createTooltip": "New Rule (CTRL + SHIFT + G)",
"rules.createTooltip": "New Rule",
"rules.deleteConfirmText": "Do you really want to delete the rule?",
"rules.deleteConfirmTitle": "Delete rule",
"rules.deleteFailed": "Failed to delete rule. Please reload.",
@ -629,8 +644,8 @@
"rules.listPageTitle": "Rules",
"rules.loadFailed": "Failed to load Rules. Please reload.",
"rules.readMore": "Read More",
"rules.refreshEventsTooltip": "Refresh Events (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Refresh Rules (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "Refresh Events",
"rules.refreshTooltip": "Refresh Rules",
"rules.reloaded": "Rules reloaded.",
"rules.restarted": "Rule will start to run in a few seconds.",
"rules.ruleEvents.cancelFailed": "Failed to cancel rule event. Please reload.",
@ -680,7 +695,7 @@
"schemas.create": "Create Schema",
"schemas.createCategory": "Create new category...",
"schemas.createFailed": "Failed to create schema. Please reload.",
"schemas.createSchemaTooltip": "New Schema (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "New Schema",
"schemas.deleteConfirmText": "Do you really want to delete the schema?",
"schemas.deleteConfirmTitle": "Delete schema",
"schemas.deleteFailed": "Failed to delete schema. Please reload.",
@ -842,7 +857,7 @@
"schemas.schemaNameHint": "You can only use letters, numbers and dashes and not more than 40 characters.",
"schemas.schemaNameValidationMessage": "Name can only contain letters, numbers, dashes and spaces.",
"schemas.schemaTagsHint": "Tags to annotate your schema for automation processes.",
"schemas.searchPlaceholder": "Search for schemas...",
"schemas.searchPlaceholder": "Search...",
"schemas.showFieldFailed": "Failed to show field. Please reload.",
"schemas.synchronized": "Schema synchronized successfully.",
"schemas.synchronizeFailed": "Failed to synchronize schema. Please reload.",
@ -911,7 +926,7 @@
"users.createFailed": "Failed to create user. Please reload.",
"users.createPageTitle": "Create User",
"users.createTitle": "New User",
"users.createTooltip": "New User (CTRL + N)",
"users.createTooltip": "New User",
"users.deleteConfirmText": "Do you really want to delete this user?",
"users.deleteConfirmTitle": "Delete user",
"users.deleteFailed": "Failed to delete user. Please reload.",
@ -924,7 +939,7 @@
"users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Lock User",
"users.passwordConfirmValidationMessage": "Passwords must be the same.",
"users.refreshTooltip": "Refresh Users (CTRL + SHIFT + R)",
"users.refreshTooltip": "Refresh Users",
"users.reloaded": "Users reloaded.",
"users.search": "Search for user",
"users.unlockFailed": "Failed to unlock user. Please reload.",
@ -944,7 +959,6 @@
"validation.min": "{field|upper} must be greater or equal to '{min}'.",
"validation.minlength": "{field|upper} must have at least {requiredlength} item(s).",
"validation.minlengthstring": "{field|upper} must have at least {requiredlength} character(s).",
"validation.notAnValidSvg": "The SVG is malicious and contains script tags.",
"validation.pattern": "{field|upper} does not match to the pattern.",
"validation.patternmessage": "{message}",
"validation.required": "{field|upper} is required.",
@ -954,6 +968,8 @@
"validation.validdatetime": "{field|upper} is not a valid date time.",
"validation.validvalues": "{field|upper} is not a valid value.",
"workflows.add": "Add Workflow",
"workflows.add.description": "The workflow name is only used in the UI and not shown to editors.",
"workflows.add.title": "Add a new workflow",
"workflows.addStep": "Add Step",
"workflows.createFailed": "Failed to create workflow. Please reload.",
"workflows.deleteConfirmText": "Do you really want to remove the workflow?",
@ -964,7 +980,7 @@
"workflows.notNamed": "Unnamed Workflow",
"workflows.preventUpdates": "Prevent updates",
"workflows.publishedNotRemovable": "Cannot be removed",
"workflows.refreshTooltip": "Refresh workflows (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "Refresh workflows",
"workflows.reloaded": "Workflows reloaded.",
"workflows.saved": "Workflow has been saved.",
"workflows.schemasHint": "Restrict this workflow to specific schemas or keep it empty for all schemas.",

39
backend/i18n/source/frontend_it.json

@ -40,8 +40,6 @@
"apps.removeImage": "Rimuovi l'immagine",
"apps.removeImageFailed": "Non è stato possibile rimuovere l'immagine dell'app. Per favore ricarica.",
"apps.updateFailed": "Non è stato possibile aggiornare l'app. Per favore ricarica.",
"apps.upgradeHintCurrent": "Tu sei nel piano {plan}.",
"apps.upgradeHintUpgrade": "Aggiorna!",
"apps.uploadImage": "Trascina il file per sostituire l'immagine dell'app. Utilizza una dimensione quadrata.",
"apps.uploadImageButton": "Carica il File",
"apps.uploadImageFailed": "Non è stato possibile caricare l'immagine. Per favore ricarica.",
@ -53,7 +51,7 @@
"appSettings.patterns.empty": "Nessun pattern è stato ancora creato.",
"assets.createFolder": "Crea cartella",
"assets.createFolderFailed": "Non è stato possibile creare la cartella degli asset. Per favore ricarica.",
"assets.createFolderTooltip": "Crea una nuova cartella (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "Crea una nuova cartella",
"assets.deleteConfirmText": "Sei sicuro di voler cancellare la risorsa?",
"assets.deleteConfirmTitle": "Elimina la risorsa",
"assets.deleteFailed": "Non è stato possibile cancellare la risorsa. Per favore ricarica.",
@ -84,7 +82,7 @@
"assets.metadataAdd": "Aggiungi un metadato",
"assets.moveFailed": "Non è stato possibile spostare la risorsa. Per favore ricarica.",
"assets.protected": "Protetto",
"assets.refreshTooltip": "Aggiorna le risorse (CTRL + SHIFT + R)",
"assets.refreshTooltip": "Aggiorna le risorse",
"assets.reloaded": "Risorse ricaricate.",
"assets.removeConfirmText": "Sei sicuro di voler cancellare la risorsa?",
"assets.removeConfirmTitle": "Risorsa cancellata",
@ -125,7 +123,7 @@
"backups.empty": "Nessun backup è stato ancora creato.",
"backups.loadFailed": "Non è stato possibile caricare i backup.",
"backups.maximumReached": "Hai raggiunto il numero massimo di backup: 10.",
"backups.refreshTooltip": "Aggiorna i backup (CTRL + SHIFT + R)",
"backups.refreshTooltip": "Aggiorna i backup",
"backups.reloaded": "Backup aggiornati.",
"backups.restore": "Backup ripristinato",
"backups.restoreFailed": "Non è stato possibile avviare il ripristino.",
@ -180,7 +178,7 @@
"clients.deleteConfirmTitle": "Rimuovere il client",
"clients.empty": "Nessun client ancora creato.",
"clients.loadFailed": "Non è stato possibile caricare i client. Per favore ricarica.",
"clients.refreshTooltip": "Aggiorna i client (CTRL + SHIFT + R)",
"clients.refreshTooltip": "Aggiorna i client",
"clients.reloaded": "Client ricaricati.",
"clients.revokeFailed": "Non è stato possibile rimuovere il client. Per favore ricarica.",
"clients.tokenFailed": "Non è stato possibile creare il token. Per favore riprova.",
@ -308,7 +306,6 @@
"common.rules": "Regole",
"common.sampleCodeLabel": "Esempio di codice per",
"common.save": "Salva",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schemi",
"common.searchGoogleMaps": "Cerca su Google Maps",
"common.searchResults": "Risultati di ricerca",
@ -363,7 +360,7 @@
"contents.contentTab.references": "Collegato a",
"contents.contentTab.referencing": "Collegato da",
"contents.create": "Nuovo",
"contents.createContentTooltip": "Nuovo contenuto (CTRL + SHIFT + G)",
"contents.createContentTooltip": "Nuovo contenuto",
"contents.created": "Contenuto creato con successo.",
"contents.createdByFieldDescription": "L'utente che ha creato l'elemento del contenuto.",
"contents.createFailed": "Non è stato possibile creare il contenuto. Per favore ricarica.",
@ -407,7 +404,7 @@
"contents.referencesLink": "Collega i contenuti selezionati ({count})",
"contents.referencesSelectExisting": "Seleziona da contenuti esistenti",
"contents.referencesSelectSchema": "Seleziona {schema}",
"contents.refreshTooltip": "Aggiorna i contenuti (CTRL + SHIFT + R)",
"contents.refreshTooltip": "Aggiorna i contenuti",
"contents.reloaded": "Contenuti aggiornati.",
"contents.removeConfirmText": "Sei sicuro di voler rimuovere il contenuto?",
"contents.removeConfirmTitle": "Cancella il contenuto",
@ -469,7 +466,7 @@
"contributors.importTitle": "Importa collaboratori",
"contributors.loadFailed": "Non è stato possibile caricare contributors. Per favore ricarica.",
"contributors.planHint": "Il tuo piano prevede un numero massimo di {maxContributors} collaboratori.",
"contributors.refreshTooltip": "Aggiorna i collaboratori (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "Aggiorna i collaboratori",
"contributors.reloaded": "Collaboratori aggiornati.",
"contributors.search": "Cerca",
"contributors.userNotFound": "L'utente non esiste.",
@ -517,7 +514,7 @@
"eventConsumers.loadFailed": "Non è stato possibile caricare event consumers. Per favore ricarica.",
"eventConsumers.pageTitle": "Eventi degli utenti",
"eventConsumers.position": "Posizione",
"eventConsumers.refreshTooltip": "Aggiorna gli eventi degli utenti (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "Aggiorna gli eventi degli utenti",
"eventConsumers.reloaded": "Eventi degli utenti aggiornati.",
"eventConsumers.resetFailed": "Non è stato possibile ripristinare gli eventi degli utenti. Per favore ricarica.",
"eventConsumers.resetTooltip": "Ripristina gli event degli utenti",
@ -538,7 +535,7 @@
"languages.masterHint": "Se non è stata impostata nessuna lingua come alternativa, le altre lingue hanno la lingua principale come alternativa.",
"languages.optional": "È Opzionale",
"languages.optionalHint": "Se sono presenti campi obbligatori questi non devono essere compilati anche per le lingue opzionali.",
"languages.refreshTooltip": "Aggiorna le lingue (CTRL + SHIFT + R)",
"languages.refreshTooltip": "Aggiorna le lingue",
"languages.reloaded": "Lingue ricaricate.",
"languages.updateFailed": "Non è stato possibile cambiare la lingua. Per favore ricarica.",
"news.headline": "Che cosa c'è di nuovo?",
@ -558,7 +555,7 @@
"plans.notPlanOwner": "Non hai creato nessun abbonamento, pertanto non è possibile cambiare il piano.",
"plans.perMonth": "Al mese",
"plans.perYear": "all'anno",
"plans.refreshTooltip": "Aggiorna i piani (CTRL + SHIFT + R)",
"plans.refreshTooltip": "Aggiorna i piani",
"plans.reloaded": "Piano aggiornati.",
"plans.selected": "Selezionato",
"profile.title": "Profilo",
@ -583,7 +580,7 @@
"roles.properties.hideSchemas": "Nascondi gli Schemi",
"roles.properties.hideSettings": "Nascondi le impostazioni",
"roles.propertiesDescription": "Le proprietà descrivono il comportamento nelle Interfacce Utente, ma non garantiscono la sicurezza per le API.",
"roles.refreshTooltip": "Aggiorna i ruoli (CTRL + SHIFT + R)",
"roles.refreshTooltip": "Aggiorna i ruoli",
"roles.reloaded": "Ruoli ricaricati.",
"roles.revokeFailed": "Non è stato possibile rimuovere il ruolo. Per favore ricarica.",
"roles.roleNamePlaceholder": "Inserisci il nome del ruolo",
@ -591,7 +588,7 @@
"rules.cancelFailed": "Non è stato possibile eliminare la regola. Per favore ricarica.",
"rules.create": "Crea un nuova Regola",
"rules.createFailed": "Non è stato possibile creare una nuova regola. Per favore ricarica.",
"rules.createTooltip": "Nuova regola (CTRL + SHIFT + G)",
"rules.createTooltip": "Nuova regola",
"rules.deleteConfirmText": "Sei sicuro di voler eliminare la regola?",
"rules.deleteConfirmTitle": "Cancella la regola",
"rules.deleteFailed": "Non è stato possibile eliminare la regola. Per favore ricarica.",
@ -601,8 +598,8 @@
"rules.listPageTitle": "Regole",
"rules.loadFailed": "Non è stato possibile caricare le regole. Per favore ricarica.",
"rules.readMore": "Leggi di più",
"rules.refreshEventsTooltip": "Aggiorna gli Eventi (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Aggiorna le Regole (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "Aggiorna gli Eventi",
"rules.refreshTooltip": "Aggiorna le Regole",
"rules.reloaded": "Regole ricaricate.",
"rules.restarted": "La Regola sarà eseguita fra pochi secondi.",
"rules.ruleEvents.cancelFailed": "Non è stato possibile cancellare l'evento della regola. Per favore ricarica.",
@ -646,7 +643,7 @@
"schemas.create": "Crea uno Schema",
"schemas.createCategory": "Crea una nuova categoria...",
"schemas.createFailed": "Non è stato possibile creare lo schema. Per favore ricarica.",
"schemas.createSchemaTooltip": "Nuovo Schema (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "Nuovo Schema",
"schemas.deleteConfirmText": "Sei sicuro di voler eliminare lo schema?",
"schemas.deleteConfirmTitle": "Cancella lo schema",
"schemas.deleteFailed": "Non è stato possibile cancellare lo schema. Per favore ricarica.",
@ -866,7 +863,7 @@
"users.createFailed": "Non è stato possibile creare l'utente. Per favore ricarica.",
"users.createPageTitle": "Crea un utente",
"users.createTitle": "Nuovo utente",
"users.createTooltip": "Nuovo utente (CTRL + N)",
"users.createTooltip": "Nuovo utente",
"users.deleteConfirmText": "Sei sicuro di voler eliminare questo utente?",
"users.deleteConfirmTitle": "Elimina utente",
"users.deleteFailed": "Non è stato possibile eliminare l'utente. Per favore ricarica.",
@ -879,7 +876,7 @@
"users.lockFailed": "Non è stato possibile bloccare l'utente. Per favore ricarica.",
"users.lockTooltip": "Utente bloccato",
"users.passwordConfirmValidationMessage": "Le password devono essere uguali.",
"users.refreshTooltip": "Aggiorna gli Utenti (CTRL + SHIFT + R)",
"users.refreshTooltip": "Aggiorna gli Utenti",
"users.reloaded": "Utenti ricaricati.",
"users.search": "Cerca l'utente",
"users.unlockFailed": "Non è stato possibile sbloccare l'utente. Per favore ricarica.",
@ -918,7 +915,7 @@
"workflows.notNamed": "Workflow senza nome",
"workflows.preventUpdates": "Impedisci gli aggiornamenti",
"workflows.publishedNotRemovable": "Non è possibile rimuoverlo",
"workflows.refreshTooltip": "Aggiorna i workflow (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "Aggiorna i workflow",
"workflows.reloaded": "Workflow ricaricati.",
"workflows.saved": "Il Workflow è stato salvato.",
"workflows.schemasHint": "Limita questo workflow ad uno schema specifico, o lascialo bianco per applicarlo a tutti gli schemi.",

39
backend/i18n/source/frontend_nl.json

@ -36,8 +36,6 @@
"apps.removeImage": "Afbeelding verwijderen",
"apps.removeImageFailed": "Verwijderen van app-afbeelding is mislukt. Laad opnieuw.",
"apps.updateFailed": "Update app mislukt. Laad opnieuw.",
"apps.upgradeHintCurrent": "Je zit in het plan {plan}.",
"apps.upgradeHintUpgrade": "Upgrade!",
"apps.uploadImage": "Zet een bestand neer om de app-afbeelding te vervangen. Gebruik een vierkant formaat.",
"apps.uploadImageButton": "Upload bestand",
"apps.uploadImageFailed": "Uploaden van afbeelding is mislukt. Laad opnieuw.",
@ -49,7 +47,7 @@
"appSettings.patterns.empty": "Nog geen patroon gemaakt.",
"assets.createFolder": "Map maken",
"assets.createFolderFailed": "Maken van een map is mislukt. Laad opnieuw.",
"assets.createFolderTooltip": "Nieuwe map maken (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "Nieuwe map maken",
"assets.deleteConfirmText": "Weet je zeker dat je het item wilt verwijderen?",
"assets.deleteConfirmTitle": "Item verwijderen",
"assets.deleteFailed": "Verwijderen van item is mislukt. Laad opnieuw.",
@ -80,7 +78,7 @@
"assets.metadataAdd": "Metadata toevoegen",
"assets.moveFailed": "Verplaatsen van item is mislukt. Laad opnieuw.",
"assets.protected": "Beschermd",
"assets.refreshTooltip": "Bestanden vernieuwen (CTRL + SHIFT + R)",
"assets.refreshTooltip": "Bestanden vernieuwen",
"assets.reloaded": "Bestanden herladen.",
"assets.removeConfirmText": "Wil je het bestand echt verwijderen?",
"assets.removeConfirmTitle": "Verwijder bestand",
@ -119,7 +117,7 @@
"backups.empty": "Nog geen back-ups gemaakt.",
"backups.loadFailed": "Laden van back-ups is mislukt.",
"backups.maximumReached": "Je hebt het maximale aantal back-ups bereikt: 10",
"backups.refreshTooltip": "Vernieuw back-ups (CTRL + SHIFT + R)",
"backups.refreshTooltip": "Vernieuw back-ups",
"backups.reloaded": "Back-ups herladen.",
"backups.restore": "Back-up herstellen",
"backups.restoreFailed": "Starten van herstel is mislukt.",
@ -174,7 +172,7 @@
"clients.deleteConfirmTitle": "Client intrekken",
"clients.empty": "Nog geen client aangemaakt.",
"clients.loadFailed": "Kan clients niet laden. Laad opnieuw.",
"clients.refreshTooltip": "Ververs clients (CTRL + SHIFT + R)",
"clients.refreshTooltip": "Ververs clients",
"clients.reloaded": "Clients herladen.",
"clients.revokeFailed": "Kan client niet intrekken. Laad opnieuw.",
"clients.tokenFailed": "Maken van token is mislukt. Probeer het opnieuw.",
@ -297,7 +295,6 @@
"common.rules": "Regels",
"common.sampleCodeLabel": "Voorbeeldcode bij",
"common.save": "Opslaan",
"common.saveShortcut": "CTRL + S",
"common.schemas": "Schema's",
"common.searchGoogleMaps": "Zoeken in Google Maps",
"common.searchResults": "Zoekresultaten",
@ -345,7 +342,7 @@
"contents.changeStatusToLater": "Zet op {action} op een latere datum en tijd.",
"contents.contentNotValid": "Inhoudselement niet geldig, controleer het veld met de rode balk aan de linkerkant in alle talen (indien lokaliseerbaar).",
"contents.create": "Nieuw",
"contents.createContentTooltip": "Nieuwe inhoud (CTRL + SHIFT + G)",
"contents.createContentTooltip": "Nieuwe inhoud",
"contents.created": "Inhoud succesvol aangemaakt.",
"contents.createdByFieldDescription": "De gebruiker die het inhoudsitem heeft gemaakt.",
"contents.createFailed": "Maken van inhoud is mislukt. Laad opnieuw.",
@ -385,7 +382,7 @@
"contents.referencesLink": "Link geselecteerde inhoud ({count})",
"contents.referencesSelectExisting": "Selecteer bestaande",
"contents.referencesSelectSchema": "Selecteer {schema}",
"contents.refreshTooltip": "Ververs inhoud (CTRL + SHIFT + R)",
"contents.refreshTooltip": "Ververs inhoud",
"contents.reloaded": "Inhoud opnieuw geladen.",
"contents.removeConfirmText": "Wil je de inhoud echt verwijderen?",
"contents.removeConfirmTitle": "Verwijder inhoud",
@ -441,7 +438,7 @@
"contributors.importTitle": "Bijdragers importeren",
"contributors.loadFailed": "Laden van bijdragers is mislukt. Laad opnieuw.",
"contributors.planHint": "Uw plan staat maximaal {maxContributors} bijdragers toe.",
"contributors.refreshTooltip": "Bijdragers vernieuwen (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "Bijdragers vernieuwen",
"contributors.reloaded": "Contributors reloaded.",
"contributors.search": "Zoeken",
"contributors.userNotFound": "De gebruiker bestaat niet.",
@ -489,7 +486,7 @@
"eventConsumers.loadFailed": "Kan gebeurtenisgebruikers niet laden. Laad opnieuw.",
"eventConsumers.pageTitle": "Evenementconsumenten",
"eventConsumers.position": "Positie",
"eventConsumers.refreshTooltip": "Ververs evenementgebruikers (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "Ververs evenementgebruikers",
"eventConsumers.reloaded": "Evenementconsumenten herladen.",
"eventConsumers.resetFailed": "Kan gebeurtenisgebruiker niet resetten. Laad opnieuw.",
"eventConsumers.resetTooltip": "Reset Event Consumer",
@ -510,7 +507,7 @@
"languages.masterHint": "Andere talen vallen terug op de master als er geen fallback is gedefinieerd.",
"languages.optional": "Is optioneel",
"languages.optionalHint": "Waarden voor optionele talen mogen niet worden ingevoerd, zelfs niet als dit veld vereist is.",
"languages.refreshTooltip": "Ververs talen (CTRL + SHIFT + R)",
"languages.refreshTooltip": "Ververs talen",
"languages.reloaded": "Talen herladen.",
"languages.updateFailed": "Het wijzigen van de taal is mislukt. Laad opnieuw.",
"news.headline": "Wat is er nieuw?",
@ -530,7 +527,7 @@
"plans.notPlanOwner": "Je hebt geen abonnement aangemaakt. Daarom kun je het plan niet wijzigen.",
"plans.perMonth": "Per maand",
"plans.perYear": "Per jaar",
"plans.refreshTooltip": "Plannen vernieuwen (CTRL + SHIFT + R)",
"plans.refreshTooltip": "Plannen vernieuwen",
"plans.reloaded": "Plans reloaded.",
"plans.selected": "Geselecteerd",
"profile.title": "Profiel",
@ -555,7 +552,7 @@
"roles.properties.hideSchemas": "Verberg schema's",
"roles.properties.hideSettings": "Verberg instellingen",
"roles.propertiesDescription": " Eigenschappen beschrijven het gedrag van de beheerinterface, maar bieden geen beveiliging voor de API. ",
"roles.refreshTooltip": "Ververs rollen (CTRL + SHIFT + R)",
"roles.refreshTooltip": "Ververs rollen",
"roles.reloaded": "Rollen opnieuw geladen.",
"roles.revokeFailed": "Kan rol niet intrekken. Laad opnieuw.",
"roles.roleNamePlaceholder": "Voer de rolnaam in",
@ -563,7 +560,7 @@
"rules.cancelFailed": "Annuleren van regel is mislukt. Laad opnieuw.",
"rules.create": "Maak een nieuwe regel",
"rules.createFailed": "Maken van regel is mislukt. Laad opnieuw.",
"rules.createTooltip": "Nieuwe regel (CTRL + SHIFT + G)",
"rules.createTooltip": "Nieuwe regel",
"rules.deleteConfirmText": "Wil je de regel echt verwijderen?",
"rules.deleteConfirmTitle": "Regel verwijderen",
"rules.deleteFailed": "Verwijderen van regel is mislukt. Laad opnieuw.",
@ -573,8 +570,8 @@
"rules.listPageTitle": "Regels",
"rules.loadFailed": "Laden van regels is mislukt. Laad opnieuw.",
"rules.readMore": "Lees meer",
"rules.refreshEventsTooltip": "Ververs evenementen (CTRL + SHIFT + R)",
"rules.refreshTooltip": "Vernieuwingsregels (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "Ververs evenementen",
"rules.refreshTooltip": "Vernieuwingsregels",
"rules.reloaded": "Regels herladen.",
"rules.restarted": "Regel begint over een paar seconden te lopen.",
"rules.ruleEvents.cancelFailed": "Annuleren van regelgebeurtenis is mislukt. Laad opnieuw.",
@ -617,7 +614,7 @@
"schemas.create": "Schema maken",
"schemas.createCategory": "Nieuwe categorie maken ...",
"schemas.createFailed": "Kan schema niet maken. Laad opnieuw.",
"schemas.createSchemaTooltip": "Nieuw schema (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "Nieuw schema",
"schemas.deleteConfirmText": "Weet je zeker dat je het schema wilt verwijderen?",
"schemas.deleteConfirmTitle": "Schema verwijderen",
"schemas.deleteFailed": "Kan schema niet verwijderen. Laad opnieuw.",
@ -828,7 +825,7 @@
"users.createFailed": "Aanmaken van gebruiker mislukt. Laad opnieuw.",
"users.createPageTitle": "Gebruiker aanmaken",
"users.createTitle": "Nieuwe gebruiker",
"users.createTooltip": "Nieuwe gebruiker (CTRL + N)",
"users.createTooltip": "Nieuwe gebruiker",
"users.editPageTitle": "Gebruiker bewerken",
"users.editTitle": "Gebruiker bewerken",
"users.listPageTitle": "Gebruikersbeheer",
@ -837,7 +834,7 @@
"users.loadUserFailed": "Kan gebruiker niet laden. Laad opnieuw.",
"users.lockTooltip": "Gebruiker vergrendelen",
"users.passwordConfirmValidationMessage": "Wachtwoorden moeten hetzelfde zijn.",
"users.refreshTooltip": "Ververs gebruikers (CTRL + SHIFT + R)",
"users.refreshTooltip": "Ververs gebruikers",
"users.reloaded": "Gebruikers herladen.",
"users.search": "Zoeken naar gebruiker",
"users.unlockTooltip": "Gebruiker ontgrendelen",
@ -875,7 +872,7 @@
"workflows.notNamed": "Naamloze workflow",
"workflows.preventUpdates": "Updates voorkomen",
"workflows.publishedNotRemovable": "Kan niet worden verwijderd",
"workflows.refreshTooltip": "Werkstromen vernieuwen (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "Werkstromen vernieuwen",
"workflows.reloaded": "Workflows opnieuw geladen.",
"workflows.saved": "Workflow is opgeslagen.",
"workflows.schemasHint": "Beperk deze workflow tot specifieke schema's of laat het leeg voor alle schema's.",

72
backend/i18n/source/frontend_zh.json

@ -42,8 +42,6 @@
"apps.removeImageFailed": "删除应用图片失败。请重新加载。",
"apps.updateFailed": "更新应用失败。请重新加载。",
"apps.updateSettingsFailed": "更新界面设置失败。请重新加载。",
"apps.upgradeHintCurrent": "你在 {plan} 计划中。",
"apps.upgradeHintUpgrade": "升级!",
"apps.uploadImage": "拖放文件以替换应用图片。使用正方形大小。",
"apps.uploadImageButton": "上传文件",
"apps.uploadImageFailed": "上传图片失败,请重新加载。",
@ -59,12 +57,12 @@
"appSettings.patterns.deleteConfirmTitle": "删除模式",
"appSettings.patterns.empty": "尚未创建模式。",
"appSettings.patterns.title": "模式",
"appSettings.refreshTooltip": "刷新 UI 设置 (CTRL + SHIFT + R)",
"appSettings.refreshTooltip": "刷新 UI 设置",
"appSettings.reloaded": "UI 设置重新加载。",
"appSettings.title": "界面设置",
"assets.createFolder": "创建文件夹",
"assets.createFolderFailed": "资源文件夹创建失败,请重新加载。",
"assets.createFolderTooltip": "创建新文件夹 (CTRL + SHIFT + G)",
"assets.createFolderTooltip": "创建新文件夹",
"assets.deleteConfirmText": "你真的要删除资源吗?",
"assets.deleteConfirmTitle": "删除资源",
"assets.deleteFailed": "资源删除失败,请重新加载。",
@ -77,7 +75,6 @@
"assets.downloadVersion": "下载此版本",
"assets.dropToUpdate": "下拉更新",
"assets.duplicateFile": "资源已经上传。",
"assets.editor.flipHorizo​​ntally": "水平翻转",
"assets.editor.flipVertically": "垂直翻转",
"assets.editor.focusPointLabel": "选择焦点位置",
"assets.editor.focusPointPreview": "不同尺寸的预览",
@ -95,7 +92,7 @@
"assets.metadataAdd": "添加元数据",
"assets.moveFailed": "资源移动失败。请重新加载。",
"assets.protected": "受保护",
"assets.refreshTooltip": "刷新资源 (CTRL + SHIFT + R)",
"assets.refreshTooltip": "刷新资源",
"assets.reloaded": "资源重新加载。",
"assets.removeConfirmText": "你真的要移除资源吗?",
"assets.removeConfirmTitle": "移除资源",
@ -136,7 +133,7 @@
"backups.empty": "尚未创建备份。",
"backups.loadFailed": "加载备份失败。",
"backups.maximumReached": "您已达到最大备份数:10。",
"backups.refreshTooltip": "刷新备份 (CTRL + SHIFT + R)",
"backups.refreshTooltip": "刷新备份",
"backups.reloaded": "备份已重新加载。",
"backups.restore": "恢复备份",
"backups.restoreFailed": "无法开始恢复。",
@ -191,7 +188,7 @@
"clients.deleteConfirmTitle": "撤销客户端",
"clients.empty": "尚未创建客户端。",
"clients.loadFailed": "加载客户端失败。请重新加载。",
"clients.refreshTooltip": "刷新客户端 (CTRL + SHIFT + R)",
"clients.refreshTooltip": "刷新客户端",
"clients.reloaded": "客户端重新加载。",
"clients.revokeFailed": "撤销客户端失败。请重新加载。",
"clients.tokenFailed": "创建令牌失败。请重试。",
@ -328,8 +325,6 @@
"common.rules": "规则",
"common.sampleCodeLabel": "示例代码在",
"common.save": "保存",
"common.saveShortcut": "CTRL + S",
"common.schema": "Schemas",
"common.search": "搜索",
"common.searchGoogleMaps": "搜索谷歌地图",
"common.searchResults": "搜索结果",
@ -337,7 +332,6 @@
"common.settings": "设置",
"common.sidebar": "侧边栏扩展",
"common.sidebarTour": "侧边栏导航包含有用的上下文特定链接。您可以在此处查看此Schemas随时间变化的历史记录。",
"common.skiped": "跳过",
"common.slug": "弹头",
"common.stars.max": "不得超过 15 颗星",
"common.status": "状态",
@ -388,7 +382,7 @@
"contents.contentTab.references": "参考资料",
"contents.contentTab.referencing": "引用",
"contents.create": "新建",
"contents.createContentTooltip": "新建内容 (CTRL + SHIFT + G)",
"contents.createContentTooltip": "新建内容",
"contents.created": "内容创建成功。",
"contents.createdByFieldDescription": "创建内容项的用户。",
"contents.createFailed": "创建内容失败,请重新加载。",
@ -432,7 +426,7 @@
"contents.referencesLink": "链接所选内容 ({count})",
"contents.referencesSelectExisting": "选择现有",
"contents.referencesSelectSchema": "选择 {schema}",
"contents.refreshTooltip": "刷新内容 (CTRL + SHIFT + R)",
"contents.refreshTooltip": "刷新内容",
"contents.reloaded": "内容已重新加载。",
"contents.removeConfirmText": "您真的要删除内容吗?",
"contents.removeConfirmTitle": "删除内容",
@ -494,7 +488,7 @@
"contributors.importTitle": "导入贡献者",
"contributors.loadFailed": "加载贡献者失败。请重新加载。",
"contributors.planHint": "您的计划允许最多 {maxContributors} 个贡献者。",
"contributors.refreshTooltip": "刷新贡献者 (CTRL + SHIFT + R)",
"contributors.refreshTooltip": "刷新贡献者",
"contributors.reloaded": "贡献者重新加载。",
"contributors.search": "搜索",
"contributors.userNotFound": "用户不存在。",
@ -542,7 +536,7 @@
"eventConsumers.loadFailed": "加载事件消费者失败。请重新加载。",
"eventConsumers.pageTitle": "事件消费者",
"eventConsumers.position": "位置",
"eventConsumers.refreshTooltip": "刷新事件消费者 (CTRL + SHIFT + R)",
"eventConsumers.refreshTooltip": "刷新事件消费者",
"eventConsumers.reloaded": "事件消费者重新加载。",
"eventConsumers.resetFailed": "无法重置事件消费者。请重新加载。",
"eventConsumers.resetTooltip": "重置事件消费者",
@ -563,7 +557,7 @@
"languages.masterHint": "如果没有定义回退,其他语言回退到母版。",
"languages.optional": "是可选的",
"languages.optionalHint": "不得输入可选语言的值,即使字段是必需的。",
"languages.refreshTooltip": "刷新语言 (CTRL + SHIFT + R)",
"languages.refreshTooltip": "刷新语言",
"languages.reloaded": "语言已重新加载。",
"languages.updateFailed": "更改语言失败。请重新加载。",
"news.headline": "有什么新鲜事?",
@ -583,7 +577,7 @@
"plans.notPlanOwner": "您尚未创建订阅。因此您无法更改计划。",
"plans.perMonth": "每月",
"plans.perYear": "每年",
"plans.refreshTooltip": "刷新计划 (CTRL + SHIFT + R)",
"plans.refreshTooltip": "刷新计划",
"plans.reloaded": "计划重新加载。",
"plans.selected": "已选择",
"profile.title": "个人资料",
@ -608,7 +602,7 @@
"roles.properties.hideSchemas": "隐藏Schemas",
"roles.properties.hideSettings": "隐藏设置",
"roles.propertiesDescription": "属性描述管理 UI 的行为,但不为 API 提供安全性。",
"roles.refreshTooltip": "刷新角色 (CTRL + SHIFT + R)",
"roles.refreshTooltip": "刷新角色",
"roles.reloaded": "重新加载角色。",
"roles.revokeFailed": "撤销角色失败,请重新加载。",
"roles.roleNamePlaceholder": "输入角色名称",
@ -618,7 +612,7 @@
"rules.cancelFailed": "取消规则失败,请重新加载。",
"rules.create": "新规则",
"rules.createFailed": "创建规则失败。请重新加载。",
"rules.createTooltip": "新规则 (CTRL + SHIFT + G)",
"rules.createTooltip": "新规则",
"rules.deleteConfirmText": "你真的要删除规则吗?",
"rules.deleteConfirmTitle": "删除规则",
"rules.deleteFailed": "删除规则失败,请重新加载。",
@ -629,8 +623,8 @@
"rules.listPageTitle": "规则",
"rules.loadFailed": "加载规则失败。请重新加载。",
"rules.readMore": "阅读更多",
"rules.refreshEventsTooltip": "刷新事件 (CTRL + SHIFT + R)",
"rules.refreshTooltip": "刷新规则 (CTRL + SHIFT + R)",
"rules.refreshEventsTooltip": "刷新事件",
"rules.refreshTooltip": "刷新规则",
"rules.reloaded": "规则重新加载。",
"rules.restarted": "规则将在几秒钟后开始运行。",
"rules.ruleEvents.cancelFailed": "取消规则事件失败。请重新加载。",
@ -662,34 +656,6 @@
"rules.triggerHint": "以后不能更改触发器类型的选择。",
"rules.unnamed": "未命名规则",
"rules.updateFailed": "更新规则失败。请重新加载。",
"schema.clone": "克隆Schemas",
"schema.create": "创建Schemas",
"schema.field.defaultValue": "默认值",
"schema.field.editor": "编辑器",
"schema.field.hiddenMarker": "隐藏",
"schema.field.localizable": "Localizable",
"schema.field.localizableMarker": "localizable",
"schema.field.placeholder": "占位符",
"schema.field.required": "必需",
"schema.field.tabEditing": "编辑",
"schema.field.tabValidation": "验证",
"schema.field.unique": "唯一",
"schema.field.visibleMarker": "可见",
"schema.fieldTypes.array.count": "项目",
"schema.fieldTypes.assets.size": "大小",
"schema.fieldTypes.string.length": "长度",
"schema.fieldTypes.string.lengthMax": "最大长度",
"schema.fieldTypes.string.pattern": "正则表达式",
"schema.loadSchemaFailed": "加载Schemas失败。请重新加载。",
"schema.modeComponent": "组件",
"schema.published": "已发布",
"schema.reloaded": "Schemas已重新加载。",
"schema.saved": "Schemas保存成功。",
"schema.synchronized": "Schemas同步成功。",
"schema.tabMore": "更多",
"schema.tabScripts": "脚本",
"schema.tabUI": "UI",
"schema.unpublished": "未发布",
"schemas.addField": "添加字段",
"schemas.addFieldAndClose": "创建并关闭",
"schemas.addFieldAndCreate": "创建并添加字段",
@ -706,7 +672,7 @@
"schemas.contextMenuTour": "打开上下文菜单以删除Schemas或为内容更改创建一些脚本。",
"schemas.createCategory": "创建新类别...",
"schemas.createFailed": "无法创建Schemas。请重新加载。",
"schemas.createSchemaTooltip": "新Schemas (CTRL + SHIFT + G)",
"schemas.createSchemaTooltip": "新Schemas",
"schemas.deleteConfirmText": "您真的要删除Schemas吗?",
"schemas.deleteConfirmTitle": "删除Schemas",
"schemas.deleteFailed": "删除Schemas失败。请重新加载。",
@ -908,7 +874,7 @@
"users.createFailed": "创建用户失败,请重新加载。",
"users.createPageTitle": "创建用户",
"users.createTitle": "新用户",
"users.createTooltip": "新用户 (CTRL + N)",
"users.createTooltip": "新用户",
"users.deleteConfirmText": "你真的要删除这个用户吗?",
"users.deleteConfirmTitle": "删除用户",
"users.deleteFailed": "删除用户失败,请重新加载。",
@ -921,7 +887,7 @@
"users.lockFailed": "锁定用户失败。请重新加载。",
"users.lockTooltip": "锁定用户",
"users.passwordConfirmValidationMessage": "密码必须相同。",
"users.refreshTooltip": "刷新用户 (CTRL + SHIFT + R)",
"users.refreshTooltip": "刷新用户",
"users.reloaded": "用户重新加载。",
"users.search": "搜索用户",
"users.unlockFailed": "解锁用户失败。请重新加载。",
@ -960,7 +926,7 @@
"workflows.notNamed": "未命名的工作流程",
"workflows.preventUpdates": "防止更新",
"workflows.publishedNotRemovable": "无法删除",
"workflows.refreshTooltip": "刷新工作流 (CTRL + SHIFT + R)",
"workflows.refreshTooltip": "刷新工作流",
"workflows.reloaded": "工作流已重新加载。",
"workflows.saved": "工作流已保存。",
"workflows.schemasHint": "将此工作流限制为特定Schemas或将其保留为所有Schemas的空。",

3
backend/src/Squidex.Shared/Texts.it.resx

@ -1168,6 +1168,9 @@
<data name="validation.notAnImage" xml:space="preserve">
<value>L'immagine non è un'immagine valida.</value>
</data>
<data name="validation.notAnValidSvg" xml:space="preserve">
<value>The SVG is malicious and contains script tags.</value>
</data>
<data name="validation.onlyOneFile" xml:space="preserve">
<value>Puoi caricare solo un file.</value>
</data>

3
backend/src/Squidex.Shared/Texts.nl.resx

@ -1168,6 +1168,9 @@
<data name="validation.notAnImage" xml:space="preserve">
<value>Afbeelding is geen geldige afbeelding.</value>
</data>
<data name="validation.notAnValidSvg" xml:space="preserve">
<value>The SVG is malicious and contains script tags.</value>
</data>
<data name="validation.onlyOneFile" xml:space="preserve">
<value>Kan slechts één bestand uploaden.</value>
</data>

3
backend/src/Squidex.Shared/Texts.resx

@ -1168,6 +1168,9 @@
<data name="validation.notAnImage" xml:space="preserve">
<value>Picture is not a valid image.</value>
</data>
<data name="validation.notAnValidSvg" xml:space="preserve">
<value>The SVG is malicious and contains script tags.</value>
</data>
<data name="validation.onlyOneFile" xml:space="preserve">
<value>Can only upload one file.</value>
</data>

3
backend/src/Squidex.Shared/Texts.zh.resx

@ -1168,6 +1168,9 @@
<data name="validation.notAnImage" xml:space="preserve">
<value>图片不是有效图片。</value>
</data>
<data name="validation.notAnValidSvg" xml:space="preserve">
<value>The SVG is malicious and contains script tags.</value>
</data>
<data name="validation.onlyOneFile" xml:space="preserve">
<value>只能上传一个文件。</value>
</data>

11
backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -39,21 +39,18 @@ namespace Squidex.Areas.Api.Controllers.Apps
{
private static readonly ResizeOptions ResizeOptions = new ResizeOptions { Width = 50, Height = 50, Mode = ResizeMode.Crop };
private readonly IAppImageStore appImageStore;
private readonly IAppPlansProvider appPlansProvider;
private readonly IAppProvider appProvider;
private readonly IAssetStore assetStore;
private readonly IAssetThumbnailGenerator assetThumbnailGenerator;
public AppsController(ICommandBus commandBus,
IAppImageStore appImageStore,
IAppPlansProvider appPlansProvider,
IAppProvider appProvider,
IAssetStore assetStore,
IAssetThumbnailGenerator assetThumbnailGenerator)
: base(commandBus)
{
this.appImageStore = appImageStore;
this.appPlansProvider = appPlansProvider;
this.appProvider = appProvider;
this.assetStore = assetStore;
this.assetThumbnailGenerator = assetThumbnailGenerator;
@ -85,7 +82,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
{
var isFrontend = HttpContext.User.IsInClient(DefaultClients.Frontend);
return apps.OrderBy(x => x.Name).Select(a => AppDto.FromApp(a, userOrClientId, isFrontend, appPlansProvider, Resources)).ToArray();
return apps.OrderBy(x => x.Name).Select(a => AppDto.FromApp(a, userOrClientId, isFrontend, Resources)).ToArray();
});
Response.Headers[HeaderNames.ETag] = apps.ToEtag();
@ -114,7 +111,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
var isFrontend = HttpContext.User.IsInClient(DefaultClients.Frontend);
return AppDto.FromApp(App, userOrClientId, isFrontend, appPlansProvider, Resources);
return AppDto.FromApp(App, userOrClientId, isFrontend, Resources);
});
Response.Headers[HeaderNames.ETag] = App.ToEtag();
@ -354,7 +351,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
var isFrontend = HttpContext.User.IsInClient(DefaultClients.Frontend);
return AppDto.FromApp(x, userOrClientId, isFrontend, appPlansProvider, Resources);
return AppDto.FromApp(x, userOrClientId, isFrontend, Resources);
});
}

22
backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs

@ -84,28 +84,15 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
/// </summary>
public bool CanAccessContent { get; set; }
/// <summary>
/// Gets the current plan name.
/// </summary>
public string? PlanName { get; set; }
/// <summary>
/// Gets the next plan name.
/// </summary>
public string? PlanUpgrade { get; set; }
/// <summary>
/// The properties from the role.
/// </summary>
[LocalizedRequired]
public JsonObject RoleProperties { get; set; } = EmptyObject;
public static AppDto FromApp(IAppEntity app, string userId, bool isFrontend, IAppPlansProvider plans, Resources resources)
public static AppDto FromApp(IAppEntity app, string userId, bool isFrontend, Resources resources)
{
var result = SimpleMapper.Map(app, new AppDto
{
PlanName = plans.GetPlanForApp(app).Plan.Name
});
var result = SimpleMapper.Map(app, new AppDto());
var permissions = PermissionSet.Empty;
@ -126,11 +113,6 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
result.CanAccessContent = true;
}
if (resources.IsAllowed(Shared.Permissions.AppPlansChange, app.Name, additional: permissions))
{
result.PlanUpgrade = plans.GetPlanUpgradeForApp(app)?.Name;
}
return result.CreateLinks(app, resources, permissions, isContributor);
}

27
frontend/.sass-lint.yml

@ -1,27 +0,0 @@
rules:
no-ids:
- 1
no-important:
- 0
final-newline:
- 0
clean-import-paths:
- 0
property-sort-order:
- 1
indentation:
- 2
-
size: 4
nesting-depth:
- 1
-
max-depth: 4
leading-underscore: false
files:
ignore:
- 'app/theme/_mixins.scss'
- 'node_modules/**/*.*'

32
frontend/.stylelintrc.json

@ -0,0 +1,32 @@
{
"extends": "stylelint-config-standard",
"plugins": [
"stylelint-scss"
],
"rules": {
"at-rule-empty-line-before": null,
"at-rule-no-unknown": null,
"selector-class-pattern": "^([a-z][a-z0-9]*)(-[a-z0-9]+)*$",
"declaration-empty-line-before": null,
"indentation": 4,
"no-duplicate-selectors": null,
"no-empty-source": null,
"no-invalid-position-at-import-rule": null,
"no-missing-end-of-source-newline": null,
"number-leading-zero": "never",
"scss/at-rule-no-unknown": true,
"selector-pseudo-element-no-unknown": [
true,
{
"ignorePseudoElements": [
"ng-deep"
]
}
]
},
"ignoreFiles": [
"**/*.cs",
"build/**/*.*",
"node_modules/**/*.*"
]
}

8
frontend/app-config/webpack.config.js

@ -31,8 +31,8 @@ const plugins = {
OptimizeCSSAssetsPlugin: require('optimize-css-assets-webpack-plugin'),
// https://webpack.js.org/plugins/eslint-webpack-plugin/
ESLintPlugin: require('eslint-webpack-plugin'),
// https://www.npmjs.com/package/sass-lint-webpack
SassLintPlugin: require('sass-lint-webpack'),
// https://github.com/webpack-contrib/stylelint-webpack-plugin
StylelintPlugin: require('stylelint-webpack-plugin'),
// https://www.npmjs.com/package/webpack-bundle-analyzer
BundleAnalyzerPlugin: require('webpack-bundle-analyzer').BundleAnalyzerPlugin,
// https://www.npmjs.com/package/@angular-devkit/build-optimizer
@ -233,7 +233,9 @@ module.exports = function calculateConfig(env) {
},
}),
new plugins.SassLintPlugin(),
new plugins.StylelintPlugin({
files: '**/*.scss',
}),
/*
* Detect circular dependencies in app.

784
frontend/app/_theme.html

File diff suppressed because it is too large

2
frontend/app/features/administration/administration-area.component.html

@ -25,6 +25,6 @@
</ul>
</div>
<div sqxPanelContainer class="panel-container">
<div sqxLayoutContainer class="panel-container">
<router-outlet></router-outlet>
</div>

8
frontend/app/features/administration/pages/cluster/cluster-page.component.html

@ -1,7 +1,5 @@
<sqx-title message="i18n:common.clusterPageTitle"></sqx-title>
<sqx-panel desiredWidth="*" minWidth="50rem" [isFullSize]="true">
<div inner>
<iframe src="./orleans"></iframe>
</div>
</sqx-panel>
<div inner>
<iframe src="./orleans"></iframe>
</div>

6
frontend/app/features/administration/pages/event-consumers/event-consumer.component.html

@ -13,13 +13,13 @@
<span>{{eventConsumer.position}}</span>
</td>
<td class="cell-actions-lg">
<button type="button" class="btn btn-text" (click)="reset()" *ngIf="eventConsumer.canReset" title="i18n:eventConsumers.resetTooltip">
<button type="button" class="btn btn-text-secondary" (click)="reset()" *ngIf="eventConsumer.canReset" title="i18n:eventConsumers.resetTooltip">
<i class="icon icon-reset"></i>
</button>
<button type="button" class="btn btn-text" (click)="start()" *ngIf="eventConsumer.canStart" title="i18n:eventConsumers.startTooltip">
<button type="button" class="btn btn-text-secondary" (click)="start()" *ngIf="eventConsumer.canStart" title="i18n:eventConsumers.startTooltip">
<i class="icon icon-play"></i>
</button>
<button type="button" class="btn btn-text" (click)="stop()" *ngIf="eventConsumer.canStop" title="i18n:eventConsumers.stopTooltip">
<button type="button" class="btn btn-text-secondary" (click)="stop()" *ngIf="eventConsumer.canStop" title="i18n:eventConsumers.stopTooltip">
<i class="icon icon-pause"></i>
</button>
</td>

20
frontend/app/features/administration/pages/event-consumers/event-consumers-page.component.html

@ -1,20 +1,14 @@
<sqx-title message="i18n:eventConsumers.pageTitle"></sqx-title>
<sqx-panel theme="light" desiredWidth="50rem" [grid]="true">
<ng-container title>
{{ 'common.consumers' | sqxTranslate }}
</ng-container>
<sqx-layout layout="main" titleText="i18n:common.consumers" titleIcon="time" [width]="50" [hideSidebar]="true">
<ng-container menu>
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:eventConsumers.refreshTooltip">
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:eventConsumers.refreshTooltip" shortcut="CTRL + B">
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
</ng-container>
<ng-container content>
<sqx-list-view [isLoading]="eventConsumersState.isLoading | async" [table]="true">
<ng-container>
<sqx-list-view innerWidth="50rem" [isLoading]="eventConsumersState.isLoading | async" [table]="true">
<ng-container header>
<table class="table table-items table-fixed" #header>
<thead>
@ -36,16 +30,16 @@
</table>
</ng-container>
<div content>
<ng-container>
<table class="table table-items table-fixed" [sqxSyncWidth]="header">
<tbody *ngFor="let eventConsumer of eventConsumersState.eventConsumers | async; trackBy: trackByEventConsumer"
[sqxEventConsumer]="eventConsumer" (error)="showError(eventConsumer)">
</tbody>
</table>
</div>
</ng-container>
</sqx-list-view>
</ng-container>
</sqx-panel>
</sqx-layout>
<ng-container *sqxModal="eventConsumerErrorDialog">
<sqx-modal-dialog (close)="eventConsumerErrorDialog.hide()">

8
frontend/app/features/administration/pages/event-consumers/event-consumers-page.component.scss

@ -1,7 +1,5 @@
.faulted {
& {
color: $color-theme-error;
}
color: $color-theme-error;
&-icon {
@include build-icon($color-theme-error);
@ -11,7 +9,3 @@
.error-message {
height: 18rem;
}
.small {
font-size: 90%;
}

30
frontend/app/features/administration/pages/restore/restore-page.component.html

@ -1,15 +1,11 @@
<sqx-title message="i18n:backups.restorePageTitle"></sqx-title>
<sqx-panel theme="light" desiredWidth="70rem">
<ng-container title>
{{ 'backups.restoreTitle' | sqxTranslate }}
</ng-container>
<ng-container content>
<sqx-layout layout="main" titleText="i18n:backups.restoreTitle" titleIcon="backup" [width]="70">
<sqx-list-view innerWidth="70rem">
<div class="card section" *ngIf="restoreJob | async; let job">
<div class="card-header">
<div class="row no-gutters">
<div class="col-auto pr-2">
<div class="row gx-2 align-items-center">
<div class="col-auto">
<div *ngIf="job.status === 'Started'" class="restore-status restore-status-pending spin">
<i class="icon-hour-glass"></i>
</div>
@ -25,7 +21,7 @@
<h3>{{ 'backups.restoreLastStatus' | sqxTranslate }}</h3>
</div>
<div class="col text-right restore-url">
<div class="col text-end restore-url">
{{job.url}}
</div>
</div>
@ -35,28 +31,28 @@
{{row}}
</div>
</div>
<div class="card-footer text-muted">
<div class="card-footer small text-muted">
<div class="row">
<div class="col">
{{ 'backups.restoreStartedLabel' | sqxTranslate }}: {{job.started | sqxISODate}}
</div>
<div class="col text-right" *ngIf="job.stopped">
<div class="col text-end" *ngIf="job.stopped">
{{ 'backups.restoreStoppedLabel' | sqxTranslate }}: {{job.stopped | sqxISODate}}
</div>
</div>
</div>
</div>
<div class="table-items-row">
<div class="table-items-row table-items-row-summary">
<form [formGroup]="restoreForm.form" (ngSubmit)="restore()">
<div class="row no-gutters">
<div class="row gx-2">
<div class="col">
<input class="form-control" formControlName="url" placeholder="{{ 'backups.restoreLastUrl' | sqxTranslate }}">
</div>
<div class="col pl-1">
<div class="col">
<input class="form-control" formControlName="name" placeholder="{{ 'backups.restoreNewAppName' | sqxTranslate }}">
</div>
<div class="col-auto pl-1">
<div class="col-auto">
<button type="submit" class="btn btn-success" [disabled]="restoreForm.hasNoUrl | async">
{{ 'backups.restore' | sqxTranslate }}
</button>
@ -64,5 +60,5 @@
</div>
</form>
</div>
</ng-container>
</sqx-panel>
</sqx-list-view>
</sqx-layout>

26
frontend/app/features/administration/pages/restore/restore-page.component.scss

@ -10,13 +10,8 @@ h3 {
.card {
&-header {
h3 {
line-height: $circle-size;
}
}
&-footer {
font-size: .9rem;
padding-bottom: 1rem;
padding-top: 1rem;
}
&-body {
@ -29,23 +24,22 @@ h3 {
}
}
%default-color {
color: $color-white;
}
.restore {
&-status {
& {
@include circle-icon($circle-size);
background: $color-border;
}
&-failed,
&-success {
color: $color-dark-foreground;
}
@include circle-icon($circle-size);
background: $color-border;
&-failed {
@extend %default-color;
background: $color-theme-error;
}
&-success {
@extend %default-color;
background: $color-theme-green;
}
}

26
frontend/app/features/administration/pages/users/user-page.component.html

@ -1,43 +1,37 @@
<form [formGroup]="userForm.form" (ngSubmit)="save()">
<input style="display:none" type="password" name="foilautofill">
<input style="display: none;" type="password" name="foilautofill">
<sqx-panel desiredWidth="26rem" [isBlank]="true" [isLazyLoaded]="false">
<sqx-layout layout="simple" [width]="30" [white]="true" [padding]="true" [overflow]="true">
<ng-container title>
<ng-container *ngIf="usersState.selectedUser | async; else noUserTitle">
<sqx-title message="i18n:users.editPageTitle"></sqx-title>
{{ 'users.editTitle' | sqxTranslate }}
<h3>{{ 'users.editTitle' | sqxTranslate }}</h3>
</ng-container>
<ng-template #noUserTitle>
<sqx-title message="i18n:users.createPageTitle"></sqx-title>
{{ 'users.createTitle' | sqxTranslate }}
<h3>{{ 'users.createTitle' | sqxTranslate }}</h3>
</ng-template>
</ng-container>
<ng-container menu>
<ng-container *ngIf="usersState.selectedUser | async; let user; else noUserMenu">
<ng-container *ngIf="isEditable">
<button type="submit" class="btn btn-primary" title="i18n:common.saveShortcut">
{{ 'common.save' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+s" (trigger)="save()"></sqx-shortcut>
</ng-container>
<button type="submit" class="btn btn-primary" title="i18n:common.saveShortcut" shortcut="CTRL + SHIFT + S" *ngIf="isEditable">
{{ 'common.save' | sqxTranslate }}
</button>
</ng-container>
<ng-template #noUserMenu>
<button type="submit" class="btn btn-primary" title="i18n:common.saveShortcut">
<button type="submit" class="btn btn-primary" title="i18n:common.saveShortcut" shortcut="CTRL + SHIFT + S">
{{ 'common.save' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+s" (trigger)="save()"></sqx-shortcut>
</ng-template>
</ng-container>
<ng-container content>
<ng-container >
<sqx-form-error [error]="userForm.error | async"></sqx-form-error>
<div class="form-group">
@ -81,5 +75,5 @@
<textarea class="form-control" id="permissions" formControlName="permissions" placeholder="{{ 'common.separateByLine' | sqxTranslate }}" autocomplete="off" spellcheck="false"></textarea>
</div>
</ng-container>
</sqx-panel>
</sqx-layout>
</form>

4
frontend/app/features/administration/pages/users/user.component.html

@ -9,10 +9,10 @@
<span class="user-email table-cell">{{user.email}}</span>
</td>
<td class="cell-actions-lg">
<button type="button" class="btn btn-text" (click)="lock()" sqxStopClick *ngIf="user.canLock" title="i18n:users.lockTooltip">
<button type="button" class="btn btn-text-secondary" (click)="lock()" sqxStopClick *ngIf="user.canLock" title="i18n:users.lockTooltip">
<i class="icon icon-unlocked"></i>
</button>
<button type="button" class="btn btn-text" (click)="unlock()" sqxStopClick *ngIf="user.canUnlock" title="i18n:users.unlockTooltip">
<button type="button" class="btn btn-text-secondary" (click)="unlock()" sqxStopClick *ngIf="user.canUnlock" title="i18n:users.unlockTooltip">
<i class="icon icon-lock"></i>
</button>

47
frontend/app/features/administration/pages/users/users-page.component.html

@ -1,33 +1,28 @@
<sqx-title message="i18n:users.listPageTitle"></sqx-title>
<sqx-panel desiredWidth="50rem" [grid]="true" closeQueryParamsHandling="">
<ng-container title>
{{ 'users.listTitle' | sqxTranslate }}
</ng-container>
<sqx-layout layout="main" titleText="i18n:users.listTitle" titleIcon="user-o" [width]="50">
<ng-container menu>
<button type="button" class="btn btn-text-secondary mr-1" (click)="reload()" title="i18n:users.refreshTooltip">
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<sqx-shortcut keys="ctrl+shift+f" (trigger)="inputFind.focus()"></sqx-shortcut>
<form class="form-inline mr-1" (ngSubmit)="search()">
<input class="form-control" #inputFind [formControl]="usersFilter" placeholder="{{ 'users.search' | sqxTranslate }}">
</form>
<div class="d-flex justify-content-end">
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:users.refreshTooltip" shortcut="CTRL + B">
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }}
</button>
<ng-container *ngIf="usersState.canCreate | async">
<sqx-shortcut keys="ctrl+shift+n" (trigger)="buttonNew.click()"></sqx-shortcut>
<form class="form-inline ms-2" (ngSubmit)="search()">
<input class="form-control" [formControl]="usersFilter" placeholder="{{ 'users.search' | sqxTranslate }}"
shortcut="CTRL + SHIFT + S"
shortcutAction="focus">
</form>
<button type="button" class="btn btn-success" #buttonNew routerLink="new" title="i18n:users.createTooltip">
<i class="icon-plus"></i> {{ 'users.create' | sqxTranslate }}
</button>
</ng-container>
<ng-container *ngIf="usersState.canCreate | async">
<button type="button" class="btn btn-success ms-2" routerLink="new" title="i18n:users.createTooltip" shortcut="CTRL + U">
<i class="icon-plus"></i> {{ 'users.create' | sqxTranslate }}
</button>
</ng-container>
</div>
</ng-container>
<ng-container content>
<sqx-list-view [isLoading]="usersState.isLoading | async" [table]="true">
<ng-container>
<sqx-list-view innerWidth="50rem" [isLoading]="usersState.isLoading | async" [table]="true">
<ng-container header>
<table class="table table-items table-fixed" #header>
<thead>
@ -49,17 +44,17 @@
</table>
</ng-container>
<div content>
<ng-container>
<table class="table table-items table-fixed" *ngIf="usersState.users | async; let users" [sqxSyncWidth]="header">
<tbody *ngFor="let user of users; trackBy: trackByUser" [sqxUser]="user"></tbody>
</table>
</div>
</ng-container>
<ng-container footer>
<sqx-pager [paging]="usersState.paging | async" (pagingChange)="usersState.page($event)"></sqx-pager>
</ng-container>
</sqx-list-view>
</ng-container>
</sqx-panel>
</sqx-layout>
<router-outlet></router-outlet>

17
frontend/app/features/api/api-area.component.html

@ -1,18 +1,17 @@
<sqx-title message="i18n:api.pageTitle"></sqx-title>
<sqx-panel theme="dark" desiredWidth="12rem">
<ng-container title>
{{ 'api.title' | sqxTranslate }}
</ng-container>
<ng-container content>
<ul class="nav nav-panel nav-dark flex-column">
<sqx-layout layout="left" titleText="i18n:api.title" titleIcon="api" [width]="16" [white]="true" [overflow]="true" [padding]="true">
<ng-container>
<ul class="nav nav-light flex-column">
<li class="nav-item">
<a class="nav-link" routerLink="graphql" routerLinkActive="active">
{{ 'api.graphql' | sqxTranslate }}
<i class="icon-angle-right"></i>
</a>
</li>
<li class="nav-item nav-heading">
{{ 'common.openAPI' | sqxTranslate }}
</li>
<li class="nav-item">
<a class="nav-link" href="/api/content/{{appsState.appName}}/docs" sqxExternalLink>
{{ 'api.contentApi' | sqxTranslate }}
@ -25,6 +24,6 @@
</li>
</ul>
</ng-container>
</sqx-panel>
</sqx-layout>
<router-outlet></router-outlet>

6
frontend/app/features/api/pages/graphql/graphql-page.component.html

@ -1,5 +1,5 @@
<sqx-title message="i18n:api.graphqlPageTitle"></sqx-title>
<sqx-panel desiredWidth="*" minWidth="50rem" [isFullSize]="true">
<div inner #graphiQLContainer></div>
</sqx-panel>
<sqx-layout layout="main" [hideHeader]="true" [hideSidebar]="true">
<div inner #graphiQLContainer></div>
</sqx-layout>

23
frontend/app/features/api/pages/graphql/graphql-page.component.scss

@ -2,24 +2,37 @@
@import '~graphiql/graphiql';
.graphiql-container {
& {
@include absolute(0, 0, 0, 0);
}
@include absolute(0, 0, 0, 0);
& * {
box-sizing: content-box;
}
// sass-lint:disable class-name-format
/* stylelint-disable-next-line selector-class-pattern */
& .editorWrap {
overflow: hidden;
}
svg {
fill: $color-dark-black;
fill: $color-black;
}
/* stylelint-disable-next-line selector-class-pattern */
.historyPaneWrap {
border-radius: 0;
border-left: 1px solid $color-border;
box-shadow: none !important;
}
/* stylelint-disable-next-line selector-class-pattern */
.docExplorerWrap {
border-radius: 0;
border-left: 1px solid $color-border;
box-shadow: none !important;
}
}
/* stylelint-disable-next-line selector-class-pattern */
.CodeMirror-linenumbers {
min-width: 29px;
}

2
frontend/app/features/apps/pages/app.component.html

@ -1,6 +1,6 @@
<div class="card card-href card-app" [routerLink]="['/app', app.name]">
<div class="card-body">
<div class="row no-gutters">
<div class="row g-0">
<div class="col-auto card-left">
<sqx-avatar [image]="app.image" [identifier]="app.name"></sqx-avatar>
</div>

26
frontend/app/features/apps/pages/apps-page.component.html

@ -30,9 +30,9 @@
<h3 class="card-title">{{ 'apps.createBlankApp' | sqxTranslate }}</h3>
<div class="card-text">
<sqx-form-hint>
{{ 'apps.createBlankAppDescription' | sqxTranslate }}
</div>
</sqx-form-hint>
</div>
</div>
@ -44,12 +44,11 @@
<h3 class="card-title">{{ 'apps.createBlogApp' | sqxTranslate }}</h3>
<div class="card-text">
<div>{{ 'apps.createBlogAppDescription' | sqxTranslate }}</div>
<div>
{{ 'common.sampleCodeLabel' | sqxTranslate }} <a href="https://github.com/Squidex/squidex-samples" sqxStopClick sqxExternalLink>{{ 'common.github' | sqxTranslate }}</a>
</div>
</div>
<sqx-form-hint>
{{ 'apps.createBlogAppDescription' | sqxTranslate }}
<br />
{{ 'common.sampleCodeLabel' | sqxTranslate }} <a href="https://github.com/Squidex/squidex-samples" sqxStopClick sqxExternalLink>{{ 'common.github' | sqxTranslate }}</a>
</sqx-form-hint>
</div>
</div>
@ -61,12 +60,11 @@
<h3 class="card-title">{{ 'apps.createProfileApp' | sqxTranslate }}</h3>
<div class="card-text">
<div>{{ 'apps.createProfileAppDescription' | sqxTranslate }}</div>
<div>
{{ 'common.sampleCodeLabel' | sqxTranslate }} <a href="https://github.com/Squidex/squidex-samples" sqxStopClick sqxExternalLink>{{ 'common.github' | sqxTranslate }}</a>
</div>
</div>
<sqx-form-hint>
{{ 'apps.createProfileAppDescription' | sqxTranslate }}
<br />
{{ 'common.sampleCodeLabel' | sqxTranslate }} <a href="https://github.com/Squidex/squidex-samples" sqxStopClick sqxExternalLink>{{ 'common.github' | sqxTranslate }}</a>
</sqx-form-hint>
</div>
</div>
</div>

39
frontend/app/features/apps/pages/apps-page.component.scss

@ -1,8 +1,4 @@
.apps {
&-title {
font-size: 1.4rem;
}
&-section {
@include clearfix;
padding: 2rem 1.25rem 0 $size-sidebar-width + .25rem;
@ -15,15 +11,17 @@
overflow-y: auto;
}
%no-decoration {
text-decoration: none;
}
:host ::ng-deep {
.card {
& {
@include hover-visible('.deeplinks', inline);
display: inline-block;
margin-bottom: 1rem;
margin-right: 1rem;
width: 20rem;
}
@include hover-visible('.deeplinks', inline);
display: inline-block;
margin-bottom: 1rem;
margin-right: 1rem;
width: 20rem;
&-links {
margin-top: .5rem;
@ -46,10 +44,11 @@
}
&-text {
color: $color-text-decent;
font-size: .9rem;
font-weight: normal;
margin-top: .5rem;
font-size: $font-small;
a {
text-decoration: none;
}
}
&-title {
@ -71,22 +70,20 @@
}
&-href {
& {
cursor: pointer;
}
cursor: pointer;
&:hover {
@extend %no-decoration;
@include box-shadow-outer(0, 3px, 16px, .2);
}
&:focus {
@extend %no-decoration;
outline: none;
}
&:hover,
&:focus,
&:active {
text-decoration: none;
@extend %no-decoration;
}
}
}

14
frontend/app/features/apps/pages/onboarding-dialog.component.scss

@ -26,7 +26,7 @@ p {
&-content {
background-color: $color-dark-onboarding;
background-image: url('./images/onboarding-background.png');
color: $color-dark-foreground;
color: $color-white;
position: relative;
}
@ -40,7 +40,7 @@ p {
}
&-close {
color: $color-dark-foreground;
color: $color-white;
cursor: pointer;
text-decoration: underline !important;
}
@ -65,12 +65,10 @@ p {
.onboarding {
&-enter-leave {
& {
@include force-width(28rem);
margin: 4rem auto 0;
text-align: center;
text-decoration: none;
}
@include force-width(28rem);
margin: 4rem auto 0;
text-align: center;
text-decoration: none;
p {
margin: 2rem 0;

30
frontend/app/features/assets/pages/asset-tags.component.html

@ -1,18 +1,20 @@
<a class="sidebar-item" (click)="reset.emit()" [class.active]="isEmpty()">
<div class="row">
<div class="col">
<div class="nav nav-light flex-column">
<div class="nav-item">
<a class="nav-link" (click)="reset.emit()" [class.active]="isEmpty()">
{{ 'common.tagsAll' | sqxTranslate }}
</div>
</a>
</div>
</a>
<a class="sidebar-item" *ngFor="let tag of tags; trackBy: trackByTag" (click)="toggle.emit(tag.name)" [class.active]="isSelected(tag)">
<div class="row">
<div class="col">
{{tag.name}}
</div>
<div class="col-auto">
{{tag.count}}
</div>
<div class="nav-item" *ngFor="let tag of tags; trackBy: trackByTag">
<a class="nav-link" (click)="toggle.emit(tag.name)" [class.active]="isSelected(tag)">
<div class="row g-0">
<div class="col">
<span class="truncate">{{tag.name}}</span>
</div>
<div class="col-auto">
<div class="badge badge-secondary rounded-pill">{{tag.count}}</div>
</div>
</div>
</a>
</div>
</a>
</div>

8
frontend/app/features/assets/pages/asset-tags.component.scss

@ -0,0 +1,8 @@
.active {
.badge {
background: none;
border: 0;
border-radius: 0;
color: $color-theme-blue;
}
}

36
frontend/app/features/assets/pages/assets-filters-page.component.html

@ -1,24 +1,18 @@
<sqx-panel desiredWidth="20rem" [isBlank]="true" [isLazyLoaded]="false">
<ng-container title>
{{ 'common.filters' | sqxTranslate }}
</ng-container>
<sqx-layout titleText="i18n:common.filters" [width]="20" [white]="true" [padding]="true" [overflow]="true">
<h3>{{ 'common.tags' | sqxTranslate }}</h3>
<ng-container content>
<h3>{{ 'common.tags' | sqxTranslate }}</h3>
<sqx-asset-tags (reset)="resetTags()"
[tags]="(assetsState.tags | async)!"
[tagsSelected]="(assetsState.tagsSelected | async)!"
(toggle)="toggleTag($event)">
</sqx-asset-tags>
<sqx-asset-tags (reset)="resetTags()"
[tags]="(assetsState.tags | async)!"
[tagsSelected]="(assetsState.tagsSelected | async)!"
(toggle)="toggleTag($event)">
</sqx-asset-tags>
<hr>
<hr>
<sqx-shared-queries
[types]="'common.assets' | sqxTranslate"
[queryUsed]="assetsState.query | async"
[queries]="assetsQueries"
(search)="search($event)">
</sqx-shared-queries>
</ng-container>
</sqx-panel>
<sqx-shared-queries
[types]="'common.assets' | sqxTranslate"
[queryUsed]="assetsState.query | async"
[queries]="assetsQueries"
(search)="search($event)">
</sqx-shared-queries>
</sqx-layout>

36
frontend/app/features/assets/pages/assets-page.component.html

@ -1,21 +1,15 @@
<sqx-title message="i18n:assets.listPageTitle"></sqx-title>
<sqx-panel desiredWidth="*" minWidth="50rem" [showSidebar]="true" [grid]="true" closeQueryParamsHandling="">
<ng-container title>
{{ 'common.assets' | sqxTranslate }}
</ng-container>
<sqx-layout layout="main" titleText="i18n:common.assets" titleIcon="assets">
<ng-container menu>
<div class="row no-gutters pl-1">
<div class="row flex-nowrap gx-2">
<div class="col-auto offset-xl-2">
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:assets.refreshTooltip">
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:assets.refreshTooltip" shortcut="CTRL + B">
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }}
</button>
</div>
<div class="col pl-1" style="width: 300px">
<div class="row no-gutters search">
<div class="col" style="width: 300px;">
<div class="row g-0 search">
<div class="col-6">
<sqx-tag-editor class="tags" [singleLine]="true" placeholder="{{ 'assets.searchByTags' | sqxTranslate }}"
[suggestions]="assetsState.tagsNames | async"
@ -36,7 +30,7 @@
</div>
</div>
<div class="col-auto pl-1">
<div class="col-auto">
<div class="btn-group">
<button type="button" class="btn btn-secondary btn-toggle" [class.btn-primary]="isListView" [disabled]="isListView" (click)="changeView(true)">
<i class="icon-list"></i>
@ -46,23 +40,21 @@
</button>
</div>
</div>
<div class="col-auto pl-1">
<sqx-shortcut keys="ctrl+shift+g" (trigger)="addAssetFolderDialog.show()"></sqx-shortcut>
<button type="button" class="btn btn-success" (click)="addAssetFolderDialog.show()" title="i18n:assets.createFolderTooltip">
<div class="col-auto">
<button type="button" class="btn btn-success" (click)="addAssetFolderDialog.show()" title="i18n:assets.createFolderTooltip" shortcut="CTRL + U">
<i class="icon-create_new_folder"></i>
</button>
</div>
</div>
</ng-container>
<ng-container content>
<ng-container>
<sqx-list-view [isLoading]="assetsState.isLoading | async">
<ng-container header>
<sqx-asset-path [path]="assetsState.path | async" (navigate)="assetsState.navigate($event.id)"></sqx-asset-path>
</ng-container>
<div content>
<div>
<sqx-assets-list [assetsState]="assetsState" [showPager]="false" [isListView]="isListView"></sqx-assets-list>
</div>
@ -72,17 +64,17 @@
</sqx-list-view>
</ng-container>
<ng-container sidebar>
<ng-container sidebarMenu>
<div class="panel-nav">
<a class="panel-link" routerLink="filters" routerLinkActive="active" queryParamsHandling="preserve" title="i18n:common.filters" titlePosition="left">
<i class="icon-filter"></i>
</a>
</div>
</ng-container>
</sqx-panel>
</sqx-layout>
<router-outlet></router-outlet>
<ng-container *sqxModal="addAssetFolderDialog">
<sqx-asset-folder-dialog (complete)="addAssetFolderDialog.hide()"></sqx-asset-folder-dialog>
</ng-container>
<router-outlet></router-outlet>

4
frontend/app/features/assets/pages/assets-page.component.scss

@ -1,10 +1,10 @@
.search ::ng-deep {
.form-control {
@include border-radius-right;
border-radius: 0 $border-radius $border-radius 0;
}
.tags {
@include border-radius-left;
border-radius: $border-radius 0 0 $border-radius;
border-right: 0;
&:focus,

12
frontend/app/features/content/pages/comments/comments-page.component.html

@ -1,9 +1,3 @@
<sqx-panel desiredWidth="20rem" [isBlank]="true" [isLazyLoaded]="false" [grid]="true">
<ng-container title>
{{ 'comments.title' | sqxTranslate }}
</ng-container>
<ng-container content>
<sqx-comments [commentsId]="commentsId | async"></sqx-comments>
</ng-container>
</sqx-panel>
<sqx-layout layout="simple" titleText="i18n:comments.title" [width]="20" [white]="true">
<sqx-comments [commentsId]="commentsId | async"></sqx-comments>
</sqx-layout>

6
frontend/app/features/content/pages/content/content-event.component.html

@ -1,10 +1,10 @@
<div class="event row no-gutters">
<div class="event row g-0">
<div class="col-auto">
<img class="user-picture" title="{{event.actor | sqxUserNameRef}}" [src]="event.actor | sqxUserPictureRef">
</div>
<div class="col pl-2 event-right">
<div class="col ps-2 event-right">
<div class="event-message">
<span class="event-actor user-ref mr-1">{{event.actor | sqxUserNameRef:null}}</span>
<span class="event-actor user-ref me-1">{{event.actor | sqxUserNameRef:null}}</span>
<span [innerHTML]="event | sqxHistoryMessage"></span>
</div>

14
frontend/app/features/content/pages/content/content-event.component.scss

@ -8,15 +8,17 @@
}
}
a {
text-decoration: none;
}
.event {
& {
font-size: .9rem;
font-weight: normal;
margin-bottom: 1.5rem;
}
font-size: $font-small;
font-weight: normal;
margin-bottom: 1.5rem;
&-created {
font-size: .75rem;
font-size: $font-smallest;
font-weight: normal;
margin: .25rem 0;
}

25
frontend/app/features/content/pages/content/content-history-page.component.html

@ -1,21 +1,14 @@
<sqx-panel desiredWidth="20rem" [isBlank]="true" [isLazyLoaded]="false">
<ng-container title>
{{ 'common.workflow' | sqxTranslate }}
</ng-container>
<ng-container content>
<sqx-layout layout="simple" titleText="i18n:common.workflow" [width]="20" [white]="true" [overflow]="true" [padding]="true">
<ng-container>
<div class="section mb-4">
<label for="id">{{ 'common.id' | sqxTranslate }}</label>
<div class="row no-gutters">
<div class="col">
<input readonly class="form-control" name="id" id="id" value="{{content.id}}" #inputId>
</div>
<div class="col-auto">
<button type="button" class="btn btn-text" [sqxCopy]="inputId">
<i class="icon-copy"></i>
</button>
</div>
<div class="input-group">
<input readonly class="form-control" name="id" id="id" value="{{content.id}}" #inputId>
<button type="button" class="btn btn-outline-secondary" [sqxCopy]="inputId">
<i class="icon-copy"></i>
</button>
</div>
</div>
@ -133,6 +126,6 @@
</sqx-content-event>
</div>
</ng-container>
</sqx-panel>
</sqx-layout>
<sqx-due-time-selector [disabled]="disableScheduler" #dueTimeSelector></sqx-due-time-selector>

46
frontend/app/features/content/pages/content/content-page.component.html

@ -1,23 +1,25 @@
<sqx-title [message]="schema.displayName"></sqx-title>
<sqx-title [message]="schema.displayName" [url]="['..']"></sqx-title>
<form [formGroup]="contentForm.form" (ngSubmit)="saveAndPublish()">
<sqx-panel desiredWidth="*" minWidth="60rem" [showSidebar]="!!content" [grid]="true" (close)="back()">
<sqx-layout layout="main" [hideSidebar]="!content">
<ng-container title>
<a class="btn btn-text" (click)="back()" *ngIf="schema.type === 'Default'">
<a class="btn btn-text-secondary" (click)="back()" *ngIf="schema.type === 'Default'">
<i class="icon-angle-left"></i>
</a>
<ng-container *ngIf="!content">
<sqx-title message="i18n:contents.createPageTitle"></sqx-title>
<ng-container *ngIf="content; noContentTitle">
<sqx-title message="i18n:contents.editPageTitle"></sqx-title>
</ng-container>
<ng-template #noContentTitle>
{{ 'contents.createTitle' | sqxTranslate }}
</ng-container>
<sqx-title message="i18n:contents.createPageTitle"></sqx-title>
</ng-template>
</ng-container>
<ng-container header>
<ng-container menu>
<ng-container *ngIf="content">
<sqx-title message="i18n:contents.editPageTitle"></sqx-title>
<ul class="nav nav-tabs2" *ngIf="contentTab | async; let tab">
<li class="nav-item">
<a class="nav-link" [routerLink]="[]" [queryParams]="{ tab: 'editor' }" [class.active]="tab === 'editor'">
@ -44,16 +46,16 @@
</ng-container>
<ng-container menu>
<ng-container *ngIf="content; else noContent">
<ng-container *ngIf="content; else noContentMenu">
<sqx-notifo topic="apps/{{contentsState.appId}}/schemas/{{schema?.name}}/contents/{{content.id}}"></sqx-notifo>
<ng-container *ngIf="contentTab | async; let tab">
<ng-container *ngIf="tab === 'references' || tab === 'referencing'; else defaultHeader">
<button type="button" class="btn btn-primary ml-1" (click)="publish()">
<button type="button" class="btn btn-primary ms-2" (click)="publish()">
{{ 'contents.publishAll' | sqxTranslate }}
</button>
<button type="button" class="btn btn-primary ml-1" (click)="validate()">
<button type="button" class="btn btn-primary ms-2" (click)="validate()">
{{ 'contents.validate' | sqxTranslate }}
</button>
</ng-container>
@ -62,7 +64,7 @@
<sqx-preview-button [schema]="schema" [content]="content" [confirm]="confirmPreview"></sqx-preview-button>
<ng-container *ngIf="content?.canDelete">
<button type="button" class="btn btn-outline-secondary ml-2" (click)="dropdown.toggle()" #buttonOptions>
<button type="button" class="btn btn-outline-secondary ms-2" (click)="dropdown.toggle()" #buttonOptions>
<i class="icon-dots"></i>
</button>
@ -80,32 +82,28 @@
</ng-container>
<ng-container *ngIf="content?.canUpdate">
<button type="submit" class="btn btn-primary ml-1" title="i18n:common.saveShortcut">
<button type="submit" class="btn btn-primary ms-2" title="i18n:common.saveShortcut" shortcut="CTRL + SHIFT + S">
{{ 'common.save' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+s" (trigger)="saveAndPublish()"></sqx-shortcut>
</ng-container>
</ng-template>
</ng-container>
</ng-container>
<ng-template #noContent>
<ng-template #noContentMenu>
<button type="button" class="btn btn-secondary" (click)="save()" *ngIf="contentsState.canCreate | async">
{{ 'common.save' | sqxTranslate }}
</button>
<button type="submit" class="btn btn-primary ml-1" title="i18n:common.saveShortcut" *ngIf="contentsState.canCreateAndPublish | async">
<button type="submit" class="btn btn-primary ms-2" title="i18n:common.saveShortcut" shortcut="CTRL + SHIFT + S" *ngIf="contentsState.canCreateAndPublish | async">
{{ 'contents.saveAndPublish' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+s" (trigger)="saveAndPublish()"></sqx-shortcut>
</ng-template>
<sqx-form-error [bubble]="true" [closeable]="true" [error]="contentForm.error | async"></sqx-form-error>
</ng-container>
<ng-container content>
<ng-container>
<ng-container *ngIf="content; else noContentEditor">
<ng-container [ngSwitch]="contentTab | async">
<ng-container *ngSwitchCase="'references'">
@ -134,6 +132,7 @@
[(language)]="language"
[contentForm]="contentForm"
[contentFormCompare]="contentFormCompare"
[contentVersion]="contentVersion"
[formContext]="formContext"
[languages]="languages"
[schema]="schema">
@ -147,6 +146,7 @@
[(language)]="language"
[contentForm]="contentForm"
[contentFormCompare]="contentFormCompare"
[contentVersion]="contentVersion"
[formContext]="formContext"
[languages]="languages"
[schema]="schema">
@ -154,7 +154,7 @@
</ng-template>
</ng-container>
<ng-container sidebar>
<ng-container sidebarMenu>
<div class="panel-nav">
<a class="panel-link" routerLink="history" routerLinkActive="active" queryParamsHandling="preserve" title="i18n:common.workflow" titlePosition="left" #linkHistory>
<i class="icon-time"></i>
@ -173,7 +173,7 @@
</sqx-onboarding-tooltip>
</div>
</ng-container>
</sqx-panel>
</sqx-layout>
</form>
<router-outlet></router-outlet>

11
frontend/app/features/content/pages/content/editor/content-editor.component.html

@ -1,16 +1,15 @@
<sqx-list-view>
<ng-container topHeader>
<div class="panel-alert panel-alert-danger" *ngIf="contentVersion">
<div class="float-right">
<a class="force" (click)="loadLatest.emit()">{{ 'contents.viewLatest' | sqxTranslate }}</a>
<div class="alert alert-danger" *ngIf="contentVersion">
<div class="float-end">
<a (click)="loadLatest.emit()">{{ 'contents.viewLatest' | sqxTranslate }}</a>
</div>
<div [innerHTML]="'contents.versionViewing' | sqxTranslate: { version: contentVersion } | sqxMarkdownInline"></div>
</div>
</ng-container>
<div content>
<ng-container>
<sqx-content-section *ngFor="let section of contentForm.sections; trackBy: trackBySection"
[(language)]="language"
[form]="contentForm"
@ -20,5 +19,5 @@
[languages]="languages"
[schema]="schema">
</sqx-content-section>
</div>
</ng-container>
</sqx-list-view>

13
frontend/app/features/content/pages/content/editor/content-editor.component.scss

@ -0,0 +1,13 @@
:host {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow: hidden;
padding: 0;
}
.alert {
border: 0;
border-radius: 0;
margin: 0;
}

18
frontend/app/features/content/pages/content/editor/content-field.component.html

@ -1,11 +1,13 @@
<div class="row no-gutters" [class.compare]="formModelCompare">
<div class="row g-0" [class.compare]="formModelCompare">
<div [class.col-12]="!formModelCompare" [class.col-6]="formModelCompare">
<div class="table-items-row" [class.field-invalid]="isInvalid | async" *ngIf="!(formModel.hiddenChanges | async)">
<div class="table-items-row table-items-row-summary" [class.field-invalid]="isInvalid | async" *ngIf="!(formModel.hiddenChanges | async)">
<div class="languages-container">
<div class="languages-buttons">
<button *ngIf="isTranslatable" type="button" class="btn btn-text-secondary btn-sm mr-1" (click)="translate()" title="i18n:contents.autotranslate">
<i class="icon-translate"></i>
</button>
<ng-container *ngIf="!formModel.field.isDisabled">
<button *ngIf="isTranslatable" type="button" class="btn btn-text-secondary btn-sm me-1" title="i18n:contents.autotranslate" (click)="translate()">
<i class="icon-translate"></i>
</button>
</ng-container>
<sqx-field-languages
[field]="formModel.field"
@ -21,7 +23,7 @@
<ng-container *ngIf="showAllControls; else singleControl">
<div class="form-group" *ngFor="let language of languages">
<sqx-field-editor
[canUnset]="true"
[canUnset]="!formModel.field.isDisabled"
[form]="form"
[formContext]="formContext"
[formModel]="formModel.get(language)"
@ -34,7 +36,7 @@
<ng-template #singleControl>
<sqx-field-editor
[canUnset]="true"
[canUnset]="!formModel.field.isDisabled"
[form]="form"
[formContext]="formContext"
[formModel]="getControl()"
@ -50,7 +52,7 @@
<i class="icon-arrow_back"></i>
</button>
<div class="table-items-row" *ngIf="!(formModelCompare!.hiddenChanges | async)">
<div class="table-items-row table-items-row-summary" *ngIf="!(formModelCompare!.hiddenChanges | async)">
<div class="languages-container">
<div class="languages-buttons-compare">
<sqx-field-languages

8
frontend/app/features/content/pages/content/editor/content-field.component.scss

@ -9,20 +9,18 @@
}
&-buttons {
@include absolute(-.5rem, 2rem);
@include absolute(-.6rem, 2rem);
z-index: 1000;
}
&-buttons-compare {
@include absolute(-.5rem, 0);
@include absolute(-.6rem, 0);
z-index: 1000;
}
}
.col-6 {
& {
padding-right: .5rem;
}
padding-right: .5rem;
&.col-right {
padding-left: .5rem;

4
frontend/app/features/content/pages/content/editor/content-section.component.html

@ -1,6 +1,6 @@
<ng-container *ngIf="(formSection.visibleChanges | async) || formCompare">
<div class="header" *ngIf="formSection.separator; let separator">
<div class="row no-gutters">
<div class="row g-0">
<div class="col-auto">
<button type="button" class="btn btn-sm btn-text-secondary" (click)="toggle()">
<i [class.icon-caret-right]="snapshot.isCollapsed" [class.icon-caret-down]="!snapshot.isCollapsed"></i>
@ -17,7 +17,7 @@
</div>
</ng-container>
<div class="row small-gutters" [class.hidden]="snapshot.isCollapsed && !formCompare">
<div class="row gx-1" [class.hidden]="snapshot.isCollapsed && !formCompare">
<sqx-content-field *ngFor="let field of formSection.fields; trackBy: trackByField"
(languageChange)="languageChange.emit($event)"
[isCompact]="isCompact"

39
frontend/app/features/content/pages/content/editor/content-section.component.scss

@ -1,26 +1,3 @@
:host ::ng-deep {
.small-gutters {
margin-left: .25rem;
margin-right: .25rem;
> .col-6,
> .col-12 {
padding-left: .25rem;
padding-right: .25rem;
}
}
}
.btn {
& {
width: 2rem;
}
&:focus {
border-color: transparent;
}
}
h3 {
margin: 0;
}
@ -34,3 +11,19 @@ h3 {
line-height: 2rem;
}
}
:host {
&:first-child {
.header {
margin-top: 0;
}
}
}
.btn {
width: 2rem;
&:focus {
border-color: transparent;
}
}

2
frontend/app/features/content/pages/content/editor/field-languages.component.html

@ -1,5 +1,5 @@
<ng-container *ngIf="field.isLocalizable && languages.length > 1">
<button *ngIf="!field.properties.isComplexUI" type="button" class="btn btn-text-secondary btn-sm mr-1" (click)="toggleShowAllControls()">
<button *ngIf="!field.properties.isComplexUI" type="button" class="btn btn-text-secondary btn-sm me-1" (click)="toggleShowAllControls()">
<ng-container *ngIf="showAllControls; else singleLanguage">
<span>{{ 'contents.languageModeSingle' | sqxTranslate }}</span>
</ng-container>

2
frontend/app/features/content/pages/content/references/content-references.component.html

@ -1,5 +1,5 @@
<sqx-list-view [isLoading]="contentsState.isLoading | async" [table]="true">
<ng-container content>
<ng-container>
<table class="table table-items table-fixed" *ngIf="contentsState.contents | async; let contents">
<tbody *ngFor="let content of contents; trackBy: trackByContent"
[sqxReferenceItem]="content"

52
frontend/app/features/content/pages/contents/contents-filters-page.component.html

@ -1,38 +1,32 @@
<sqx-panel desiredWidth="20rem" [isBlank]="true" [isLazyLoaded]="false">
<ng-container title>
{{ 'common.filters' | sqxTranslate }}
</ng-container>
<sqx-layout titleText="i18n:common.filters" [width]="20" [white]="true" [padding]="true" [overflow]="true">
<ng-container *ngIf="schemaQueries | async; let queries">
<sqx-query-list
[types]="'common.contents' | sqxTranslate"
[queryUsed]="contentsState.query | async"
[queries]="queries.defaultQueries"
(search)="search($event)">
</sqx-query-list>
<hr>
<div class="sidebar-section">
<h3>{{ 'contents.statusQueries' | sqxTranslate }}</h3>
<ng-container content>
<ng-container *ngIf="schemaQueries | async; let queries">
<sqx-query-list
[types]="'common.contents' | sqxTranslate"
[queryUsed]="contentsState.query | async"
[queries]="queries.defaultQueries"
[queries]="contentsState.statusQueries | async"
(search)="search($event)">
</sqx-query-list>
</div>
<hr>
<div class="sidebar-section">
<h3>{{ 'contents.statusQueries' | sqxTranslate }}</h3>
<sqx-query-list
[types]="'common.contents' | sqxTranslate"
[queryUsed]="contentsState.query | async"
[queries]="contentsState.statusQueries | async"
(search)="search($event)">
</sqx-query-list>
</div>
<hr>
<hr>
<sqx-shared-queries
[types]="'common.contents' | sqxTranslate"
[queryUsed]="contentsState.query | async"
[queries]="queries"
(search)="search($event)">
</sqx-shared-queries>
</ng-container>
<sqx-shared-queries
[types]="'common.contents' | sqxTranslate"
[queryUsed]="contentsState.query | async"
[queries]="queries"
(search)="search($event)">
</sqx-shared-queries>
</ng-container>
</sqx-panel>
</sqx-layout>

42
frontend/app/features/content/pages/contents/contents-page.component.html

@ -1,22 +1,16 @@
<sqx-title [message]="schema.displayName"></sqx-title>
<sqx-panel desiredWidth="*" minWidth="50rem" [showSidebar]="true" [grid]="true" closeQueryParamsHandling="">
<ng-container title>
{{ 'common.contents' | sqxTranslate }}
</ng-container>
<sqx-layout layout="main" titleText="i18n:common.contents" titleIcon="contents">
<ng-container menu>
<div class="row no-gutters pl-1">
<div class="col-auto ml-8">
<div class="row flex-nowrap gx-2">
<div class="col-auto ms-8">
<sqx-notifo topic="apps/{{contentsState.appId}}/schemas/{{schema?.id}}/contents"></sqx-notifo>
<sqx-shortcut keys="ctrl+shift+r" (trigger)="reload()"></sqx-shortcut>
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:contents.refreshTooltip">
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:contents.refreshTooltip" shortcut="CTRL + B">
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }}
</button>
</div>
<div class="col pl-1">
<div class="col">
<sqx-search-form formClass="form" placeholder="{{ 'contents.searchPlaceholder' | sqxTranslate }}"
(queryChange)="search($event)"
[query]="contentsState.query | async"
@ -27,27 +21,25 @@
[enableShortcut]="true">
</sqx-search-form>
</div>
<div class="col-auto pl-1" *ngIf="languages.length > 1">
<div class="col-auto" *ngIf="languages.length > 1">
<sqx-language-selector class="languages-buttons" [(selectedLanguage)]="language" [languages]="languages"></sqx-language-selector>
</div>
<div class="col-auto pl-1">
<button type="button" class="btn btn-success" #newButton routerLink="new" title="i18n:contents.createContentTooltip" [disabled]="(contentsState.canCreateAny | async) === false">
<div class="col-auto">
<button type="button" class="btn btn-success" routerLink="new" title="i18n:contents.createContentTooltip" shortcut="CTRL + U" [disabled]="(contentsState.canCreateAny | async) === false">
<i class="icon-plus"></i> {{ 'contents.create' | sqxTranslate }}
</button>
<sqx-shortcut keys="ctrl+shift+g" (trigger)="newButton.click()"></sqx-shortcut>
</div>
</div>
</ng-container>
<ng-container content>
<ng-container>
<ng-container *ngIf="tableView.listFields | async; let listFields">
<sqx-list-view [isLoading]="contentsState.isLoading | async" [syncedHeader]="true" [table]="true">
<ng-container topHeader>
<div class="selection" *ngIf="selectionCount > 0">
{{ 'contents.selectionCount' | sqxTranslate: { count: selectionCount } }}&nbsp;&nbsp;
<button type="button" class="btn btn-outline-secondary btn-status mr-1" *ngFor="let status of selectionStatuses | sqxKeys" (click)="changeSelectedStatus(status)">
<button type="button" class="btn btn-outline-secondary btn-status me-2" *ngFor="let status of selectionStatuses | sqxKeys" (click)="changeSelectedStatus(status)">
<sqx-content-status layout="text"
[status]="status"
[statusColor]="selectionStatuses[status]">
@ -79,17 +71,17 @@
</div>
</ng-container>
<ng-container syncedHeader>
<ng-container header>
<table class="table table-items table-fixed" [style.minWidth]="listFields | sqxContentListWidth" #header>
<thead>
<tr>
<th class="cell-select">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="all_selected"
<div class="form-check">
<input class="form-check-input" type="checkbox" id="all_selected"
[ngModel]="selectedAll"
(ngModelChange)="selectAll($event)">
<label class="custom-control-label" for="all_selected"></label>
<label class="form-check-label" for="all_selected"></label>
</div>
</th>
<th class="cell-actions cell-actions-left">
@ -108,7 +100,7 @@
</table>
</ng-container>
<ng-container syncedContent>
<ng-container>
<div class="table-container">
<table class="table table-items table-fixed" [style.minWidth]="listFields | sqxContentListWidth" [sqxSyncWidth]="header">
<tbody *ngFor="let content of contentsState.contents | async; trackBy: trackByContent"
@ -134,7 +126,7 @@
</ng-container>
</ng-container>
<ng-container sidebar>
<ng-container sidebarMenu>
<div class="panel-nav">
<a class="panel-link" routerLink="filters" routerLinkActive="active" queryParamsHandling="preserve" title="i18n:common.filters" titlePosition="left">
<i class="icon-filter"></i>
@ -145,7 +137,7 @@
</a>
</div>
</ng-container>
</sqx-panel>
</sqx-layout>
<router-outlet></router-outlet>

17
frontend/app/features/content/pages/contents/contents-page.component.scss

@ -2,15 +2,23 @@
cursor: pointer;
}
.alert {
border-radius: 0;
}
.table-container {
display: inline-block;
min-width: 100%;
padding: 0;
padding-right: 1.5rem;
.table-items {
margin: 0;
}
}
.icon-plus {
font-size: .8rem;
font-size: $font-smallest;
}
.hidden {
@ -24,16 +32,19 @@
&-button {
@include absolute(null, 1rem, -2.375rem);
background-color: $color-background;
border: 0;
border-radius: 4px;
z-index: 1000;
}
}
.btn-status {
background: $color-dark-foreground;
background: $color-white;
}
.selection {
background: $color-theme-secondary;
border-bottom: 1px solid $color-border;
border-radius: 0;
padding: .25 * $panel-padding $panel-padding;
}

12
frontend/app/features/content/pages/contents/custom-view-editor.component.html

@ -14,9 +14,9 @@
<div *ngFor="let field of fieldNames" cdkDrag>
<i class="icon-drag2 drag-handle"></i>
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" checked (click)="removeField(field)" id="field_{{field}}" [disabled]="!field">
<label class="custom-control-label" for="field_{{field}}">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked (click)="removeField(field)" id="field_{{field}}" [disabled]="!field">
<label class="form-check-label" for="field_{{field}}">
{{field || '--'}}
</label>
</div>
@ -29,9 +29,9 @@
<div *ngFor="let field of fieldsNotAdded">
<i class="icon-drag2 drag-handle invisible"></i>
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" (click)="addField(field)" id="field_{{field}}">
<label class="custom-control-label" for="field_{{field}}">
<div class="form-check">
<input class="form-check-input" type="checkbox" (click)="addField(field)" id="field_{{field}}">
<label class="form-check-label" for="field_{{field}}">
{{field}}
</label>
</div>

2
frontend/app/features/content/pages/contents/custom-view-editor.component.scss

@ -13,7 +13,7 @@
visibility: hidden;
}
.custom-checkbox {
.form-check {
display: inline-block;
padding-left: 2rem;
padding-right: .5rem;

50
frontend/app/features/content/pages/schemas/schemas-page.component.html

@ -1,45 +1,23 @@
<sqx-title message="i18n:contents.schemasPageTitle"></sqx-title>
<sqx-panel theme="dark" [desiredWidth]="width" [showClose]="!isCollapsed" [showSecondHeader]="true">
<ng-container title>
<ng-container *ngIf="!isCollapsed">
{{ 'common.schemas' | sqxTranslate }}
</ng-container>
</ng-container>
<sqx-layout layout="left" titleCollapsed="i18n:common.schemas" [width]="18" [white]="true" [padding]="true" [overflow]="true">
<ng-container menu>
<div class="search-form">
<input class="form-control" [formControl]="schemasFilter" placeholder="{{ 'contents.searchSchemasPlaceholder' | sqxTranslate }}">
<ng-container header>
<a class="panel-close btn-collapse" [class.collapsed]="isCollapsed" (click)="toggle()">
<i [class.icon-angle-double-left]="!isCollapsed" [class.icon-angle-double-right]="isCollapsed"></i>
</a>
<i class="icon-search"></i>
</div>
</ng-container>
<ng-container secondHeader>
<ng-container *ngIf="!isCollapsed">
<sqx-shortcut keys="ctrl+shift+f" (trigger)="inputFind.focus()"></sqx-shortcut>
<div class="search-form">
<input class="form-control form-control-dark" #inputFind [formControl]="schemasFilter" placeholder="{{ 'contents.searchSchemasPlaceholder' | sqxTranslate }}">
<i class="icon-search"></i>
</div>
<ng-container>
<ng-container *ngIf="schemasState.publishedSchemas | async; let schemas">
<sqx-schema-category *ngFor="let category of schemasState.categories | async; trackBy: trackByCategory"
[schemaCategory]="category"
[schemasFilter]="schemasFilter.valueChanges | async"
[forContent]="true">
</sqx-schema-category>
</ng-container>
</ng-container>
<ng-container content>
<div [class.hidden]="isCollapsed">
<ng-container *ngIf="schemasState.publishedSchemas | async; let schemas">
<sqx-schema-category *ngFor="let category of schemasState.categories | async; trackBy: trackByCategory"
[schemaCategory]="category"
[schemasFilter]="schemasFilter.valueChanges | async"
[forContent]="true">
</sqx-schema-category>
</ng-container>
</div>
<div class="headline" [class.hidden]="!isCollapsed">
{{ 'common.schemas' | sqxTranslate }}
</div>
</ng-container>
</sqx-panel>
</sqx-layout>
<router-outlet></router-outlet>

23
frontend/app/features/content/pages/schemas/schemas-page.component.scss

@ -1,23 +0,0 @@
.btn-collapse {
& {
font-size: 1.2rem;
font-weight: 300;
line-height: 1rem;
right: 3rem;
}
&:hover {
color: $color-dark-foreground;
}
&.collapsed {
right: 1rem;
}
}
.headline {
font-size: 1.2rem;
font-weight: 400;
margin-top: 50px;
transform: rotate(-90deg);
}

20
frontend/app/features/content/pages/sidebar/sidebar-page.component.html

@ -1,16 +1,10 @@
<sqx-panel desiredWidth="20rem" [isBlank]="true" [isLazyLoaded]="false">
<ng-container title>
{{ 'common.sidebar' | sqxTranslate }}
</ng-container>
<ng-container content>
<sqx-content-extension
[url]="url | async"
[content]="contentsState.selectedContent | async"
[contentSchema]="(schemasState.selectedSchema | async)!">
</sqx-content-extension>
</ng-container>
</sqx-panel>
<sqx-layout titleText="i18n:common.sidebar" [width]="20" [white]="true" [padding]="true" [overflow]="true">
<sqx-content-extension
[url]="url | async"
[content]="contentsState.selectedContent | async"
[contentSchema]="(schemasState.selectedSchema | async)!">
</sqx-content-extension>
</sqx-layout>

2
frontend/app/features/content/shared/content-extension.component.html

@ -1 +1 @@
<iframe #iframe scrolling="no" width="100%"></iframe>
<iframe #iframe scrolling="no" width="100%" [attr.src]="computedUrl | sqxSafeResourceUrl"></iframe>

64
frontend/app/features/content/shared/content-extension.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
import { ChangeDetectionStrategy, Component, ElementRef, HostListener, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { ApiUrlConfig, ResourceOwner, Types } from '@app/framework/internal';
import { AppsState, AuthService, computeEditorUrl, ContentDto, SchemaDto } from '@app/shared';
@ -16,14 +16,10 @@ import { AppsState, AuthService, computeEditorUrl, ContentDto, SchemaDto } from
templateUrl: './content-extension.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ContentExtensionComponent extends ResourceOwner implements AfterViewInit, OnChanges {
export class ContentExtensionComponent extends ResourceOwner implements OnChanges {
private readonly context: any;
private computedUrl: string;
private isInitialized = false;
@Input()
public url?: string | null;
@Input()
public content?: ContentDto | null;
@ -33,9 +29,15 @@ export class ContentExtensionComponent extends ResourceOwner implements AfterVie
@ViewChild('iframe', { static: false })
public iframe: ElementRef<HTMLIFrameElement>;
@Input()
public set url(value: string | undefined | null) {
this.computedUrl = computeEditorUrl(value, this.appsState.snapshot.selectedSettings);
}
public computedUrl: string;
constructor(apiUrl: ApiUrlConfig, authService: AuthService,
private readonly appsState: AppsState,
private readonly renderer: Renderer2,
private readonly router: Router,
) {
super();
@ -49,12 +51,6 @@ export class ContentExtensionComponent extends ResourceOwner implements AfterVie
}
public ngOnChanges(changes: SimpleChanges) {
if (changes['url']) {
this.computedUrl = computeEditorUrl(this.url, this.appsState.snapshot.selectedSettings);
this.setupUrl();
}
if (changes['contentSchema']) {
this.context['schemaName'] = this.contentSchema?.name;
this.context['schemaId'] = this.contentSchema?.id;
@ -65,36 +61,26 @@ export class ContentExtensionComponent extends ResourceOwner implements AfterVie
}
}
private setupUrl() {
if (this.iframe?.nativeElement) {
this.iframe.nativeElement.src = this.computedUrl;
}
}
@HostListener('window:message', ['$event'])
public onWindowMessage(event: MessageEvent) {
if (event.source === this.iframe.nativeElement.contentWindow) {
const { type } = event.data;
public ngAfterViewInit() {
this.setupUrl();
if (type === 'started') {
this.isInitialized = true;
this.own(
this.renderer.listen('window', 'message', (event: MessageEvent) => {
if (event.source === this.iframe.nativeElement.contentWindow) {
const { type } = event.data;
this.sendInit();
this.sendContent();
} else if (type === 'resize') {
const { height } = event.data;
if (type === 'started') {
this.isInitialized = true;
this.iframe.nativeElement.height = `${height}px`;
} else if (type === 'navigate') {
const { url } = event.data;
this.sendInit();
this.sendContent();
} else if (type === 'resize') {
const { height } = event.data;
this.iframe.nativeElement.height = `${height}px`;
} else if (type === 'navigate') {
const { url } = event.data;
this.router.navigateByUrl(url);
}
}
}));
this.router.navigateByUrl(url);
}
}
}
private sendInit() {

6
frontend/app/features/content/shared/content-status.component.html

@ -1,6 +1,6 @@
<ng-container *ngIf="isMultiline; else simple">
<div class="content-status-summary">
<span class="content-status default mr-1" [style.color]="statusColor" title="{{tooltipText}}">
<span class="content-status default me-1" [style.color]="statusColor" title="{{tooltipText}}">
<i class="icon-circle icon-sm"></i>
</span>
@ -11,7 +11,7 @@
<div>
<span class="label">{{ 'contents.scheduledTo' | sqxTranslate }}&nbsp;</span>
<span class="content-status default mr-1" [style.color]="scheduled?.color" title="{{tooltipText}}">
<span class="content-status default me-1" [style.color]="scheduled?.color" title="{{tooltipText}}">
<i class="icon-circle icon-sm"></i>
</span>
@ -40,6 +40,6 @@
</span>
</ng-template>
<span class="content-status-label ml-1" *ngIf="isText">{{status}}</span>
<span class="content-status-label ms-1" *ngIf="isText">{{status}}</span>
</span>
</ng-template>

6
frontend/app/features/content/shared/content-status.component.scss

@ -1,12 +1,10 @@
.content-status {
&.default {
color: $color-text-decent;
}
&.pending {
color: $color-dark-black;
color: $color-black;
}
&-summary {
@ -16,7 +14,7 @@
&-scheduled {
color: $color-text !important;
font-size: .9rem;
font-size: $font-small;
font-weight: normal;
}

12
frontend/app/features/content/shared/due-time-selector.component.html

@ -5,16 +5,16 @@
</ng-container>
<ng-container content>
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" [(ngModel)]="dueTimeMode" value="Immediately" id="immediately" name="dueTimeMode">
<label class="custom-control-label" for="immediately">
<div class="form-check">
<input class="form-check-input" type="radio" [(ngModel)]="dueTimeMode" value="Immediately" id="immediately" name="dueTimeMode">
<label class="form-check-label" for="immediately">
{{ 'contents.changeStatusToImmediately' | sqxTranslate: { action: dueTimeAction } }}
</label>
</div>
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" [(ngModel)]="dueTimeMode" value="Scheduled" id="scheduled" name="dueTimeMode">
<label class="custom-control-label" for="scheduled">
<div class="form-check">
<input class="form-check-input" type="radio" [(ngModel)]="dueTimeMode" value="Scheduled" id="scheduled" name="dueTimeMode">
<label class="form-check-label" for="scheduled">
{{ 'contents.changeStatusToLater' | sqxTranslate: { action: dueTimeAction } }}
</label>
</div>

4
frontend/app/features/content/shared/forms/array-editor.component.html

@ -48,7 +48,7 @@
</cdk-virtual-scroll-viewport>
</div>
<div class="row no-gutters align-items-center">
<div class="row g-0 align-items-center">
<div class="col-auto">
<ng-container *ngIf="isArray; else component">
<ng-container *ngIf="hasField">
@ -91,7 +91,7 @@
</div>
<div class="col">
<button type="button" class="btn btn-text-danger ml-2" *ngIf="items.length > 0"
<button type="button" class="btn btn-text-danger ms-2" *ngIf="items.length > 0"
(sqxConfirmClick)="clear()"
confirmTitle="i18n:contents.arrayClearConfirmTitle"
confirmText="i18n:contents.arrayClearConfirmText"

2
frontend/app/features/content/shared/forms/array-editor.component.scss

@ -5,7 +5,7 @@
}
.array-container {
background: $color-border;
background: $color-border-lighter;
margin: 0;
margin-bottom: 1rem;
padding-bottom: 1rem;

4
frontend/app/features/content/shared/forms/array-item.component.html

@ -1,7 +1,7 @@
<div class="card item" [class.invalid]="isInvalid | async">
<div class="card-header drag-handle">
<div class="row">
<div class="col-auto pr-1">
<div class="col-auto pe-1">
<ng-content></ng-content>
</div>
<div class="col">
@ -10,7 +10,7 @@
<span class="header-title">{{title | async }}</span>
</div>
</div>
<div class="col-auto pr-4">
<div class="col-auto pe-4">
<button type="button" class="btn btn-text-secondary" [disabled]="isDisabled || isFirst" (click)="moveTop()" title="i18n:contents.arrayMoveTop">
<i class="icon-caret-top"></i>
</button>

6
frontend/app/features/content/shared/forms/array-item.component.scss

@ -7,10 +7,8 @@
}
.card {
& {
border: 1px solid darken($color-border, 5%);
border-left-width: 4px;
}
border: 1px solid darken($color-border, 5%);
border-left-width: 4px;
&-header {
line-height: 2.2rem;

6
frontend/app/features/content/shared/forms/assets-editor.component.html

@ -1,12 +1,12 @@
<div class="assets-container" (sqxDropFile)="addFiles($event)" [sqxDropDisabled]="snapshot.isDisabled" tabindex="1000">
<div class="header list">
<div class="row no-gutters">
<div class="row gx-2">
<div class="col" [class.disabled]="snapshot.isDisabled">
<div class="drop-area align-items-center" (click)="assetsDialog.show()" (sqxDropFile)="addFiles($event)" [sqxDropDisabled]="snapshot.isDisabled">
{{ 'contents.assetsUpload' | sqxTranslate }}
</div>
</div>
<div class="col-auto pl-1">
<div class="col-auto">
<div class="btn-group">
<button type="button" class="btn btn-secondary btn-toggle" [class.btn-primary]="snapshot.isListView" [disabled]="snapshot.isListView" (click)="changeView(true)">
<i class="icon-list"></i>
@ -21,7 +21,7 @@
<div class="body" (sqxResizeCondition)="setCompact($event)" [sqxResizeMinWidth]="600" [sqxResizeMaxWidth]="0">
<ng-container *ngIf="!snapshot.isListView; else listTemplate">
<div class="row no-gutters">
<div class="row g-0">
<sqx-asset *ngFor="let file of snapshot.assetFiles"
[assetFile]="file"
[isDisabled]="snapshot.isDisabled"

36
frontend/app/features/content/shared/forms/assets-editor.component.scss

@ -4,14 +4,12 @@
.assets {
&-container {
& {
background: $color-background;
height: $asset-height + 2rem;
overflow-x: hidden;
overflow-y: scroll;
padding: 1rem;
padding-bottom: 0;
}
background: $color-background;
height: $asset-height + 2rem;
overflow-x: hidden;
overflow-y: scroll;
padding: 1rem;
padding-bottom: 0;
}
}
@ -30,19 +28,15 @@
}
.drop-area {
& {
@include border-radius;
@include truncate-nowidth;
border: 2px dashed darken($color-border, 10%);
color: darken($color-border, 30%);
cursor: pointer;
font-size: 1rem;
font-weight: normal;
padding: 5px .5rem;
text-align: center;
text-decoration: none;
transition: border-color .4s ease;
}
@include truncate-nowidth;
border: 2px dashed darken($color-border, 10%);
border-radius: $border-radius;
color: darken($color-border, 30%);
cursor: pointer;
padding: 5px .5rem;
text-align: center;
text-decoration: none;
transition: border-color .4s ease;
&:hover {
text-decoration: underline;

31
frontend/app/features/content/shared/forms/field-editor.component.html

@ -3,7 +3,7 @@
{{field.displayName}} {{displaySuffix}} <span class="field-required" [class.hidden]="!field.properties.isRequired">*</span>
</label>
<small class="field-disabled pl-1" *ngIf="field.isDisabled">Disabled</small>
<small class="field-disabled ps-1" *ngIf="field.isDisabled">Disabled</small>
<sqx-control-errors *ngIf="form" [for]="editorControl" [fieldName]="field.displayName"></sqx-control-errors>
@ -39,9 +39,9 @@
<sqx-toggle [formControl]="editorControl" [threeStates]="!field.properties.isRequired"></sqx-toggle>
</ng-container>
<ng-container *ngSwitchCase="'Checkbox'">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" [formControl]="editorControl" id="{{uniqueId}}" sqxIndeterminateValue [threeStates]="!field.properties.isRequired">
<label class="custom-control-label" for="{{uniqueId}}"></label>
<div class="form-check">
<input class="form-check-input" type="checkbox" [formControl]="editorControl" id="{{uniqueId}}" sqxIndeterminateValue [threeStates]="!field.properties.isRequired">
<label class="form-check-label" for="{{uniqueId}}"></label>
</div>
</ng-container>
</ng-container>
@ -84,15 +84,15 @@
<sqx-stars [formControl]="editorControl" [maximumStars]="field.rawProperties.maxValue"></sqx-stars>
</ng-container>
<ng-container *ngSwitchCase="'Dropdown'">
<select class="custom-select" [formControl]="editorControl">
<select class="form-select" [formControl]="editorControl">
<option [ngValue]="null"></option>
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option>
</select>
</ng-container>
<ng-container *ngSwitchCase="'Radio'">
<div class="custom-control custom-radio custom-control-inline" *ngFor="let value of field.rawProperties.allowedValues">
<input class="custom-control-input" type="radio" [value]="value" [formControl]="editorControl" [name]="uniqueId" id="{{uniqueId}}_{{value}}">
<label class="custom-control-label" for="{{uniqueId}}_{{value}}">
<div class="form-check" *ngFor="let value of field.rawProperties.allowedValues">
<input class="form-check-input" type="radio" [value]="value" [formControl]="editorControl" [name]="uniqueId" id="{{uniqueId}}_{{value}}">
<label class="form-check-label" for="{{uniqueId}}_{{value}}">
{{value}}
</label>
</div>
@ -158,15 +158,15 @@
<sqx-stock-photo-editor [formControl]="editorControl"></sqx-stock-photo-editor>
</ng-container>
<ng-container *ngSwitchCase="'Dropdown'">
<select class="custom-select" [formControl]="editorControl">
<select class="form-select" [formControl]="editorControl">
<option [ngValue]="null"></option>
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option>
</select>
</ng-container>
<ng-container *ngSwitchCase="'Radio'">
<div class="custom-control custom-radio custom-control-inline" *ngFor="let value of field.rawProperties.allowedValues">
<input class="custom-control-input" type="radio" [value]="value" [formControl]="editorControl" [name]="uniqueId" id="{{uniqueId}}_{{value}}">
<label class="custom-control-label" for="{{uniqueId}}_{{value}}">
<div class="form-check custom-control-inline" *ngFor="let value of field.rawProperties.allowedValues">
<input class="form-check-input" type="radio" [value]="value" [formControl]="editorControl" [name]="uniqueId" id="{{uniqueId}}_{{value}}">
<label class="form-check-label" for="{{uniqueId}}_{{value}}">
{{value}}
</label>
</div>
@ -185,7 +185,7 @@
<sqx-checkbox-group [formControl]="editorControl" [values]="field.rawProperties.allowedValues"></sqx-checkbox-group>
</ng-container>
<ng-container *ngSwitchCase="'Dropdown'">
<select multiple class="custom-select" [formControl]="editorControl">
<select multiple class="form-select" [formControl]="editorControl">
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option>
</select>
</ng-container>
@ -198,12 +198,13 @@
</ng-template>
</div>
<div *ngIf="canUnset" class="unset" title="i18n:contents.unsetValue">
<div *ngIf="canUnset" class="unset" >
<button type="button" class="btn btn-sm btn-text-secondary force" [disabled]="isEmpty | async"
(sqxConfirmClick)="unset()"
confirmTitle="i18n:contents.unsetValueConfirmTitle"
confirmText="i18n:contents.unsetValueConfirmText"
confirmRememberKey="unsetValue">
confirmRememberKey="unsetValue"
title="i18n:contents.unsetValue">
<i class="icon-close"></i>
</button>
</div>

12
frontend/app/features/content/shared/forms/field-editor.component.scss

@ -1,7 +1,5 @@
.field {
& {
position: relative;
}
position: relative;
&-required {
color: $color-theme-error;
@ -9,7 +7,7 @@
&-disabled {
color: $color-border-dark;
font-size: .8rem;
font-size: $font-smallest;
font-weight: normal;
}
}
@ -18,14 +16,12 @@
@include absolute(-.5rem, 0);
i {
font-size: 80%;
font-size: $font-smallest;
}
}
.ui {
& {
margin-bottom: 1rem;
}
margin-bottom: 1rem;
&-separator {
border-bottom: 1px solid darken($color-border, 5%);

2
frontend/app/features/content/shared/forms/iframe-editor.component.html

@ -1,6 +1,6 @@
<div #container>
<div #inner [class.fullscreen]="snapshot.isFullscreen">
<iframe #iframe scrolling="no" width="100%"></iframe>
<iframe #iframe scrolling="no" width="100%" [attr.src]="computedUrl | sqxSafeResourceUrl"></iframe>
</div>
</div>

2
frontend/app/features/content/shared/forms/iframe-editor.component.scss

@ -6,7 +6,7 @@ iframe {
.fullscreen {
@include fixed(0, 0, 0, 0);
background: $panel-light-background;
background: $color-white;
border: 0;
border-radius: 0;
z-index: 1040;

169
frontend/app/features/content/shared/forms/iframe-editor.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnChanges, OnDestroy, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, HostListener, Input, OnChanges, OnDestroy, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Router } from '@angular/router';
import { DialogModel, DialogService, StatefulControlComponent, Types } from '@app/framework';
@ -29,10 +29,9 @@ interface State {
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class IFrameEditorComponent extends StatefulControlComponent<State, any> implements OnChanges, OnDestroy, AfterViewInit {
export class IFrameEditorComponent extends StatefulControlComponent<State, any> implements OnChanges, OnDestroy {
private value: any;
private isInitialized = false;
private computedUrl: string;
private assetsCorrelationId: any;
@ViewChild('iframe', { static: false })
@ -56,17 +55,19 @@ export class IFrameEditorComponent extends StatefulControlComponent<State, any>
@Input()
public language?: string | null;
@Input()
public url: string;
@Input()
public set disabled(value: boolean | null | undefined) {
this.setDisabledState(value === true);
}
public assetsDialog = new DialogModel();
@Input()
public set url(value: string | undefined | null) {
this.computedUrl = computeEditorUrl(value, this.appsState.snapshot.selectedSettings);
}
public fullscreen: boolean;
public computedUrl: string;
public assetsDialog = new DialogModel();
constructor(changeDetector: ChangeDetectorRef,
private readonly appsState: AppsState,
@ -84,12 +85,6 @@ export class IFrameEditorComponent extends StatefulControlComponent<State, any>
}
public ngOnChanges(changes: SimpleChanges) {
if (changes['url']) {
this.computedUrl = computeEditorUrl(this.url, this.appsState.snapshot.selectedSettings);
this.setupUrl();
}
if (this.iframe?.nativeElement) {
if (changes['formValue']) {
this.sendFormValue();
@ -105,86 +100,76 @@ export class IFrameEditorComponent extends StatefulControlComponent<State, any>
}
}
private setupUrl() {
if (this.iframe?.nativeElement) {
this.iframe.nativeElement.src = this.computedUrl;
}
}
@HostListener('window:message', ['$event'])
public onWindowMessage(event: MessageEvent) {
if (event.source === this.iframe.nativeElement.contentWindow) {
const { type } = event.data;
if (type === 'started') {
this.isInitialized = true;
this.sendInit();
this.sendFullscreen();
this.sendFormValue();
this.sendLanguage();
this.sendDisabled();
this.sendMoved();
this.sendValue();
} else if (type === 'resize') {
const { height } = event.data;
this.renderer.setStyle(this.iframe.nativeElement, 'height', `${height}px`);
} else if (type === 'navigate') {
const { url } = event.data;
this.router.navigateByUrl(url);
} else if (type === 'fullscreen') {
const { mode } = event.data;
public ngAfterViewInit() {
this.setupUrl();
this.own(
this.renderer.listen('window', 'message', (event: MessageEvent) => {
if (event.source === this.iframe.nativeElement.contentWindow) {
const { type } = event.data;
if (type === 'started') {
this.isInitialized = true;
this.sendInit();
this.sendFullscreen();
this.sendFormValue();
this.sendLanguage();
this.sendDisabled();
this.sendMoved();
this.sendValue();
} else if (type === 'resize') {
const { height } = event.data;
this.renderer.setStyle(this.iframe.nativeElement, 'height', `${height}px`);
} else if (type === 'navigate') {
const { url } = event.data;
this.router.navigateByUrl(url);
} else if (type === 'fullscreen') {
const { mode } = event.data;
if (mode !== this.snapshot.isFullscreen) {
this.toggleFullscreen(mode);
}
} else if (type === 'valueChanged') {
const { value } = event.data;
if (!Types.equals(this.value, value)) {
this.value = value;
this.callChange(value);
}
} else if (type === 'touched') {
this.callTouched();
} else if (type === 'notifyInfo') {
const { text } = event.data;
if (Types.isString(text)) {
this.dialogs.notifyInfo(text);
}
} else if (type === 'notifyError') {
const { text } = event.data;
if (Types.isString(text)) {
this.dialogs.notifyError(text);
}
} else if (type === 'confirm') {
const { text, title, correlationId } = event.data;
if (Types.isString(text) && Types.isString(title) && correlationId) {
this.dialogs.confirm(title, text).subscribe(result => {
this.sendMessage('confirmResult', { correlationId, result });
});
}
} else if (type === 'pickAssets') {
const { correlationId } = event.data;
if (correlationId) {
this.assetsCorrelationId = correlationId;
this.assetsDialog.show();
}
}
this.detectChanges();
if (mode !== this.snapshot.isFullscreen) {
this.toggleFullscreen(mode);
}
}));
} else if (type === 'valueChanged') {
const { value } = event.data;
if (!Types.equals(this.value, value)) {
this.value = value;
this.callChange(value);
}
} else if (type === 'touched') {
this.callTouched();
} else if (type === 'notifyInfo') {
const { text } = event.data;
if (Types.isString(text)) {
this.dialogs.notifyInfo(text);
}
} else if (type === 'notifyError') {
const { text } = event.data;
if (Types.isString(text)) {
this.dialogs.notifyError(text);
}
} else if (type === 'confirm') {
const { text, title, correlationId } = event.data;
if (Types.isString(text) && Types.isString(title) && correlationId) {
this.dialogs.confirm(title, text).subscribe(result => {
this.sendMessage('confirmResult', { correlationId, result });
});
}
} else if (type === 'pickAssets') {
const { correlationId } = event.data;
if (correlationId) {
this.assetsCorrelationId = correlationId;
this.assetsDialog.show();
}
}
this.detectChanges();
}
}
public pickAssets(assets: ReadonlyArray<AssetDto>) {

28
frontend/app/features/content/shared/forms/stock-photo-editor.component.html

@ -1,5 +1,4 @@
<div class="row no-gutters" (sqxResizeCondition)="setCompact($event)" [sqxResizeMinWidth]="600" [sqxResizeMaxWidth]="0">
<div class="row g-0" (sqxResizeCondition)="setCompact($event)" [sqxResizeMinWidth]="600" [sqxResizeMaxWidth]="0">
<div class="col-auto col-image" [class.expand]="snapshot.isCompact">
<input class="form-control value" [formControl]="valueControl" readonly>
@ -17,26 +16,25 @@
</div>
</ng-template>
</div>
<div class="col pl-4" *ngIf="!snapshot.isCompact">
<div class="col ps-4" *ngIf="!snapshot.isCompact">
<i class="icon-angle-left icon"></i>
<input class="form-control" [formControl]="stockPhotoSearch" placeholder="{{ 'contents.stockPhotoSearch' | sqxTranslate }}">
<sqx-list-view [isLoading]="snapshot.isLoading" [table]="true">
<div content>
<div class="photos">
<ng-container *ngIf="stockPhotos | async; let photos; trackBy: trackByPhoto">
<div *ngFor="let photo of photos" class="photo" [class.selected]="isSelected(photo)" (click)="selectPhoto(photo)">
<img [src]="photo.thumbUrl">
<div class="photos">
<ng-container *ngIf="stockPhotos | async; let photos; trackBy: trackByPhoto">
<div *ngFor="let photo of photos" class="photo" [class.selected]="isSelected(photo)" (click)="selectPhoto(photo)">
<img [src]="photo.thumbUrl">
<div class="photo-user">
<a class="photo-user-link" [href]="photo.userProfileUrl" sqxExternalLink sqxStopClick>
{{photo.user}}
</a>
</div>
<div class="photo-user">
<a class="photo-user-link" [href]="photo.userProfileUrl" sqxExternalLink sqxStopClick>
{{photo.user}}
</a>
</div>
</ng-container>
</div>
</div>
</ng-container>
</div>
</sqx-list-view>
</div>

44
frontend/app/features/content/shared/forms/stock-photo-editor.component.scss

@ -16,9 +16,7 @@ $height: 300px;
}
.value {
& {
padding-right: 2.5rem;
}
padding-right: 2.5rem;
&-clear {
@include absolute(0, 0, auto, auto);
@ -26,18 +24,16 @@ $height: 300px;
}
.preview {
& {
@include force-height($height);
align-items: center;
background: $color-background;
border: 0;
border-radius: .25rem;
color: $color-dark-foreground;
display: flex;
justify-content: center;
margin: 0;
margin-top: .5rem;
}
@include force-height($height);
align-items: center;
background: $color-background;
border: 0;
border-radius: .25rem;
color: $color-white;
display: flex;
justify-content: center;
margin: 0;
margin-top: .5rem;
&-empty {
padding: 1rem;
@ -70,14 +66,12 @@ sqx-list-view {
}
.photo {
& {
border: 2px solid $color-border;
border-radius: 0;
break-inside: avoid-column;
margin-bottom: .5rem;
margin-right: .5rem;
position: relative;
}
border: 2px solid $color-border;
border-radius: 0;
break-inside: avoid-column;
margin-bottom: .5rem;
margin-right: .5rem;
position: relative;
&:hover {
border-color: $color-theme-blue;
@ -96,8 +90,8 @@ sqx-list-view {
&-user-link {
@include truncate;
color: $color-dark-foreground;
font-size: 90%;
color: $color-white;
font-size: $font-small;
font-weight: normal;
}

2
frontend/app/features/content/shared/list/content-list-field.component.html

@ -22,7 +22,7 @@
</ng-container>
<ng-container *ngSwitchCase="metaFields.status">
<ng-container *ngIf="content.newStatus; else singleStatus">
<div class="row no-gutters status-grid">
<div class="row g-0 status-grid">
<div class="col">
<sqx-content-status [truncate]="true"
layout="text"

10
frontend/app/features/content/shared/list/content-value-editor.component.html

@ -9,7 +9,7 @@
<sqx-stars [formControlName]="field.name" [maximumStars]="field.rawProperties.maxValue"></sqx-stars>
</ng-container>
<ng-container *ngSwitchCase="'Dropdown'">
<select class="custom-select" [formControlName]="field.name">
<select class="form-select" [formControlName]="field.name">
<option [ngValue]="null"></option>
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option>
</select>
@ -25,7 +25,7 @@
<input class="form-control" type="text" [formControlName]="field.name" [placeholder]="field.displayPlaceholder" sqxTransformInput="Slugify">
</ng-container>
<ng-container *ngSwitchCase="'Dropdown'">
<select class="custom-select" [formControlName]="field.name">
<select class="form-select" [formControlName]="field.name">
<option [ngValue]="null"></option>
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option>
</select>
@ -38,9 +38,9 @@
<sqx-toggle [formControlName]="field.name" [threeStates]="!field.properties.isRequired"></sqx-toggle>
</ng-container>
<ng-container *ngSwitchCase="'Checkbox'">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" [formControlName]="field.name" id="{{uniqueId}}" sqxIndeterminateValue>
<label class="custom-control-label" for="{{uniqueId}}"></label>
<div class="form-check">
<input class="form-check-input" type="checkbox" [formControlName]="field.name" id="{{uniqueId}}" sqxIndeterminateValue>
<label class="form-check-label" for="{{uniqueId}}"></label>
</div>
</ng-container>
</ng-container>

2
frontend/app/features/content/shared/list/content-value.component.html

@ -4,5 +4,5 @@
</span>
</ng-container>
<ng-template #html>
<div class="html-value" [innerHTML]="value.html"></div>
<div class="htms-value" [innerHTML]="value.html"></div>
</ng-template>

8
frontend/app/features/content/shared/list/content-value.component.scss

@ -11,11 +11,11 @@
top: 50%;
}
img + span {
padding-left: 60px;
}
span {
@include truncate;
}
img + span {
padding-left: 60px;
}
}

8
frontend/app/features/content/shared/list/content.component.html

@ -1,16 +1,16 @@
<tr [sqxTabRouterLink]="link">
<td class="cell-select inline-edit" sqxStopClick>
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="{{content.id}}_selected"
<div class="form-check">
<input class="form-check-input" type="checkbox" id="{{content.id}}_selected"
[ngModel]="selected"
(ngModelChange)="selectedChange.emit($event)" />
<label class="custom-control-label" for="{{content.id}}_selected" ></label>
<label class="form-check-label" for="{{content.id}}_selected" ></label>
</div>
<ng-container *ngIf="isDirty">
<div class="edit-menu">
<button type="button" class="btn btn-text-secondary btn-cancel mr-2" (click)="cancel()" sqxStopClick>
<button type="button" class="btn btn-text-secondary btn-cancel me-2" (click)="cancel()" sqxStopClick>
<i class="icon-close"></i>
</button>

6
frontend/app/features/content/shared/list/content.component.scss

@ -1,11 +1,9 @@
.inline-edit {
& {
position: relative;
}
position: relative;
.edit-menu {
@include absolute(.75rem, auto, auto, .25rem);
background: $color-table-background;
background: $color-white;
border-right: 1px solid $color-border;
padding-right: 1rem;
white-space: nowrap;

2
frontend/app/features/content/shared/preview-button.component.html

@ -1,7 +1,7 @@
<ng-container *ngIf="snapshot.previewNameSelected">
<span>{{ 'common.preview' | sqxTranslate }}: </span>
<div class="btn-group ml-1" #buttonGroup>
<div class="btn-group ms-2" #buttonGroup>
<button type="button" class="btn btn-secondary" (click)="follow(snapshot.previewNameSelected)">
<i class="icon-external-link"></i> {{snapshot.previewNameSelected}}
</button>

20
frontend/app/features/content/shared/references/content-creator.component.html

@ -1,30 +1,26 @@
<sqx-modal-dialog (close)="emitComplete()" size="lg" [showFooter]="false">
<ng-container title>
<div class="row">
<div class="col-selector">
<select class="custom-select form-control-dark" [ngModel]="schema" (ngModelChange)="selectSchema($event)">
<option *ngFor="let schema of schemas" [ngValue]="schema">
{{ 'contents.referencesSelectSchema' | sqxTranslate: { schema: schema.displayName } }}
</option>
</select>
</div>
</div>
<select class="form-select" [ngModel]="schema" (ngModelChange)="selectSchema($event)">
<option *ngFor="let schema of schemas" [ngValue]="schema">
{{ 'contents.referencesSelectSchema' | sqxTranslate: { schema: schema.displayName } }}
</option>
</select>
</ng-container>
<ng-container tabs>
<div class="row no-gutters">
<div class="row gx-2 mt-3 mb-3">
<div class="col-auto">
<div *ngIf="schema && languages.length > 1">
<sqx-language-selector class="languages-buttons" [(selectedLanguage)]="language!" [languages]="languages"></sqx-language-selector>
</div>
</div>
<div class="col text-right">
<div class="col text-end">
<button type="button" class="btn btn-outline-success" (click)="save()">
{{ 'common.create' | sqxTranslate }}
</button>
<button type="button" class="btn btn-success ml-1" (click)="saveAndPublish()" *ngIf="schema?.canContentsCreateAndPublish">
<button type="button" class="btn btn-success ms-2" (click)="saveAndPublish()" *ngIf="schema?.canContentsCreateAndPublish">
{{ 'contents.referencesCreatePublish' | sqxTranslate }}
</button>

14
frontend/app/features/content/shared/references/content-creator.component.scss

@ -1,15 +1,7 @@
:host ::ng-deep {
.modal-tabs {
background: $color-white;
padding-left: 1.75rem;
padding-right: 1.75rem;
}
.modal-content {
.modal-body {
background: $color-background;
}
.form-control-dark {
border: 1px solid darken($color-modal-header-foreground, 20%);
padding-left: 1.5rem;
padding-right: 1.5rem;
}
}

2
frontend/app/features/content/shared/references/content-selector-item.component.html

@ -1,6 +1,6 @@
<tr (click)="toggle()">
<td class="cell-select" sqxStopClick>
<input type="checkbox" class="custom-control custom-checkbox"
<input type="checkbox" class="form-check"
[disabled]="!selectable"
[ngModel]="selected || !selectable"
(ngModelChange)="select($event)"

18
frontend/app/features/content/shared/references/content-selector.component.html

@ -1,8 +1,8 @@
<sqx-modal-dialog (close)="emitComplete()" size="lg" [fullHeight]="true" [flexBody]="true">
<sqx-modal-dialog (close)="emitComplete()" size="lg" [fullHeight]="true" [flexBody]="true" [hasTabs]="false">
<ng-container title>
<div class="row">
<div class="col-selector">
<select class="custom-select form-control-dark" [ngModel]="schema" (ngModelChange)="selectSchema($event)">
<select class="form-select" [ngModel]="schema" (ngModelChange)="selectSchema($event)">
<option *ngFor="let schema of schemas" [ngValue]="schema">
{{ 'contents.referencesSelectSchema' | sqxTranslate: { schema: schema.displayName } }}
</option>
@ -12,14 +12,14 @@
</ng-container>
<ng-container tabs>
<div class="row no-gutters">
<div class="row gx-2 mt-3 mb-3">
<ng-container *ngIf="schema">
<div class="col-auto">
<button type="button" class="btn btn-text-secondary" (click)="reload()">
<i class="icon-reset"></i>
</button>
</div>
<div class="col pl-1">
<div class="col">
<sqx-search-form formClass="form" placeholder="{{ 'contents.searchPlaceholder' | sqxTranslate }}"
[query]="contentsState.query | async"
[queryModel]="queryModel"
@ -27,7 +27,7 @@
</sqx-search-form>
</div>
<div class="col-auto pl-1" *ngIf="languages.length > 1">
<div class="col-auto" *ngIf="languages.length > 1">
<sqx-language-selector class="languages-buttons" [(selectedLanguage)]="language" [languages]="languages"></sqx-language-selector>
</div>
</ng-container>
@ -37,12 +37,12 @@
<ng-container content>
<ng-container *ngIf="schema">
<sqx-list-view [isLoading]="contentsState.isLoading | async" [syncedHeader]="true" [table]="true">
<ng-container syncedHeader>
<ng-container header>
<table class="table table-items table-fixed" [style.minWidth]="schema.defaultReferenceFields | sqxContentListWidth" #header>
<thead>
<tr>
<th class="cell-select">
<input type="checkbox" class="custom-control custom-checkbox"
<input type="checkbox" class="form-check"
[ngModel]="selectedAll"
(ngModelChange)="selectAll($event)">
</th>
@ -65,7 +65,7 @@
</table>
</ng-container>
<ng-container syncedContent>
<ng-container content>
<div class="table-container">
<table class="table table-items table-fixed" [style.minWidth]="schema.defaultReferenceFields | sqxContentListWidth" *ngIf="contentsState.contents | async; let contents" [sqxSyncWidth]="header">
<tbody *ngFor="let content of contents; trackBy: trackByContent"
@ -88,7 +88,7 @@
</ng-container>
<ng-container footer>
<button type="button" class="btn text-secondary" (click)="emitComplete()">
<button type="button" class="btn btn-text-secondary" (click)="emitComplete()">
{{ 'common.cancel' | sqxTranslate }}
</button>

10
frontend/app/features/content/shared/references/content-selector.component.scss

@ -2,14 +2,6 @@
.modal-body {
background: $color-background;
}
.modal-tabs {
background: $color-dark-foreground;
}
.form-control-dark {
border: 1px solid darken($color-modal-header-foreground, 20%);
}
}
.col-selector {
@ -18,7 +10,7 @@
.form-control {
@include absolute(-.125rem, auto, auto, 0);
@include force-width(300px);
color: $color-dark-foreground;
color: $color-white;
}
}

6
frontend/app/features/content/shared/references/reference-item.component.html

@ -12,8 +12,8 @@
</td>
<td class="cell-valid" *ngIf="validityVisible">
<span class="badge badge-pill badge-success" *ngIf="valid === true">VALID</span>
<span class="badge badge-pill badge-danger" *ngIf="valid === false">INVALID</span>
<span class="badge rounded-pill badge-success" *ngIf="valid === true">VALID</span>
<span class="badge rounded-pill badge-danger" *ngIf="valid === false">INVALID</span>
</td>
<td sqxContentListCell="meta.status.color">
@ -21,7 +21,7 @@
</td>
<td class="cell-label" *ngIf="!isCompact">
<span class="badge badge-pill truncate-inline badge-primary">{{content.schemaDisplayName}}</span>
<span class="badge rounded-pill truncate-inline badge-primary">{{content.schemaDisplayName}}</span>
</td>
<td class="cell-actions">

8
frontend/app/features/content/shared/references/reference-item.component.scss

@ -1,12 +1,10 @@
.reference-edit {
& {
@include hover-visible('.reference-menu');
position: relative;
}
@include hover-visible('.reference-menu');
position: relative;
.reference-menu {
@include absolute(0, -.25rem, auto, auto);
background: $color-table-background;
background: $color-white;
border: 0;
border-left: 1px solid $color-border;
padding-left: 1rem;

20
frontend/app/features/content/shared/references/references-editor.component.scss

@ -20,18 +20,14 @@
}
.drop-area {
& {
@include border-radius;
border: 2px dashed darken($color-border, 10%);
color: darken($color-border, 30%);
cursor: pointer;
font-size: 1rem;
font-weight: normal;
padding: 1rem;
text-align: center;
text-decoration: none;
transition: border-color .4s ease;
}
border: 2px dashed darken($color-border, 10%);
border-radius: $border-radius;
color: darken($color-border, 30%);
cursor: pointer;
padding: 1rem;
text-align: center;
text-decoration: none;
transition: border-color .4s ease;
a {
&:hover {

2
frontend/app/features/dashboard/pages/cards/api-calls-card.component.html

@ -2,7 +2,7 @@
<div class="card-header">
{{ 'dashboard.apiCallsCard' | sqxTranslate }}
<div class="float-right">
<div class="float-end">
<a class="force" (click)="downloadLog()">
<small>{{ 'dashboard.downloadLog' | sqxTranslate }}</small>
</a>

8
frontend/app/features/dashboard/pages/cards/api-performance-card.component.html

@ -2,11 +2,11 @@
<div class="card-header">
{{ 'dashboard.apiPerformanceCard' | sqxTranslate: { summary: chartSummary } }}
<div class="float-right">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="stacked" [ngModel]="isStacked" (ngModelChange)="isStackedChange.emit($event)">
<div class="float-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="stacked" [ngModel]="isStacked" (ngModelChange)="isStackedChange.emit($event)">
<label class="custom-control-label" for="stacked">
<label class="form-check-label" for="stacked">
{{ 'dashboard.stackedChart' | sqxTranslate }}
</label>
</div>

8
frontend/app/features/dashboard/pages/cards/api-traffic-card.component.html

@ -2,11 +2,11 @@
<div class="card-header">
{{ 'dashboard.trafficHeader' | sqxTranslate }}: {{chartSummary | sqxFileSize}}
<div class="float-right">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="stacked" [ngModel]="isStacked" (ngModelChange)="isStackedChange.emit($event)">
<div class="float-end">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="stacked" [ngModel]="isStacked" (ngModelChange)="isStackedChange.emit($event)">
<label class="custom-control-label" for="stacked">
<label class="form-check-label" for="stacked">
{{ 'dashboard.stackedChart' | sqxTranslate }}
</label>
</div>

6
frontend/app/features/dashboard/pages/dashboard-config.component.html

@ -6,10 +6,10 @@
<ng-container *sqxModal="dropdownModal">
<div class="dropdown-menu" [sqxAnchoredTo]="buttonSettings" @fade position="bottom-right">
<div class="dropdown-item" *ngFor="let item of configDefaults">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="field_{{item.type}}" [ngModel]="isSelected(item)" (ngModelChange)="addOrRemove(item)">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="field_{{item.type}}" [ngModel]="isSelected(item)" (ngModelChange)="addOrRemove(item)">
<label class="custom-control-label" for="field_{{item.type}}">
<label class="form-check-label" for="field_{{item.type}}">
{{item.name | sqxTranslate}}
</label>
</div>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save