From 6dc7ca4d3807c654be04aad47ba067c269851979 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 14 May 2021 15:45:23 +0200 Subject: [PATCH] Feature/components (#698) * Started to work on components. * Cleanup * Just some stupid refactoring. * Continued with components. * Backend structure for component. * UI fixes. * Better handling for unpublished schemas. * Saving changes. * Fix OpenAPI * Tests fixed. * Support for components. * Recursive level guard. * Schema fix. --- backend/i18n/frontend_en.json | 12 +- backend/i18n/frontend_it.json | 8 + backend/i18n/frontend_nl.json | 8 + backend/i18n/source/backend_en.json | 4 + backend/i18n/source/frontend_en.json | 8 + .../Contents/Component.cs | 19 + .../InvariantPartitioning.cs | 6 +- .../Schemas/ComponentFieldProperties.cs | 57 +++ .../Schemas/ComponentsFieldProperties.cs | 61 +++ .../Schemas/FieldBase.cs | 2 +- .../Schemas/FieldExtensions.cs | 44 ++ .../Schemas/Fields.cs | 168 ++++++-- .../Schemas/IField.cs | 4 +- .../Schemas/IFieldPropertiesVisitor.cs | 4 + .../Schemas/IFieldVisitor.cs | 4 + .../Schemas/IMetadataProvider.cs | 23 ++ .../Schemas/SchemaType.cs | 3 +- .../ConvertContent/ContentConverter.cs | 6 +- .../ConvertContent/FieldConverters.cs | 165 +++++++- .../ConvertContent/StringFormatter.cs | 10 + .../ConvertContent/ValueConverters.cs | 52 +-- .../DefaultValues/DefaultValueFactory.cs | 10 + .../ExtractReferenceIds/ReferencesCleaner.cs | 10 + .../ReferencesExtractor.cs | 60 ++- .../GenerateEdmSchema/EdmTypeVisitor.cs | 69 +++- .../JsonSchemaExtensions.cs | 6 +- .../GenerateJsonSchema/JsonTypeVisitor.cs | 141 +++++-- .../Scripting/ScriptVars.cs | 4 +- .../DefaultFieldValueValidatorsFactory.cs | 47 ++- .../DefaultValidatorsFactory.cs | 6 +- .../ValidateContent/IValidatorsFactory.cs | 6 +- .../ValidateContent/JsonValueConverter.cs | 79 +++- .../ValidateContent/JsonValueValidator.cs | 89 +++-- .../Validators/ComponentValidator.cs | 37 ++ .../Validators/ObjectValidator.cs | 3 +- .../AppProvider.cs | 70 ++++ .../Apps/RolePermissionsProvider.cs | 4 +- .../DomainObject/ContentDomainObject.cs | 3 +- .../Guards/SingletonExtensions.cs | 14 +- .../DomainObject/Guards/WorkflowExtensions.cs | 4 +- .../Types/Contents/FieldInputVisitor.cs | 10 + .../GraphQL/Types/Contents/FieldVisitor.cs | 10 + .../GraphQL/Types/Contents/SchemaInfo.cs | 9 +- .../Contents/Queries/ContentQueryService.cs | 9 +- .../Contents/Queries/Steps/ConvertData.cs | 6 +- .../Queries/Steps/EnrichWithSchema.cs | 2 +- .../Guards/FieldPropertiesValidator.cs | 17 +- .../Schemas/SchemasSearchSource.cs | 4 +- .../Newtonsoft/ConverterContractResolver.cs | 1 - backend/src/Squidex.Shared/Permissions.cs | 40 +- backend/src/Squidex.Shared/Texts.it.resx | 12 + backend/src/Squidex.Shared/Texts.nl.resx | 12 + backend/src/Squidex.Shared/Texts.resx | 12 + backend/src/Squidex.Web/ApiController.cs | 18 +- .../src/Squidex.Web/ApiPermissionAttribute.cs | 4 +- .../EnrichWithSchemaIdCommandMiddleware.cs | 5 +- backend/src/Squidex.Web/IAppFeature.cs | 4 +- backend/src/Squidex.Web/ISchemaFeature.cs | 4 +- .../src/Squidex.Web/Pipeline/AppFeature.cs | 14 +- .../src/Squidex.Web/Pipeline/AppResolver.cs | 2 +- .../src/Squidex.Web/Pipeline/SchemaFeature.cs | 14 +- .../Squidex.Web/Pipeline/SchemaResolver.cs | 13 +- .../Squidex.Web/Pipeline/UsageMiddleware.cs | 8 +- backend/src/Squidex.Web/Resources.cs | 2 +- .../SchemaMustBePublishedAttribute.cs | 16 + .../Api/Config/OpenApi/OpenApiServices.cs | 2 + .../Api/Config/OpenApi/QueryExtensions.cs | 8 +- .../Contents/ContentsController.cs | 121 +++--- .../Contents/Generator/OperationsBuilder.cs | 4 +- .../Generator/SchemasOpenApiGenerator.cs | 35 +- .../Contents/Models/BulkUpdateContentsDto.cs | 4 +- .../Controllers/Contents/Models/ContentDto.cs | 10 +- .../Contents/Models/ContentsDto.cs | 4 +- .../Contents/Models/CreateContentDto.cs | 4 +- .../Contents/Models/ImportContentsDto.cs | 4 +- .../Contents/Models/UpsertContentDto.cs | 4 +- .../Api/Controllers/Rules/RulesController.cs | 10 +- .../Converters/FieldPropertiesDtoFactory.cs | 10 + .../Controllers/Schemas/Models/FieldDto.cs | 4 +- .../Fields/ComponentFieldPropertiesDto.cs | 29 ++ .../Fields/ComponentsFieldPropertiesDto.cs | 39 ++ .../Schemas/Models/NestedFieldDto.cs | 2 +- .../Controllers/Schemas/Models/SchemaDto.cs | 2 +- .../Schemas/SchemaFieldsController.cs | 118 +++--- .../Controllers/Schemas/SchemasController.cs | 92 ++--- .../Model/Schemas/SchemaTests.cs | 12 +- .../ConvertContent/ContentConversionTests.cs | 124 ++++-- .../ConvertContent/StringFormatterTests.cs | 48 +++ .../ConvertContent/ValueConvertersTests.cs | 8 +- .../ReferenceExtractionTests.cs | 87 +++- .../GenerateJsonSchema/JsonSchemaTests.cs | 1 + .../ValidateContent/ComponentFieldTests.cs | 137 +++++++ .../ValidateContent/ComponentsFieldTests.cs | 187 +++++++++ .../ValidationTestExtensions.cs | 68 +++- .../Validators/ComponentValidatorTests.cs | 65 +++ .../TestHelpers/TestUtils.cs | 15 +- .../DomainObject/ContentDomainObjectTests.cs | 2 +- .../DomainObject/Guards/GuardContentTests.cs | 44 +- .../Queries/ContentQueryServiceTests.cs | 3 +- .../ComponentsFieldPropertiesTests.cs | 44 ++ .../Schemas/SchemasSearchSourceTests.cs | 24 +- .../Collections/ImmutableListTests.cs | 1 - .../ApiPermissionAttributeTests.cs | 11 +- ...nrichWithSchemaIdCommandMiddlewareTests.cs | 11 +- .../Pipeline/SchemaResolverTests.cs | 100 +++-- .../Pipeline/UsageMiddlewareTests.cs | 17 +- .../TestSuite.ApiTests/SchemaTests.cs | 7 +- frontend/app-config/karma-test-shim.js | 2 +- .../administration/state/users.state.ts | 3 +- .../features/apps/pages/app.component.html | 2 +- frontend/app/features/content/declarations.ts | 3 +- frontend/app/features/content/module.ts | 11 +- .../content-history-page.component.html | 4 +- .../pages/content/content-page.component.html | 4 +- .../pages/content/content-page.component.ts | 4 +- .../pages/schemas/schemas-page.component.ts | 8 +- .../shared/forms/array-editor.component.html | 143 ++++--- .../shared/forms/array-editor.component.ts | 44 +- .../shared/forms/array-item.component.html | 4 +- .../shared/forms/array-item.component.ts | 30 +- ....html => component-section.component.html} | 0 ....scss => component-section.component.scss} | 0 ...nent.ts => component-section.component.ts} | 14 +- .../shared/forms/component.component.html | 44 ++ .../shared/forms/component.component.scss | 5 + .../shared/forms/component.component.ts | 81 ++++ .../shared/forms/field-editor.component.html | 20 + .../shared/list/content.component.html | 2 +- .../references/content-creator.component.html | 2 +- .../references/content-creator.component.ts | 36 +- .../references/content-selector.component.ts | 33 +- .../rules/pages/rules/rule.component.html | 2 +- frontend/app/features/schemas/declarations.ts | 4 + frontend/app/features/schemas/module.ts | 13 +- .../pages/schema/fields/field.component.html | 4 +- .../fields/forms/field-form-ui.component.html | 6 + .../field-form-validation.component.html | 26 +- .../fields/types/component-ui.component.html | 0 .../fields/types/component-ui.component.scss | 0 .../fields/types/component-ui.component.ts | 26 ++ .../types/component-validation.component.html | 12 + .../types/component-validation.component.scss | 5 + .../types/component-validation.component.ts | 31 ++ .../fields/types/components-ui.component.html | 0 .../fields/types/components-ui.component.scss | 0 .../fields/types/components-ui.component.ts | 26 ++ .../components-validation.component.html | 30 ++ .../components-validation.component.scss | 5 + .../types/components-validation.component.ts | 31 ++ .../pages/schema/schema-page.component.html | 2 +- .../pages/schemas/schema-form.component.html | 17 + .../pages/schemas/schemas-page.component.html | 2 +- .../pages/schemas/schemas-page.component.ts | 6 +- .../client-connect-form.component.html | 6 +- .../settings/pages/plans/plan.component.html | 4 +- .../forms/undefinable-form-array.spec.ts | 6 +- .../angular/forms/undefinable-form-array.ts | 8 +- .../forms/undefinable-form-group.spec.ts | 71 ++++ .../angular/forms/undefinable-form-group.ts | 87 ++++ frontend/app/framework/declarations.ts | 1 + .../framework/utils/array-extensions.spec.ts | 10 + .../app/framework/utils/array-extensions.ts | 14 + .../assets/asset-folder.component.html | 2 +- .../components/schema-category.component.html | 7 +- .../components/schema-category.component.ts | 5 +- .../search/queries/query-path.component.html | 2 +- frontend/app/shared/declarations.ts | 3 +- .../shared/guards/load-schemas.guard.spec.ts | 36 ++ .../app/shared/guards/load-schemas.guard.ts | 24 ++ .../schema-must-exist-published.guard.spec.ts | 34 +- .../schema-must-exist-published.guard.ts | 4 +- ...schema-must-not-be-singleton.guard.spec.ts | 8 +- .../schema-must-not-be-singleton.guard.ts | 4 +- frontend/app/shared/module.ts | 3 +- .../shared/services/schemas.service.spec.ts | 52 ++- .../app/shared/services/schemas.service.ts | 12 +- frontend/app/shared/services/schemas.types.ts | 48 +++ .../shared/state/contents.forms-helpers.ts | 23 +- .../app/shared/state/contents.forms.spec.ts | 2 +- frontend/app/shared/state/contents.forms.ts | 377 ++++++++++++------ .../state/contents.forms.visitors.spec.ts | 74 +++- .../shared/state/contents.forms.visitors.ts | 30 +- frontend/app/shared/state/schemas.forms.ts | 10 + .../app/shared/state/schemas.state.spec.ts | 90 ++--- frontend/app/shared/state/schemas.state.ts | 87 ++-- .../shell/pages/home/home-page.component.html | 4 +- frontend/app/theme/icomoon/Read Me.txt | 7 + frontend/app/theme/icomoon/demo.html | 44 +- frontend/app/theme/icomoon/fonts/icomoon.eot | Bin 32412 -> 32680 bytes frontend/app/theme/icomoon/fonts/icomoon.svg | 5 +- frontend/app/theme/icomoon/fonts/icomoon.ttf | Bin 32248 -> 32516 bytes frontend/app/theme/icomoon/fonts/icomoon.woff | Bin 32324 -> 32592 bytes .../app/theme/icomoon/icons/component.svg | 73 ++++ frontend/app/theme/icomoon/selection.json | 2 +- frontend/app/theme/icomoon/style.css | 19 +- 195 files changed, 4009 insertions(+), 1136 deletions(-) create mode 100644 backend/src/Squidex.Domain.Apps.Core.Model/Contents/Component.cs create mode 100644 backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentFieldProperties.cs create mode 100644 backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentsFieldProperties.cs create mode 100644 backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IMetadataProvider.cs create mode 100644 backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ComponentValidator.cs create mode 100644 backend/src/Squidex.Web/SchemaMustBePublishedAttribute.cs create mode 100644 backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentFieldPropertiesDto.cs create mode 100644 backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentsFieldPropertiesDto.cs create mode 100644 backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentFieldTests.cs create mode 100644 backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentsFieldTests.cs create mode 100644 backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/ComponentValidatorTests.cs create mode 100644 backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/DomainObject/Guards/FieldProperties/ComponentsFieldPropertiesTests.cs rename frontend/app/features/content/shared/forms/{array-section.component.html => component-section.component.html} (100%) rename frontend/app/features/content/shared/forms/{array-section.component.scss => component-section.component.scss} (100%) rename frontend/app/features/content/shared/forms/{array-section.component.ts => component-section.component.ts} (67%) create mode 100644 frontend/app/features/content/shared/forms/component.component.html create mode 100644 frontend/app/features/content/shared/forms/component.component.scss create mode 100644 frontend/app/features/content/shared/forms/component.component.ts create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/component-ui.component.html create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/component-ui.component.scss create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/component-ui.component.ts create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.html create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.scss create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.ts create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.html create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.scss create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.ts create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.html create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.scss create mode 100644 frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.ts create mode 100644 frontend/app/framework/angular/forms/undefinable-form-group.spec.ts create mode 100644 frontend/app/framework/angular/forms/undefinable-form-group.ts create mode 100644 frontend/app/shared/guards/load-schemas.guard.spec.ts create mode 100644 frontend/app/shared/guards/load-schemas.guard.ts create mode 100644 frontend/app/theme/icomoon/Read Me.txt create mode 100644 frontend/app/theme/icomoon/icons/component.svg diff --git a/backend/i18n/frontend_en.json b/backend/i18n/frontend_en.json index 423855d30..53c074cfc 100644 --- a/backend/i18n/frontend_en.json +++ b/backend/i18n/frontend_en.json @@ -231,6 +231,7 @@ "common.cluster": "Cluster", "common.clusterPageTitle": "Cluster", "common.comments": "Comments", + "common.components": "Components", "common.confirm": "Confirm", "common.consumers": "Consumers", "common.content": "Content", @@ -363,6 +364,7 @@ "common.workflow": "Workflow", "common.workflows": "Workflows", "common.yes": "Yes", + "contents.addComponent": "Add Component", "contents.arrayAddItem": "Add Item", "contents.arrayClear": "Clear", "contents.arrayClearConfirmText": "Do you really want to clear the array?", @@ -383,6 +385,8 @@ "contents.changeStatusTo": "Change content item(s) to {action}", "contents.changeStatusToImmediately": "Set to {action} immediately.", "contents.changeStatusToLater": "Set to {action} at a later point date and time.", + "contents.componentNoSchema": "Add at least one schema to set component.", + "contents.componentsNoSchema": "Add at least one schema to add components.", "contents.contentNotValid": "Content element not valid, please check the field with the red bar on the left in all languages (if localizable).", "contents.contentTab.editor": "Editor", "contents.contentTab.references": "References", @@ -399,8 +403,8 @@ "contents.deleteConfirmText": "Do you really want to delete the content?", "contents.deleteConfirmTitle": "Delete content", "contents.deleteManyConfirmText": "Do you really want to delete the selected content items?", - "contents.deleteReferrerConfirmText": "The content is referenced by another content item.\n\nDo you really want to delete/unpublish this content?", - "contents.deleteReferrerConfirmTitle": "Delete/unpublish content", + "contents.deleteReferrerConfirmText": "The content is referenced by another content item.\n\nDo you really want to delete this content?", + "contents.deleteReferrerConfirmTitle": "Delete content", "contents.deleteVersionConfirmText": "Do you really want to delete this version?", "contents.deleteVersionFailed": "Failed to delete version. Please reload.", "contents.draftNew": "New Draft", @@ -760,6 +764,8 @@ "schemas.fieldTypes.assets.sizeMax": "Min Size", "schemas.fieldTypes.assets.sizeMin": "Max Size", "schemas.fieldTypes.boolean.description": "Yes or no, true or false.", + "schemas.fieldTypes.component.description": "Embed another schema to this content.", + "schemas.fieldTypes.components.description": "Embed another schemas to this content as array.", "schemas.fieldTypes.dateTime.defaultMode": "Default Mode", "schemas.fieldTypes.dateTime.description": "Events date, opening hours.", "schemas.fieldTypes.dateTime.rangeMax": "Max Value", @@ -805,6 +811,8 @@ "schemas.loadFailed": "Failed to load schemas. Please reload.", "schemas.loadSchemaFailed": "Failed to load schema. Please reload.", "schemas.lockFieldFailed": "Failed to lock field. Please reload.", + "schemas.modeComponent": "Component", + "schemas.modeComponentDescription": "Can only be embedded to component fields...", "schemas.modeMultiple": "Multiple contents", "schemas.modeMultipleDescription": "Best for multiple instances like blog posts, pages, authors, products...", "schemas.modeSingle": "Single content", diff --git a/backend/i18n/frontend_it.json b/backend/i18n/frontend_it.json index 510a7e18c..3bf76d595 100644 --- a/backend/i18n/frontend_it.json +++ b/backend/i18n/frontend_it.json @@ -231,6 +231,7 @@ "common.cluster": "Cluster", "common.clusterPageTitle": "Cluster", "common.comments": "Commenti", + "common.components": "Components", "common.confirm": "Conferma", "common.consumers": "Servizi", "common.content": "Contenuto", @@ -363,6 +364,7 @@ "common.workflow": "Workflow", "common.workflows": "Workflow", "common.yes": "Sì", + "contents.addComponent": "Add Component", "contents.arrayAddItem": "Aggiungi un elemento", "contents.arrayClear": "Pulisci", "contents.arrayClearConfirmText": "Sei sicuro di voler cancellare l'array?", @@ -383,6 +385,8 @@ "contents.changeStatusTo": "Cambia gli elementi del contenuto in {action}", "contents.changeStatusToImmediately": "Imposta {action} immediatamente.", "contents.changeStatusToLater": "Imposta {action} ad una data e ora successiva.", + "contents.componentNoSchema": "Add at least one schema to set component.", + "contents.componentsNoSchema": "Add at least one schema to add components.", "contents.contentNotValid": "Un elemento del contenuto non è valido, verifica il campo con la barra rossa per tutte le lingue impostate (se presenti).", "contents.contentTab.editor": "Editor", "contents.contentTab.references": "Collegato a", @@ -760,6 +764,8 @@ "schemas.fieldTypes.assets.sizeMax": "Dimensione Min", "schemas.fieldTypes.assets.sizeMin": "Dimensione Max", "schemas.fieldTypes.boolean.description": "Si o no, vero o falso.", + "schemas.fieldTypes.component.description": "Embed another schema to this content.", + "schemas.fieldTypes.components.description": "Embed another schemas to this content as array.", "schemas.fieldTypes.dateTime.defaultMode": "Modalità predefinita", "schemas.fieldTypes.dateTime.description": "Data degli eventi, orari di apertura.", "schemas.fieldTypes.dateTime.rangeMax": "Valore Max", @@ -805,6 +811,8 @@ "schemas.loadFailed": "Non è stato possibile caricare gli schemi. Per favore ricarica.", "schemas.loadSchemaFailed": "Non è stato possibile caricare lo schema. Per favore ricarica.", "schemas.lockFieldFailed": "Non è stato possibile bloccare il campo. Per favore ricarica.", + "schemas.modeComponent": "Component", + "schemas.modeComponentDescription": "Can only be embedded to component fields...", "schemas.modeMultiple": "Contenuti multipli", "schemas.modeMultipleDescription": "Ideale per contenuti multipli come post di blog, pagine, autori, prodotti...", "schemas.modeSingle": "Singolo contenuto", diff --git a/backend/i18n/frontend_nl.json b/backend/i18n/frontend_nl.json index 40fa88482..0bf9db833 100644 --- a/backend/i18n/frontend_nl.json +++ b/backend/i18n/frontend_nl.json @@ -231,6 +231,7 @@ "common.cluster": "Cluster", "common.clusterPageTitle": "Cluster", "common.comments": "Reacties", + "common.components": "Components", "common.confirm": "Bevestigen", "common.consumers": "Consumenten", "common.content": "Inhoud", @@ -363,6 +364,7 @@ "common.workflow": "Workflow", "common.workflows": "Workflows", "common.yes": "Ja", + "contents.addComponent": "Add Component", "contents.arrayAddItem": "Item toevoegen", "contents.arrayClear": "Clear", "contents.arrayClearConfirmText": "Do you really want to clear the array?", @@ -383,6 +385,8 @@ "contents.changeStatusTo": "Verander inhoud item(s) in {action}", "contents.changeStatusToImmediately": "Zet onmiddellijk op {action}.", "contents.changeStatusToLater": "Zet op {action} op een latere datum en tijd.", + "contents.componentNoSchema": "Add at least one schema to set component.", + "contents.componentsNoSchema": "Add at least one schema to add components.", "contents.contentNotValid": "Inhoudselement niet geldig, controleer het veld met de rode balk aan de linkerkant in alle talen (indien lokaliseerbaar).", "contents.contentTab.editor": "Editor", "contents.contentTab.references": "References", @@ -760,6 +764,8 @@ "schemas.fieldTypes.assets.sizeMax": "Min. grootte", "schemas.fieldTypes.assets.sizeMin": "Max. grootte", "schemas.fieldTypes.boolean.description": "Ja of nee, waar of niet waar.", + "schemas.fieldTypes.component.description": "Embed another schema to this content.", + "schemas.fieldTypes.components.description": "Embed another schemas to this content as array.", "schemas.fieldTypes.dateTime.defaultMode": "Standaardmodus", "schemas.fieldTypes.dateTime.description": "Datum van evenementen, openingstijden.", "schemas.fieldTypes.dateTime.rangeMax": "Max. waarde", @@ -805,6 +811,8 @@ "schemas.loadFailed": "Kan schema's niet laden. Laad opnieuw.", "schemas.loadSchemaFailed": "Kan schema niet laden. Laad opnieuw.", "schemas.lockFieldFailed": "Kan veld niet vergrendelen. Laad opnieuw.", + "schemas.modeComponent": "Component", + "schemas.modeComponentDescription": "Can only be embedded to component fields...", "schemas.modeMultiple": "Meerdere inhoud", "schemas.modeMultipleDescription": "Beste voor meerdere instanties, zoals blogposts, pagina's, auteurs, producten ...", "schemas.modeSingle": "Enkele inhoud", diff --git a/backend/i18n/source/backend_en.json b/backend/i18n/source/backend_en.json index 60a7c749b..48393394a 100644 --- a/backend/i18n/source/backend_en.json +++ b/backend/i18n/source/backend_en.json @@ -125,6 +125,9 @@ "contents.invalidArrayOfObjects": "Invalid json type, expected array of objects.", "contents.invalidArrayOfStrings": "Invalid json type, expected array of strings.", "contents.invalidBoolean": "Invalid json type, expected boolean.", + "contents.invalidComponentNoObject": "Invalid json object, expected object with 'schemaId' field.", + "contents.invalidComponentNoType": "Invalid component. No 'schemaId' field found.", + "contents.invalidComponentUnknownSchema": "Invalid component. Cannot find schema.", "contents.invalidGeolocation": "Invalid json type, expected latitude/longitude object.", "contents.invalidGeolocationLatitude": "Latitude must be between -90 and 90.", "contents.invalidGeolocationLongitude": "Longitude must be between -180 and 180.", @@ -132,6 +135,7 @@ "contents.invalidString": "Invalid json type, expected string.", "contents.listReferences": "{count} Reference(s)", "contents.referenced": "Content is referenced by another content and cannot be deleted or unpublished.", + "contents.schemaNotPublished": "Schema not published.", "contents.singletonNotChangeable": "Singleton content cannot be updated.", "contents.singletonNotCreatable": "Singleton content cannot be created.", "contents.singletonNotDeletable": "Singleton content cannot be deleted.", diff --git a/backend/i18n/source/frontend_en.json b/backend/i18n/source/frontend_en.json index 7daa8257a..53c074cfc 100644 --- a/backend/i18n/source/frontend_en.json +++ b/backend/i18n/source/frontend_en.json @@ -231,6 +231,7 @@ "common.cluster": "Cluster", "common.clusterPageTitle": "Cluster", "common.comments": "Comments", + "common.components": "Components", "common.confirm": "Confirm", "common.consumers": "Consumers", "common.content": "Content", @@ -363,6 +364,7 @@ "common.workflow": "Workflow", "common.workflows": "Workflows", "common.yes": "Yes", + "contents.addComponent": "Add Component", "contents.arrayAddItem": "Add Item", "contents.arrayClear": "Clear", "contents.arrayClearConfirmText": "Do you really want to clear the array?", @@ -383,6 +385,8 @@ "contents.changeStatusTo": "Change content item(s) to {action}", "contents.changeStatusToImmediately": "Set to {action} immediately.", "contents.changeStatusToLater": "Set to {action} at a later point date and time.", + "contents.componentNoSchema": "Add at least one schema to set component.", + "contents.componentsNoSchema": "Add at least one schema to add components.", "contents.contentNotValid": "Content element not valid, please check the field with the red bar on the left in all languages (if localizable).", "contents.contentTab.editor": "Editor", "contents.contentTab.references": "References", @@ -760,6 +764,8 @@ "schemas.fieldTypes.assets.sizeMax": "Min Size", "schemas.fieldTypes.assets.sizeMin": "Max Size", "schemas.fieldTypes.boolean.description": "Yes or no, true or false.", + "schemas.fieldTypes.component.description": "Embed another schema to this content.", + "schemas.fieldTypes.components.description": "Embed another schemas to this content as array.", "schemas.fieldTypes.dateTime.defaultMode": "Default Mode", "schemas.fieldTypes.dateTime.description": "Events date, opening hours.", "schemas.fieldTypes.dateTime.rangeMax": "Max Value", @@ -805,6 +811,8 @@ "schemas.loadFailed": "Failed to load schemas. Please reload.", "schemas.loadSchemaFailed": "Failed to load schema. Please reload.", "schemas.lockFieldFailed": "Failed to lock field. Please reload.", + "schemas.modeComponent": "Component", + "schemas.modeComponentDescription": "Can only be embedded to component fields...", "schemas.modeMultiple": "Multiple contents", "schemas.modeMultipleDescription": "Best for multiple instances like blog posts, pages, authors, products...", "schemas.modeSingle": "Single content", diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Component.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Component.cs new file mode 100644 index 000000000..3fe5ba24c --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Contents/Component.cs @@ -0,0 +1,19 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; + +#pragma warning disable SA1313 // Parameter names should begin with lower-case letter + +namespace Squidex.Domain.Apps.Core.Contents +{ + public sealed record Component(string Type, JsonObject Data, Schema Schema) + { + public const string Discriminator = "schemaId"; + } +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs b/backend/src/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs index b3e9a082f..47bc4e6d2 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs @@ -13,6 +13,8 @@ namespace Squidex.Domain.Apps.Core { public static readonly InvariantPartitioning Instance = new InvariantPartitioning(); public static readonly string Key = "iv"; + public static readonly string Name = "Invariant"; + public static readonly string Description = "invariant value"; public string Master { @@ -28,7 +30,7 @@ namespace Squidex.Domain.Apps.Core { if (Contains(key)) { - return "Invariant"; + return Name; } return null; @@ -61,7 +63,7 @@ namespace Squidex.Domain.Apps.Core public override string ToString() { - return "invariant value"; + return Description; } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentFieldProperties.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentFieldProperties.cs new file mode 100644 index 000000000..eab4efcb8 --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentFieldProperties.cs @@ -0,0 +1,57 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Linq; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; + +namespace Squidex.Domain.Apps.Core.Schemas +{ + public sealed record ComponentFieldProperties : FieldProperties + { + public DomainId SchemaId + { + init + { + if (value != default) + { + SchemaIds = ImmutableList.Create(value); + } + else + { + SchemaIds = null; + } + } + get + { + return SchemaIds?.FirstOrDefault() ?? default; + } + } + + public ImmutableList? SchemaIds { get; init; } + + public override T Accept(IFieldPropertiesVisitor visitor, TArgs args) + { + return visitor.Visit(this, args); + } + + public override T Accept(IFieldVisitor visitor, IField field, TArgs args) + { + return visitor.Visit((IField)field, args); + } + + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) + { + return Fields.Component(id, name, partitioning, this, settings); + } + + public override NestedField CreateNestedField(long id, string name, IFieldSettings? settings = null) + { + return Fields.Component(id, name, this, settings); + } + } +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentsFieldProperties.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentsFieldProperties.cs new file mode 100644 index 000000000..519347a86 --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ComponentsFieldProperties.cs @@ -0,0 +1,61 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Linq; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; + +namespace Squidex.Domain.Apps.Core.Schemas +{ + public sealed record ComponentsFieldProperties : FieldProperties + { + public int? MinItems { get; init; } + + public int? MaxItems { get; init; } + + public DomainId SchemaId + { + init + { + if (value != default) + { + SchemaIds = ImmutableList.Create(value); + } + else + { + SchemaIds = null; + } + } + get + { + return SchemaIds?.FirstOrDefault() ?? default; + } + } + + public ImmutableList? SchemaIds { get; init; } + + public override T Accept(IFieldPropertiesVisitor visitor, TArgs args) + { + return visitor.Visit(this, args); + } + + public override T Accept(IFieldVisitor visitor, IField field, TArgs args) + { + return visitor.Visit((IField)field, args); + } + + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings? settings = null) + { + return Fields.Components(id, name, partitioning, this, settings); + } + + public override NestedField CreateNestedField(long id, string name, IFieldSettings? settings = null) + { + return Fields.Components(id, name, this, settings); + } + } +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldBase.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldBase.cs index 9c143aa53..754cf734a 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldBase.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldBase.cs @@ -11,7 +11,7 @@ using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas { - public abstract class FieldBase + public abstract class FieldBase : IMetadataProvider { private Dictionary metadata; diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldExtensions.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldExtensions.cs index ab55f6a08..e2c0cc1e7 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldExtensions.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldExtensions.cs @@ -6,8 +6,10 @@ // ========================================================================== using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using NamedIdStatic = Squidex.Infrastructure.NamedId; namespace Squidex.Domain.Apps.Core.Schemas @@ -24,6 +26,48 @@ namespace Squidex.Domain.Apps.Core.Schemas return fields.Where(x => IsForApi(x, withHidden)); } + public static IEnumerable GetSharedFields(this IField field, ImmutableList? schemaIds, bool withHidden) + { + if (schemaIds == null || schemaIds.Count == 0) + { + return Enumerable.Empty(); + } + + var allFields = + schemaIds + .Select(x => field.GetResolvedSchema(x)).NotNull() + .SelectMany(x => x.Fields.ForApi(withHidden)) + .GroupBy(x => new { x.Name, Type = x.RawProperties.GetType() }).Where(x => x.Count() == 1) + .Select(x => x.First()); + + return allFields; + } + + public static T SetResolvedSchema(this T metadataProvider, DomainId id, Schema schema) where T : IMetadataProvider + { + var key = $"ResolvedSchema_{id}"; + + metadataProvider.Metadata[key] = schema; + + return metadataProvider; + } + + public static Schema? GetResolvedSchema(this T metadataProvider, object id) where T : IMetadataProvider + { + var key = $"ResolvedSchema_{id}"; + + return metadataProvider.GetMetadata(key); + } + + public static bool TryGetResolvedSchema(this T metadataProvider, object id, [MaybeNullWhen(false)] out Schema schema) where T : IMetadataProvider + { + var key = $"ResolvedSchema_{id}"; + + schema = metadataProvider.GetMetadata(key); + + return schema != null; + } + public static bool IsForApi(this T field, bool withHidden = false) where T : IField { return (withHidden || !field.IsHidden) && !field.RawProperties.IsUIProperty(); diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs index aa7ced7d9..16760a3a3 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs @@ -16,112 +16,158 @@ namespace Squidex.Domain.Apps.Core.Schemas return new ArrayField(id, name, partitioning, fields); } - public static ArrayField Array(long id, string name, Partitioning partitioning, ArrayFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField Array(long id, string name, Partitioning partitioning, + ArrayFieldProperties? properties = null, IFieldSettings? settings = null) { return new ArrayField(id, name, partitioning, properties, settings); } - public static RootField Assets(long id, string name, Partitioning partitioning, AssetsFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Assets(long id, string name, Partitioning partitioning, + AssetsFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField Boolean(long id, string name, Partitioning partitioning, BooleanFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Boolean(long id, string name, Partitioning partitioning, + BooleanFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField DateTime(long id, string name, Partitioning partitioning, DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Component(long id, string name, Partitioning partitioning, + ComponentFieldProperties? properties = null, IFieldSettings? settings = null) + { + return new RootField(id, name, partitioning, properties, settings); + } + + public static RootField Components(long id, string name, Partitioning partitioning, + ComponentsFieldProperties? properties = null, IFieldSettings? settings = null) + { + return new RootField(id, name, partitioning, properties, settings); + } + + public static RootField DateTime(long id, string name, Partitioning partitioning, + DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField Geolocation(long id, string name, Partitioning partitioning, GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Geolocation(long id, string name, Partitioning partitioning, + GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField Json(long id, string name, Partitioning partitioning, JsonFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Json(long id, string name, Partitioning partitioning, + JsonFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField Number(long id, string name, Partitioning partitioning, NumberFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Number(long id, string name, Partitioning partitioning, + NumberFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField References(long id, string name, Partitioning partitioning, ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField References(long id, string name, Partitioning partitioning, + ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField String(long id, string name, Partitioning partitioning, StringFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField String(long id, string name, Partitioning partitioning, + StringFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField Tags(long id, string name, Partitioning partitioning, TagsFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField Tags(long id, string name, Partitioning partitioning, + TagsFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static RootField UI(long id, string name, Partitioning partitioning, UIFieldProperties? properties = null, IFieldSettings? settings = null) + public static RootField UI(long id, string name, Partitioning partitioning, + UIFieldProperties? properties = null, IFieldSettings? settings = null) { return new RootField(id, name, partitioning, properties, settings); } - public static NestedField Assets(long id, string name, AssetsFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Assets(long id, string name, + AssetsFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField Boolean(long id, string name, BooleanFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Boolean(long id, string name, + BooleanFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField DateTime(long id, string name, DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Component(long id, string name, + ComponentFieldProperties? properties = null, IFieldSettings? settings = null) + { + return new NestedField(id, name, properties, settings); + } + + public static NestedField Components(long id, string name, + ComponentsFieldProperties? properties = null, IFieldSettings? settings = null) + { + return new NestedField(id, name, properties, settings); + } + + public static NestedField DateTime(long id, string name, + DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField Geolocation(long id, string name, GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Geolocation(long id, string name, + GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField Json(long id, string name, JsonFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Json(long id, string name, + JsonFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField Number(long id, string name, NumberFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Number(long id, string name, + NumberFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField References(long id, string name, ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField References(long id, string name, + ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField String(long id, string name, StringFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField String(long id, string name, + StringFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField Tags(long id, string name, TagsFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField Tags(long id, string name, + TagsFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static NestedField UI(long id, string name, UIFieldProperties? properties = null, IFieldSettings? settings = null) + public static NestedField UI(long id, string name, + UIFieldProperties? properties = null, IFieldSettings? settings = null) { return new NestedField(id, name, properties, settings); } - public static Schema AddArray(this Schema schema, long id, string name, Partitioning partitioning, Func? handler = null, ArrayFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddArray(this Schema schema, long id, string name, Partitioning partitioning, + Func? handler = null, ArrayFieldProperties? properties = null, IFieldSettings? settings = null) { var field = Array(id, name, partitioning, properties, settings); @@ -133,102 +179,140 @@ namespace Squidex.Domain.Apps.Core.Schemas return schema.AddField(field); } - public static Schema AddAssets(this Schema schema, long id, string name, Partitioning partitioning, AssetsFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddAssets(this Schema schema, long id, string name, Partitioning partitioning, + AssetsFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(Assets(id, name, partitioning, properties, settings)); } - public static Schema AddBoolean(this Schema schema, long id, string name, Partitioning partitioning, BooleanFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddBoolean(this Schema schema, long id, string name, Partitioning partitioning, + BooleanFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(Boolean(id, name, partitioning, properties, settings)); } - public static Schema AddDateTime(this Schema schema, long id, string name, Partitioning partitioning, DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddComponent(this Schema schema, long id, string name, Partitioning partitioning, + ComponentFieldProperties? properties = null, IFieldSettings? settings = null) + { + return schema.AddField(Component(id, name, partitioning, properties, settings)); + } + + public static Schema AddComponents(this Schema schema, long id, string name, Partitioning partitioning, + ComponentsFieldProperties? properties = null, IFieldSettings? settings = null) + { + return schema.AddField(Components(id, name, partitioning, properties, settings)); + } + + public static Schema AddDateTime(this Schema schema, long id, string name, Partitioning partitioning, + DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(DateTime(id, name, partitioning, properties, settings)); } - public static Schema AddGeolocation(this Schema schema, long id, string name, Partitioning partitioning, GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddGeolocation(this Schema schema, long id, string name, Partitioning partitioning, + GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(Geolocation(id, name, partitioning, properties, settings)); } - public static Schema AddJson(this Schema schema, long id, string name, Partitioning partitioning, JsonFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddJson(this Schema schema, long id, string name, Partitioning partitioning, + JsonFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(Json(id, name, partitioning, properties, settings)); } - public static Schema AddNumber(this Schema schema, long id, string name, Partitioning partitioning, NumberFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddNumber(this Schema schema, long id, string name, Partitioning partitioning, + NumberFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(Number(id, name, partitioning, properties, settings)); } - public static Schema AddReferences(this Schema schema, long id, string name, Partitioning partitioning, ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddReferences(this Schema schema, long id, string name, Partitioning partitioning, + ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(References(id, name, partitioning, properties, settings)); } - public static Schema AddString(this Schema schema, long id, string name, Partitioning partitioning, StringFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddString(this Schema schema, long id, string name, Partitioning partitioning, + StringFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(String(id, name, partitioning, properties, settings)); } - public static Schema AddTags(this Schema schema, long id, string name, Partitioning partitioning, TagsFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddTags(this Schema schema, long id, string name, Partitioning partitioning, + TagsFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(Tags(id, name, partitioning, properties, settings)); } - public static Schema AddUI(this Schema schema, long id, string name, Partitioning partitioning, UIFieldProperties? properties = null, IFieldSettings? settings = null) + public static Schema AddUI(this Schema schema, long id, string name, Partitioning partitioning, + UIFieldProperties? properties = null, IFieldSettings? settings = null) { return schema.AddField(UI(id, name, partitioning, properties, settings)); } - public static ArrayField AddAssets(this ArrayField field, long id, string name, AssetsFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddAssets(this ArrayField field, long id, string name, + AssetsFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(Assets(id, name, properties, settings)); } - public static ArrayField AddBoolean(this ArrayField field, long id, string name, BooleanFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddBoolean(this ArrayField field, long id, string name, + BooleanFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(Boolean(id, name, properties, settings)); } - public static ArrayField AddDateTime(this ArrayField field, long id, string name, DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddComponents(this ArrayField field, long id, string name, + ComponentFieldProperties? properties = null, IFieldSettings? settings = null) + { + return field.AddField(Component(id, name, properties, settings)); + } + + public static ArrayField AddDateTime(this ArrayField field, long id, string name, + DateTimeFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(DateTime(id, name, properties, settings)); } - public static ArrayField AddGeolocation(this ArrayField field, long id, string name, GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddGeolocation(this ArrayField field, long id, string name, + GeolocationFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(Geolocation(id, name, properties, settings)); } - public static ArrayField AddJson(this ArrayField field, long id, string name, JsonFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddJson(this ArrayField field, long id, string name, + JsonFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(Json(id, name, properties, settings)); } - public static ArrayField AddNumber(this ArrayField field, long id, string name, NumberFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddNumber(this ArrayField field, long id, string name, + NumberFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(Number(id, name, properties, settings)); } - public static ArrayField AddReferences(this ArrayField field, long id, string name, ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddReferences(this ArrayField field, long id, string name, + ReferencesFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(References(id, name, properties, settings)); } - public static ArrayField AddString(this ArrayField field, long id, string name, StringFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddString(this ArrayField field, long id, string name, + StringFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(String(id, name, properties, settings)); } - public static ArrayField AddTags(this ArrayField field, long id, string name, TagsFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddTags(this ArrayField field, long id, string name, + TagsFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(Tags(id, name, properties, settings)); } - public static ArrayField AddUI(this ArrayField field, long id, string name, UIFieldProperties? properties = null, IFieldSettings? settings = null) + public static ArrayField AddUI(this ArrayField field, long id, string name, + UIFieldProperties? properties = null, IFieldSettings? settings = null) { return field.AddField(UI(id, name, properties, settings)); } diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs index 4f9aadac1..9372b23a1 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs @@ -7,7 +7,7 @@ namespace Squidex.Domain.Apps.Core.Schemas { - public interface IField : IFieldSettings + public interface IField : IFieldSettings, IMetadataProvider { long Id { get; } @@ -17,4 +17,4 @@ namespace Squidex.Domain.Apps.Core.Schemas T Accept(IFieldVisitor visitor, TArgs args); } -} \ No newline at end of file +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldPropertiesVisitor.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldPropertiesVisitor.cs index d629b657f..610fd2f23 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldPropertiesVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldPropertiesVisitor.cs @@ -15,6 +15,10 @@ namespace Squidex.Domain.Apps.Core.Schemas T Visit(BooleanFieldProperties properties, TArgs args); + T Visit(ComponentFieldProperties properties, TArgs args); + + T Visit(ComponentsFieldProperties properties, TArgs args); + T Visit(DateTimeFieldProperties properties, TArgs args); T Visit(GeolocationFieldProperties properties, TArgs args); diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldVisitor.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldVisitor.cs index 1c63c7457..f581089a0 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldVisitor.cs @@ -15,6 +15,10 @@ namespace Squidex.Domain.Apps.Core.Schemas T Visit(IField field, TArgs args); + T Visit(IField field, TArgs args); + + T Visit(IField field, TArgs args); + T Visit(IField field, TArgs args); T Visit(IField field, TArgs args); diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IMetadataProvider.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IMetadataProvider.cs new file mode 100644 index 000000000..4d6f0e034 --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/IMetadataProvider.cs @@ -0,0 +1,23 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; + +namespace Squidex.Domain.Apps.Core.Schemas +{ + public interface IMetadataProvider + { + IDictionary Metadata { get; } + + T? GetMetadata(string key, T? defaultValue = default); + + T GetMetadata(string key, Func defaultValueFactory); + + bool HasMetadata(string key); + } +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaType.cs b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaType.cs index 8ba4671c4..8a210bcbe 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaType.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Model/Schemas/SchemaType.cs @@ -10,6 +10,7 @@ namespace Squidex.Domain.Apps.Core.Schemas public enum SchemaType { Default, - Singleton + Singleton, + Component } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs index 6705a20a4..c08bf5562 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs @@ -30,7 +30,7 @@ namespace Squidex.Domain.Apps.Core.ConvertContent if (newData != null) { - newData = ConvertData(converters, field, newData); + newData = ConvertData(field, newData, converters); } if (newData != null) @@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Core.ConvertContent return result; } - private static ContentFieldData? ConvertData(FieldConverter[] converters, IRootField field, ContentFieldData data) + private static ContentFieldData? ConvertData(IRootField field, ContentFieldData data, FieldConverter[] converters) { if (converters != null) { @@ -60,4 +60,4 @@ namespace Squidex.Domain.Apps.Core.ConvertContent return data; } } -} \ No newline at end of file +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs index 5f2f403e3..57fb4c92c 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs @@ -180,32 +180,171 @@ namespace Squidex.Domain.Apps.Core.ConvertContent { return (data, field) => { - foreach (var (key, value) in data.ToList()) + ContentFieldData? newData = null; + + foreach (var (key, value) in data) { - var newValue = value; + var newValue = ConvertByType(field, value, null, converters); - for (var i = 0; i < converters.Length; i++) + if (newValue == null) + { + newData ??= new ContentFieldData(data); + newData.Remove(key); + } + else if (!ReferenceEquals(newValue, value)) { - newValue = converters[i](newValue!, field, null); + newData ??= new ContentFieldData(data); + newData[key] = newValue; + } + } - if (newValue == null) - { - break; - } + return newData ?? data; + }; + } + + private static IJsonValue? ConvertByType(T field, IJsonValue? value, IArrayField? parent, ValueConverter[] converters) where T : IField + { + switch (field) + { + case IArrayField arrayField: + return ConvertArray(arrayField, value, converters); + + case IField: + return ConvertComponent(field, value, converters); + + case IField: + return ConvertComponents(field, value, converters); + + default: + return ConvertValue(field, value, parent, converters); + } + } + + private static IJsonValue? ConvertArray(IArrayField field, IJsonValue? value, ValueConverter[] converters) + { + if (value is JsonArray array) + { + JsonArray? result = null; + + for (int i = 0, j = 0; i < array.Count; i++, j++) + { + var newValue = ConvertArrayItem(field, array[i], converters); + + if (newValue == null) + { + result ??= new JsonArray(array); + result.RemoveAt(j); + j--; } + else if (!ReferenceEquals(newValue, array[i])) + { + result ??= new JsonArray(array); + result[j] = newValue; + } + } + + return result ?? array; + } + + return null; + } + + private static IJsonValue? ConvertComponents(IField field, IJsonValue? value, ValueConverter[] converters) + { + if (value is JsonArray array) + { + JsonArray? result = null; + + for (int i = 0, j = 0; i < array.Count; i++, j++) + { + var newValue = ConvertComponent(field, array[i], converters); if (newValue == null) { - data.Remove(key); + result ??= new JsonArray(array); + result.RemoveAt(j); + j--; } - else if (!ReferenceEquals(newValue, value)) + else if (!ReferenceEquals(newValue, array[i])) { - data[key] = newValue; + result ??= new JsonArray(array); + result[j] = newValue; } } - return data; - }; + return result ?? array; + } + + return null; + } + + private static IJsonValue? ConvertComponent(IField field, IJsonValue? value, ValueConverter[] converters) + { + if (value is JsonObject obj && obj.TryGetValue(Component.Discriminator, out var type) && field.TryGetResolvedSchema(type.Value, out var schema)) + { + return ConvertNested(schema.FieldCollection, obj, null, converters); + } + + return null; + } + + private static IJsonValue? ConvertArrayItem(IArrayField field, IJsonValue? value, ValueConverter[] converters) + { + if (value is JsonObject obj) + { + return ConvertNested(field.FieldCollection, obj, field, converters); + } + + return null; + } + + private static IJsonValue ConvertNested(FieldCollection fields, JsonObject source, IArrayField? parent, ValueConverter[] converters) where T : IField + { + JsonObject? result = null; + + foreach (var (key, value) in source) + { + var newValue = value; + + if (fields.ByName.TryGetValue(key, out var field)) + { + newValue = ConvertByType(field, value, parent, converters); + } + else if (key != Component.Discriminator) + { + newValue = null; + } + + if (newValue == null) + { + result ??= new JsonObject(source); + result.Remove(key); + } + else if (!ReferenceEquals(newValue, value)) + { + result ??= new JsonObject(source); + result[key] = newValue; + } + } + + return result ?? source; + } + + private static IJsonValue? ConvertValue(IField field, IJsonValue? value, IArrayField? parent, ValueConverter[] converters) + { + var newValue = value; + + for (var i = 0; i < converters.Length; i++) + { + newValue = converters[i](newValue!, field, parent); + + if (newValue == null) + { + break; + } + } + + return newValue; } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs index 11dde4071..fcab56a46 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/StringFormatter.cs @@ -65,6 +65,16 @@ namespace Squidex.Domain.Apps.Core.ConvertContent } } + public string Visit(ComponentFieldProperties properties, Args args) + { + return "{ Component }"; + } + + public string Visit(ComponentsFieldProperties properties, Args args) + { + return FormatArray(args.Value, "Component", "Components"); + } + public string Visit(DateTimeFieldProperties properties, Args args) { return args.Value.ToString(); diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs index 06553b3de..6750128b0 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs @@ -16,7 +16,7 @@ using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ConvertContent { - public delegate IJsonValue? ValueConverter(IJsonValue value, IField field, IArrayField? parent = null); + public delegate IJsonValue? ValueConverter(IJsonValue value, IField field, IArrayField? parent); public static class ValueConverters { @@ -110,55 +110,5 @@ namespace Squidex.Domain.Apps.Core.ConvertContent return value; }; } - - public static ValueConverter ForNested(params ValueConverter[] converters) - { - if (converters?.Any() != true) - { - return Noop; - } - - return (value, field, parent) => - { - if (value is JsonArray array && field is IArrayField arrayField) - { - foreach (var nested in array.OfType()) - { - foreach (var (fieldName, nestedValue) in nested.ToList()) - { - var newValue = nestedValue; - - if (arrayField.FieldsByName.TryGetValue(fieldName, out var nestedField)) - { - for (var i = 0; i < converters.Length; i++) - { - newValue = converters[i](newValue!, nestedField, arrayField); - - if (newValue == null) - { - break; - } - } - } - else - { - newValue = null; - } - - if (newValue == null) - { - nested.Remove(fieldName); - } - else if (!ReferenceEquals(nestedValue, newValue)) - { - nested[fieldName] = newValue; - } - } - } - } - - return value; - }; - } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs index 4947153d8..b1351c5b6 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/DefaultValues/DefaultValueFactory.cs @@ -63,6 +63,16 @@ namespace Squidex.Domain.Apps.Core.DefaultValues return JsonValue.Create(value); } + public IJsonValue Visit(ComponentFieldProperties properties, Args args) + { + return JsonValue.Null; + } + + public IJsonValue Visit(ComponentsFieldProperties properties, Args args) + { + return JsonValue.Array(); + } + public IJsonValue Visit(GeolocationFieldProperties properties, Args args) { return JsonValue.Null; diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs index c1427ea43..02404c39e 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs @@ -56,6 +56,16 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds return args.Value; } + public IJsonValue Visit(IField field, Args args) + { + return args.Value; + } + + public IJsonValue Visit(IField field, Args args) + { + return args.Value; + } + public IJsonValue Visit(IField field, Args args) { return args.Value; diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs index 0bf74200a..fdceae9af 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs @@ -6,7 +6,7 @@ // ========================================================================== using System.Collections.Generic; -using System.Linq; +using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; using Squidex.Infrastructure.Json.Objects; @@ -48,15 +48,9 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { if (args.Value is JsonArray array) { - foreach (var item in array.OfType()) + for (var i = 0; i < array.Count; i++) { - foreach (var nestedField in field.Fields) - { - if (item.TryGetValue(nestedField.Name, out var nestedValue)) - { - nestedField.Accept(this, new Args(nestedValue, args.Result, args.ResultLimit)); - } - } + ExtractFromArrayItem(field, array[i], args); } } @@ -82,6 +76,26 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds return None.Value; } + public None Visit(IField field, Args args) + { + ExtractFromComponent(field, args.Value, args); + + return None.Value; + } + + public None Visit(IField field, Args args) + { + if (args.Value is JsonArray array) + { + for (var i = 0; i < array.Count; i++) + { + ExtractFromComponent(field, array[i], args); + } + } + + return None.Value; + } + public None Visit(IField field, Args args) { return None.Value; @@ -117,6 +131,34 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds return None.Value; } + private void ExtractFromArrayItem(IArrayField field, IJsonValue value, Args args) + { + if (value is JsonObject obj) + { + foreach (var nestedField in field.Fields) + { + if (obj.TryGetValue(nestedField.Name, out var nestedValue)) + { + nestedField.Accept(this, new Args(nestedValue, args.Result, args.ResultLimit)); + } + } + } + } + + private void ExtractFromComponent(IField field, IJsonValue value, Args args) + { + if (value is JsonObject obj && obj.TryGetValue(Component.Discriminator, out var type) && field.TryGetResolvedSchema(type.Value, out var schema)) + { + foreach (var componentField in schema.Fields) + { + if (obj.TryGetValue(componentField.Name, out var componentValue)) + { + componentField.Accept(this, new Args(componentValue, args.Result, args.ResultLimit)); + } + } + } + } + private static void AddIds(ref Args args) { var added = 0; diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs index ef31aed81..37cdbc4d3 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateEdmSchema/EdmTypeVisitor.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using Microsoft.OData.Edm; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Text; @@ -13,6 +14,7 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema { internal sealed class EdmTypeVisitor : IFieldVisitor { + private const int MaxDepth = 5; private static readonly EdmComplexType JsonType = new EdmComplexType("Squidex", "Json", null, false, true); private static readonly EdmTypeVisitor Instance = new EdmTypeVisitor(); @@ -20,9 +22,18 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema { public readonly EdmTypeFactory Factory; - public Args(EdmTypeFactory factory) + public readonly int Level; + + public Args(EdmTypeFactory factory, int level) { Factory = factory; + + Level = level; + } + + public Args Increment() + { + return new Args(Factory, Level + 1); } } @@ -32,29 +43,14 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema public static IEdmTypeReference? BuildType(IField field, EdmTypeFactory factory) { - var args = new Args(factory); + var args = new Args(factory, 0); return field.Accept(Instance, args); } public IEdmTypeReference? Visit(IArrayField field, Args args) { - var (fieldEdmType, created) = args.Factory($"Data.{field.Name.ToPascalCase()}.Item"); - - if (created) - { - foreach (var nestedField in field.Fields) - { - var nestedEdmType = nestedField.Accept(this, args); - - if (nestedEdmType != null) - { - fieldEdmType.AddStructuralProperty(nestedField.Name.EscapeEdmField(), nestedEdmType); - } - } - } - - return new EdmComplexTypeReference(fieldEdmType, false); + return CreateNestedType(field, field.Fields.ForApi(true), args); } public IEdmTypeReference? Visit(IField field, Args args) @@ -67,6 +63,16 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema return CreatePrimitive(EdmPrimitiveTypeKind.Boolean, field); } + public IEdmTypeReference? Visit(IField field, Args args) + { + return CreateNestedType(field, field.GetSharedFields(field.Properties.SchemaIds, true), args); + } + + public IEdmTypeReference? Visit(IField field, Args args) + { + return CreateNestedType(field, field.GetSharedFields(field.Properties.SchemaIds, true), args); + } + public IEdmTypeReference? Visit(IField field, Args args) { return CreatePrimitive(EdmPrimitiveTypeKind.DateTimeOffset, field); @@ -121,5 +127,32 @@ namespace Squidex.Domain.Apps.Core.GenerateEdmSchema { return new EdmComplexTypeReference(JsonType, !field.RawProperties.IsRequired); } + + private IEdmTypeReference? CreateNestedType(IField field, IEnumerable nested, Args args) + { + if (args.Level > MaxDepth) + { + return null; + } + + var (fieldEdmType, created) = args.Factory($"Data.{field.Name.ToPascalCase()}.Nested"); + + if (created) + { + var nestedArgs = args.Increment(); + + foreach (var sharedField in nested) + { + var nestedEdmType = sharedField.Accept(this, nestedArgs); + + if (nestedEdmType != null) + { + fieldEdmType.AddStructuralProperty(sharedField.Name.EscapeEdmField(), nestedEdmType); + } + } + } + + return new EdmComplexTypeReference(fieldEdmType, false); + } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs index 5693d1130..56d1504b8 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonSchemaExtensions.cs @@ -24,7 +24,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema foreach (var field in schema.Fields.ForApi()) { - var property = JsonTypeVisitor.BuildProperty(field, null, false); + var property = JsonTypeVisitor.BuildProperty(field); if (property != null) { @@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema foreach (var field in schema.Fields.ForApi(withHidden)) { - var propertyItem = JsonTypeVisitor.BuildProperty(field, null, withHidden); + var propertyItem = JsonTypeVisitor.BuildProperty(field, schemaResolver, withHidden); if (propertyItem != null) { @@ -75,7 +75,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema foreach (var partitionKey in partitioning.AllKeys) { - var propertyItem = JsonTypeVisitor.BuildProperty(field, null, withHidden); + var propertyItem = JsonTypeVisitor.BuildProperty(field, withHiddenFields: withHidden); if (propertyItem != null) { diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs index d67b55959..793838280 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs @@ -7,8 +7,12 @@ using System; using System.Collections.ObjectModel; +using System.Linq; using NJsonSchema; +using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Core.GenerateJsonSchema @@ -17,6 +21,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema internal sealed class JsonTypeVisitor : IFieldVisitor { + private const int MaxDepth = 5; private static readonly JsonTypeVisitor Instance = new JsonTypeVisitor(); public readonly struct Args @@ -25,11 +30,20 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema public readonly bool WithHiddenFields; - public Args(SchemaResolver? schemaResolver, bool withHiddenFields) + public readonly int Level; + + public Args(SchemaResolver? schemaResolver, bool withHiddenFields, int level) { SchemaResolver = schemaResolver; WithHiddenFields = withHiddenFields; + + Level = level; + } + + public Args Increment() + { + return new Args(SchemaResolver, WithHiddenFields, Level + 1); } } @@ -37,20 +51,27 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema { } - public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver? schemaResolver, bool withHiddenFields) + public static JsonSchemaProperty? BuildProperty(IField field, SchemaResolver? schemaResolver = null, bool withHiddenFields = false) { - var args = new Args(schemaResolver, withHiddenFields); + var args = new Args(schemaResolver, withHiddenFields, 0); return field.Accept(Instance, args); } public JsonSchemaProperty? Visit(IArrayField field, Args args) { + if (args.Level > MaxDepth) + { + return null; + } + var itemSchema = SchemaBuilder.Object(); + var nestedArgs = args.Increment(); + foreach (var nestedField in field.Fields.ForApi(args.WithHiddenFields)) { - var nestedProperty = nestedField.Accept(this, args); + var nestedProperty = nestedField.Accept(this, nestedArgs); if (nestedProperty != null) { @@ -74,48 +95,46 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema return SchemaBuilder.BooleanProperty(); } - public JsonSchemaProperty? Visit(IField field, Args args) + public JsonSchemaProperty? Visit(IField field, Args args) { - return SchemaBuilder.DateTimeProperty(); + if (args.Level > MaxDepth) + { + return null; + } + + var property = SchemaBuilder.ObjectProperty(); + + BuildComponent(property, field, field.Properties.SchemaIds, args); + + return property; } - public JsonSchemaProperty? Visit(IField field, Args args) + public JsonSchemaProperty? Visit(IField field, Args args) { - if (args.SchemaResolver != null) + if (args.Level > MaxDepth) { - var reference = args.SchemaResolver("GeolocationDto", () => - { - var geolocationSchema = SchemaBuilder.Object(); + return null; + } - geolocationSchema.Format = GeoJson.Format; + var itemSchema = SchemaBuilder.Object(); - geolocationSchema.Properties.Add("latitude", new JsonSchemaProperty - { - Type = JsonObjectType.Number, - Maximum = 90, - Minimum = -90 - }.SetRequired(false)); + BuildComponent(itemSchema, field, field.Properties.SchemaIds, args); - geolocationSchema.Properties.Add("longitude", new JsonSchemaProperty - { - Type = JsonObjectType.Number, - Maximum = 180, - Minimum = -180 - }.SetRequired(false)); + return SchemaBuilder.ArrayProperty(itemSchema); + } - return geolocationSchema; - }); + public JsonSchemaProperty? Visit(IField field, Args args) + { + return SchemaBuilder.DateTimeProperty(); + } - return SchemaBuilder.ObjectProperty(reference); - } - else - { - var property = SchemaBuilder.ObjectProperty(); + public JsonSchemaProperty? Visit(IField field, Args args) + { + var property = SchemaBuilder.ObjectProperty(); - property.Format = GeoJson.Format; + property.Format = GeoJson.Format; - return property; - } + return property; } public JsonSchemaProperty? Visit(IField field, Args args) @@ -176,5 +195,59 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema { return null; } + + private void BuildComponent(JsonSchema jsonSchema, IField field, ImmutableList? schemaIds, Args args) + { + jsonSchema.Properties.Add(Component.Discriminator, SchemaBuilder.StringProperty(isRequired: true)); + + if (args.SchemaResolver != null) + { + var schemas = schemaIds?.Select(x => field.GetResolvedSchema(x)).NotNull() ?? Enumerable.Empty(); + + var discriminator = new OpenApiDiscriminator + { + PropertyName = Component.Discriminator + }; + + foreach (var schema in schemas) + { + var schemaName = $"{schema.TypeName()}ComponentDto"; + + var componentSchema = args.SchemaResolver(schemaName, () => + { + var nestedArgs = args.Increment(); + + var componentSchema = SchemaBuilder.Object(); + + foreach (var sharedField in schema.Fields.ForApi(nestedArgs.WithHiddenFields)) + { + var sharedProperty = sharedField.Accept(this, nestedArgs); + + if (sharedProperty != null) + { + sharedProperty.Description = sharedField.RawProperties.Hints; + sharedProperty.SetRequired(sharedField.RawProperties.IsRequired); + + componentSchema.Properties.Add(sharedField.Name, sharedProperty); + } + } + + componentSchema.Properties.Add(Component.Discriminator, SchemaBuilder.StringProperty(isRequired: true)); + + return componentSchema; + }); + + jsonSchema.OneOf.Add(componentSchema); + + discriminator.Mapping[schemaName] = componentSchema; + } + + jsonSchema.DiscriminatorObject = discriminator; + } + else + { + jsonSchema.AllowAdditionalProperties = true; + } + } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptVars.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptVars.cs index 31cabc614..3801d79a8 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptVars.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ScriptVars.cs @@ -11,8 +11,6 @@ using System.Security.Claims; using Squidex.Domain.Apps.Core.Contents; using Squidex.Infrastructure; -#pragma warning disable CS0618 // Type or member is obsolete - namespace Squidex.Domain.Apps.Core.Scripting { public sealed class ScriptVars : ScriptContext @@ -71,6 +69,7 @@ namespace Squidex.Domain.Apps.Core.Scripting set => SetValue(value); } +#pragma warning disable CS0618 // Type or member is obsolete public ContentData? DataOld { get => GetValue(); @@ -90,6 +89,7 @@ namespace Squidex.Domain.Apps.Core.Scripting SetValue(value); } } +#pragma warning restore CS0618 // Type or member is obsolete [Obsolete("Use dataOld")] public ContentData? OldData diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs index bda2db8dc..a8495a821 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs @@ -36,9 +36,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { } - public static IEnumerable CreateValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator) + public static IEnumerable CreateValidators(ValidatorContext context, IField field, ValidatorFactory factory) { - var args = new Args(context, createFieldValidator); + var args = new Args(context, factory); return field.Accept(Instance, args); } @@ -81,6 +81,34 @@ namespace Squidex.Domain.Apps.Core.ValidateContent } } + public IEnumerable Visit(IField field, Args args) + { + var properties = field.Properties; + + var isRequired = IsRequired(properties, args.Context); + + if (isRequired) + { + yield return new RequiredValidator(); + } + + yield return ComponentValidator(args.Factory); + } + + public IEnumerable Visit(IField field, Args args) + { + var properties = field.Properties; + + var isRequired = IsRequired(properties, args.Context); + + if (isRequired || properties.MinItems != null || properties.MaxItems != null) + { + yield return new CollectionValidator(isRequired, properties.MinItems, properties.MaxItems); + } + + yield return new CollectionItemValidator(ComponentValidator(args.Factory)); + } + public IEnumerable Visit(IField field, Args args) { var properties = field.Properties; @@ -238,5 +266,20 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return isRequired; } + + private static IValidator ComponentValidator(ValidatorFactory factory) + { + return new ComponentValidator(schema => + { + var nestedValidators = new Dictionary(schema.Fields.Count); + + foreach (var nestedField in schema.Fields) + { + nestedValidators[nestedField.Name] = (false, factory(nestedField)); + } + + return new ObjectValidator(nestedValidators, false, "field"); + }); + } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultValidatorsFactory.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultValidatorsFactory.cs index b98abc98b..50ee2ecdd 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultValidatorsFactory.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultValidatorsFactory.cs @@ -13,7 +13,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { public sealed class DefaultValidatorsFactory : IValidatorsFactory { - public IEnumerable CreateFieldValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator) + public IEnumerable CreateFieldValidators(ValidatorContext context, IField field, ValidatorFactory factory) { if (field is IField) { @@ -21,9 +21,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent } } - public IEnumerable CreateValueValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator) + public IEnumerable CreateValueValidators(ValidatorContext context, IField field, ValidatorFactory factory) { - return DefaultFieldValueValidatorsFactory.CreateValidators(context, field, createFieldValidator); + return DefaultFieldValueValidatorsFactory.CreateValidators(context, field, factory); } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IValidatorsFactory.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IValidatorsFactory.cs index 7458902d4..9666ea7e0 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IValidatorsFactory.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IValidatorsFactory.cs @@ -14,17 +14,17 @@ namespace Squidex.Domain.Apps.Core.ValidateContent public interface IValidatorsFactory { - IEnumerable CreateFieldValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator) + IEnumerable CreateFieldValidators(ValidatorContext context, IField field, ValidatorFactory factory) { yield break; } - IEnumerable CreateValueValidators(ValidatorContext context, IField field, ValidatorFactory createFieldValidator) + IEnumerable CreateValueValidators(ValidatorContext context, IField field, ValidatorFactory factory) { yield break; } - IEnumerable CreateContentValidators(ValidatorContext context, ValidatorFactory createFieldValidator) + IEnumerable CreateContentValidators(ValidatorContext context, ValidatorFactory factory) { yield break; } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs index 0a3596564..2c9c6e0ec 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs @@ -1,4 +1,4 @@ -// ========================================================================== +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) @@ -57,6 +57,16 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return ConvertToIdList(args.Value); } + public (object? Result, JsonError? Error) Visit(IField field, Args args) + { + return ConvertToComponent(field, args.Value); + } + + public (object? Result, JsonError? Error) Visit(IField field, Args args) + { + return ConvertToComponentList(field, args.Value); + } + public (object? Result, JsonError? Error) Visit(IField field, Args args) { return ConvertToIdList(args.Value); @@ -147,22 +157,22 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { var result = new List(array.Count); - foreach (var item in array) + for (var i = 0; i < array.Count; i++) { - if (item is JsonString s && !string.IsNullOrWhiteSpace(s.Value)) + if (array[i] is JsonString s && !string.IsNullOrWhiteSpace(s.Value)) { result.Add(DomainId.Create(s.Value)); } else { - return (null, new JsonError("Invalid json type, expected array of strings.")); + return (null, new JsonError(T.Get("contents.invalidArrayOfStrings"))); } } return (result, null); } - return (null, new JsonError("Invalid json type, expected array of strings.")); + return (null, new JsonError(T.Get("contents.invalidArrayOfStrings"))); } private static (object? Result, JsonError? Error) ConvertToStringList(IJsonValue value) @@ -171,9 +181,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { var result = new List(array.Count); - foreach (var item in array) + for (var i = 0; i < array.Count; i++) { - if (item is JsonString s && !string.IsNullOrWhiteSpace(s.Value)) + if (array[i] is JsonString s && !string.IsNullOrWhiteSpace(s.Value)) { result.Add(s.Value); } @@ -189,15 +199,42 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return (null, new JsonError(T.Get("contents.invalidArrayOfStrings"))); } + private (object? Result, JsonError? Error) ConvertToComponentList(IField field, IJsonValue value) + { + if (value is JsonArray array) + { + var result = new List(array.Count); + + for (var i = 0; i < array.Count; i++) + { + var (item, error) = ConvertToComponent(field, array[i]); + + if (error != null) + { + return (null, error); + } + + if (item != null) + { + result.Add(item); + } + } + + return (result, null); + } + + return (null, new JsonError(T.Get("contents.invalidArrayOfObjects"))); + } + private static (object? Result, JsonError? Error) ConvertToObjectList(IJsonValue value) { if (value is JsonArray array) { var result = new List(array.Count); - foreach (var item in array) + for (var i = 0; i < array.Count; i++) { - if (item is JsonObject obj) + if (array[i] is JsonObject obj) { result.Add(obj); } @@ -212,5 +249,29 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return (null, new JsonError(T.Get("contents.invalidArrayOfObjects"))); } + + private static (object? Result, JsonError? Error) ConvertToComponent(IField field, IJsonValue value) + { + if (value is not JsonObject obj) + { + return (null, new JsonError(T.Get("contents.invalidComponentNoObject"))); + } + + if (!obj.TryGetValue(Component.Discriminator, out var type)) + { + return (null, new JsonError(T.Get("contents.invalidComponentNoType"))); + } + + if (!field.TryGetResolvedSchema(type, out var schema)) + { + return (null, new JsonError(T.Get("contents.invalidComponentUnknownSchema"))); + } + + var data = new JsonObject(obj); + + data.Remove(Component.Discriminator); + + return (new Component(type.Value, data, schema), null); + } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueValidator.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueValidator.cs index 3a3412750..e6f8820c3 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueValidator.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueValidator.cs @@ -55,34 +55,19 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return IsValidStringList(args.Value); } - public bool Visit(IField field, Args args) - { - return IsValidStringList(args.Value); - } - - public bool Visit(IField field, Args args) - { - return IsValidStringList(args.Value); - } - public bool Visit(IField field, Args args) { return args.Value is JsonBoolean; } - public bool Visit(IField field, Args args) - { - return args.Value is JsonNumber; - } - - public bool Visit(IField field, Args args) + public bool Visit(IField field, Args args) { - return args.Value is JsonString; + return IsValidComponent(args.Value); } - public bool Visit(IField field, Args args) + public bool Visit(IField field, Args args) { - return true; + return IsValidComponentList(args.Value); } public bool Visit(IField field, Args args) @@ -109,13 +94,38 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return true; } + public bool Visit(IField field, Args args) + { + return args.Value is JsonNumber; + } + + public bool Visit(IField field, Args args) + { + return IsValidStringList(args.Value); + } + + public bool Visit(IField field, Args args) + { + return args.Value is JsonString; + } + + public bool Visit(IField field, Args args) + { + return IsValidStringList(args.Value); + } + + public bool Visit(IField field, Args args) + { + return true; + } + private static bool IsValidStringList(IJsonValue value) { if (value is JsonArray array) { - foreach (var item in array) + for (var i = 0; i < array.Count; i++) { - if (item is not JsonString) + if (array[i] is not JsonString) { return false; } @@ -131,9 +141,27 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { if (value is JsonArray array) { - foreach (var item in array) + for (var i = 0; i < array.Count; i++) + { + if (array[i] is not JsonObject) + { + return false; + } + } + + return true; + } + + return false; + } + + private static bool IsValidComponentList(IJsonValue value) + { + if (value is JsonArray array) + { + for (var i = 0; i < array.Count; i++) { - if (item is not JsonObject) + if (!IsValidComponent(array[i])) { return false; } @@ -144,5 +172,20 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return false; } + + private static bool IsValidComponent(IJsonValue value) + { + if (value is not JsonObject obj) + { + return false; + } + + if (!obj.TryGetValue(Component.Discriminator, out var type)) + { + return false; + } + + return !string.IsNullOrWhiteSpace(type.Value); + } } } diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ComponentValidator.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ComponentValidator.cs new file mode 100644 index 000000000..ec5bec2cc --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ComponentValidator.cs @@ -0,0 +1,37 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Core.Schemas; + +namespace Squidex.Domain.Apps.Core.ValidateContent.Validators +{ + public sealed class ComponentValidator : IValidator + { + private readonly Func validatorFactory; + + public ComponentValidator(Func validatorFactory) + { + this.validatorFactory = validatorFactory; + } + + public async Task ValidateAsync(object? value, ValidationContext context, AddError addError) + { + if (value is Component component) + { + var validator = validatorFactory(component.Schema); + + if (validator != null) + { + await validator.ValidateAsync(component.Data, context, addError); + } + } + } + } +} diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs index 8250fc828..570f63634 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs @@ -1,4 +1,4 @@ -// ========================================================================== +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) @@ -22,6 +22,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators { this.fields = fields; this.fieldType = fieldType; + this.isPartial = isPartial; } diff --git a/backend/src/Squidex.Domain.Apps.Entities/AppProvider.cs b/backend/src/Squidex.Domain.Apps.Entities/AppProvider.cs index 05afab815..34243d69f 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/AppProvider.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/AppProvider.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Squidex.Caching; +using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.Indexes; using Squidex.Domain.Apps.Entities.Rules; @@ -16,6 +17,7 @@ using Squidex.Domain.Apps.Entities.Rules.Indexes; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas.Indexes; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Security; namespace Squidex.Domain.Apps.Entities @@ -112,6 +114,8 @@ namespace Squidex.Domain.Apps.Entities if (schema != null) { + await ResolveSchemaAsync(appId, schema.SchemaDef); + localCache.Add(cacheKey, schema); localCache.Add(SchemaCacheKey(appId, schema.Id), schema); } @@ -132,6 +136,8 @@ namespace Squidex.Domain.Apps.Entities if (schema != null) { + await ResolveSchemaAsync(appId, schema.SchemaDef); + localCache.Add(cacheKey, schema); localCache.Add(SchemaCacheKey(appId, schema.SchemaDef.Name), schema); } @@ -156,6 +162,17 @@ namespace Squidex.Domain.Apps.Entities return indexSchemas.GetSchemasAsync(appId); }); + foreach (var schema in schemas) + { + localCache.Add(SchemaCacheKey(appId, schema.Id), schema); + localCache.Add(SchemaCacheKey(appId, schema.SchemaDef.Name), schema); + } + + foreach (var schema in schemas) + { + await ResolveSchemaAsync(appId, schema.SchemaDef); + } + return schemas; } @@ -176,6 +193,59 @@ namespace Squidex.Domain.Apps.Entities return rules.Find(x => x.Id == id); } + private async Task ResolveSchemaAsync(DomainId appId, Schema schema) + { + async Task ResolveWithIdsAsync(IField field, ImmutableList? schemaIds) + { + if (schemaIds != null) + { + foreach (var schemaId in schemaIds) + { + if (!field.TryGetResolvedSchema(schemaId, out _)) + { + var resolvedEntity = await GetSchemaAsync(appId, schemaId, true); + + if (resolvedEntity != null) + { + field.SetResolvedSchema(schemaId, resolvedEntity.SchemaDef); + } + } + } + } + } + + async Task ResolveArrayAsync(IArrayField arrayField) + { + foreach (var nestedField in arrayField.Fields) + { + await ResolveAsync(nestedField); + } + } + + async Task ResolveAsync(IField field) + { + switch (field) + { + case IField component: + await ResolveWithIdsAsync(field, component.Properties.SchemaIds); + break; + + case IField components: + await ResolveWithIdsAsync(field, components.Properties.SchemaIds); + break; + + case IArrayField arrayField: + await ResolveArrayAsync(arrayField); + break; + } + } + + foreach (var field in schema.Fields) + { + await ResolveAsync(field); + } + } + private static string AppCacheKey(DomainId appId) { return $"APPS_ID_{appId}"; diff --git a/backend/src/Squidex.Domain.Apps.Entities/Apps/RolePermissionsProvider.cs b/backend/src/Squidex.Domain.Apps.Entities/Apps/RolePermissionsProvider.cs index 1c88cb548..d3a4863f7 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Apps/RolePermissionsProvider.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Apps/RolePermissionsProvider.cs @@ -40,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Apps if (value?.StartsWith(Permissions.App, StringComparison.OrdinalIgnoreCase) == true) { - if (value.IndexOf("{name}", Permissions.App.Length, StringComparison.OrdinalIgnoreCase) >= 0) + if (value.IndexOf("{schema}", Permissions.App.Length, StringComparison.OrdinalIgnoreCase) >= 0) { forAppSchemas.Add(value); } @@ -78,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Apps foreach (var schema in schemaNames) { - var replaced = trimmed.Replace("{name}", schema); + var replaced = trimmed.Replace("{schema}", schema); result.Add(replaced); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs index df72ac17e..e4fa44528 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs @@ -96,7 +96,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject await CreateCore(c, operation); - if (operation.Schema.SchemaDef.IsSingleton()) + if (operation.Schema.SchemaDef.Type == SchemaType.Singleton) { ChangeStatus(c.AsChange(Status.Published)); } @@ -223,6 +223,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject private async Task CreateCore(CreateContent c, OperationContext operation) { operation.MustNotCreateSingleton(); + operation.MustNotCreateForUnpublishedSchema(); operation.MustHaveData(c.Data); if (!c.DoNotValidate) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs index c12803834..509f58566 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs @@ -14,9 +14,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards { public static class SingletonExtensions { + public static void MustNotCreateForUnpublishedSchema(this OperationContext context) + { + if (!context.SchemaDef.IsPublished && context.SchemaDef.Type != SchemaType.Singleton) + { + throw new DomainException(T.Get("contents.schemaNotPublished")); + } + } + public static void MustNotCreateSingleton(this OperationContext context) { - if (context.SchemaDef.IsSingleton() && context.ContentId != context.Schema.Id) + if (context.SchemaDef.Type == SchemaType.Singleton && context.ContentId != context.Schema.Id) { throw new DomainException(T.Get("contents.singletonNotCreatable")); } @@ -24,7 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards public static void MustNotChangeSingleton(this OperationContext context, Status status) { - if (context.SchemaDef.IsSingleton() && (context.Content.NewStatus == null || status != Status.Published)) + if (context.SchemaDef.Type == SchemaType.Singleton && (context.Content.NewStatus == null || status != Status.Published)) { throw new DomainException(T.Get("contents.singletonNotChangeable")); } @@ -32,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards public static void MustNotDeleteSingleton(this OperationContext context) { - if (context.SchemaDef.IsSingleton()) + if (context.SchemaDef.Type == SchemaType.Singleton) { throw new DomainException(T.Get("contents.singletonNotDeletable")); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/WorkflowExtensions.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/WorkflowExtensions.cs index fa601f256..bb66781d7 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/WorkflowExtensions.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/WorkflowExtensions.cs @@ -24,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards public static async Task CheckTransitionAsync(this OperationContext context, Status status) { - if (!context.SchemaDef.IsSingleton()) + if (context.SchemaDef.Type != SchemaType.Singleton) { var workflow = GetWorkflow(context); @@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards public static async Task CheckStatusAsync(this OperationContext context, Status status) { - if (!context.SchemaDef.IsSingleton()) + if (context.SchemaDef.Type != SchemaType.Singleton) { var workflow = GetWorkflow(context); diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs index 97d1d7c93..91c542449 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs @@ -44,6 +44,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents return AllTypes.Boolean; } + public IGraphType? Visit(IField field, FieldInfo args) + { + return AllTypes.Json; + } + + public IGraphType? Visit(IField field, FieldInfo args) + { + return AllTypes.Json; + } + public IGraphType? Visit(IField field, FieldInfo args) { return AllTypes.DateTime; diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs index 982ed2c9e..47d0085e5 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs @@ -120,6 +120,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents return (AllTypes.Boolean, JsonBoolean, null); } + public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) + { + return (AllTypes.Json, JsonPath, ContentActions.Json.Arguments); + } + + public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) + { + return (AllTypes.Json, JsonPath, ContentActions.Json.Arguments); + } + public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) { return (AllTypes.DateTime, JsonDateTime, null); diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs index 461adbacd..ef326d39a 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs @@ -57,7 +57,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { var names = new Names(); - foreach (var schema in schemas.Where(x => x.SchemaDef.IsPublished && x.SchemaDef.Fields.Count > 0).OrderBy(x => x.Created)) + var validSchemas = schemas.Where(x => + x.SchemaDef.IsPublished && + x.SchemaDef.Type != SchemaType.Component && + x.SchemaDef.Fields.Count > 0); + + foreach (var schema in validSchemas.OrderBy(x => x.Created)) { var typeName = schema.TypeName(); @@ -191,4 +196,4 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents return $"{name}{offset + 1}"; } } -} \ No newline at end of file +} diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs index f91c07638..20ca246c0 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs @@ -1,4 +1,4 @@ -// ========================================================================== +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) @@ -206,7 +206,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries { var schemas = await appProvider.GetSchemasAsync(context.App.Id); - return schemas.Where(x => HasPermission(context, x, Permissions.AppContentsReadOwn)).ToList(); + return schemas.Where(x => IsAccessible(x) && HasPermission(context, x, Permissions.AppContentsReadOwn)).ToList(); + } + + private static bool IsAccessible(ISchemaEntity schema) + { + return schema.SchemaDef.IsPublished; } private static bool HasPermission(Context context, ISchemaEntity schema, string permissionId) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs index ef8593684..512d11ae9 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs @@ -43,10 +43,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps this.contentRepository = contentRepository; excludedChangedField = FieldConverters.ExcludeChangedTypes(jsonSerializer); - excludedChangedValue = FieldConverters.ForValues(ValueConverters.ForNested(ValueConverters.ExcludeChangedTypes(jsonSerializer))); + excludedChangedValue = FieldConverters.ForValues(ValueConverters.ExcludeChangedTypes(jsonSerializer)); excludedHiddenField = FieldConverters.ExcludeHidden; - excludedHiddenValue = FieldConverters.ForValues(ValueConverters.ForNested(ValueConverters.ExcludeHidden)); + excludedHiddenValue = FieldConverters.ForValues(ValueConverters.ExcludeHidden); } public async Task EnrichAsync(Context context, IEnumerable contents, ProvideSchema schemas) @@ -125,7 +125,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps if (cleanReferences != null) { yield return FieldConverters.ForValues(cleanReferences); - yield return FieldConverters.ForValues(ValueConverters.ForNested(cleanReferences)); } yield return FieldConverters.ResolveInvariant(context.App.Languages); @@ -154,7 +153,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps var resolveAssetUrls = ValueConverters.ResolveAssetUrls(appId, assetUrls, urlGenerator); yield return FieldConverters.ForValues(resolveAssetUrls); - yield return FieldConverters.ForValues(ValueConverters.ForNested(resolveAssetUrls)); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithSchema.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithSchema.cs index 7a39c9690..120b41980 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithSchema.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithSchema.cs @@ -25,7 +25,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps foreach (var content in group) { - content.IsSingleton = schema.SchemaDef.IsSingleton(); + content.IsSingleton = schema.SchemaDef.Type == SchemaType.Singleton; content.SchemaName = schemaName; content.SchemaDisplayName = schemaDisplayName; diff --git a/backend/src/Squidex.Domain.Apps.Entities/Schemas/DomainObject/Guards/FieldPropertiesValidator.cs b/backend/src/Squidex.Domain.Apps.Entities/Schemas/DomainObject/Guards/FieldPropertiesValidator.cs index f029db8b3..271655de9 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Schemas/DomainObject/Guards/FieldPropertiesValidator.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Schemas/DomainObject/Guards/FieldPropertiesValidator.cs @@ -1,4 +1,4 @@ -// ========================================================================== +// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) @@ -91,6 +91,21 @@ namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards } } + public IEnumerable Visit(ComponentFieldProperties properties, None args) + { + yield break; + } + + public IEnumerable Visit(ComponentsFieldProperties properties, None args) + { + if (IsMaxGreaterThanMin(properties.MaxItems, properties.MinItems)) + { + yield return new ValidationError(Not.GreaterEqualsThan(nameof(properties.MaxItems), nameof(properties.MinItems)), + nameof(properties.MinItems), + nameof(properties.MaxItems)); + } + } + public IEnumerable Visit(DateTimeFieldProperties properties, None args) { if (!properties.Editor.IsEnumValue()) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs b/backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs index 68fff4e43..1329d98b1 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs @@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas { AddSchemaUrl(result, appId, schemaId, name); - if (HasPermission(context, schemaId)) + if (schema.SchemaDef.Type != SchemaType.Component && HasPermission(context, schemaId)) { AddContentsUrl(result, appId, schema, schemaId, name); } @@ -71,7 +71,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas private void AddContentsUrl(SearchResults result, NamedId appId, ISchemaEntity schema, NamedId schemaId, string name) { - if (schema.SchemaDef.IsSingleton()) + if (schema.SchemaDef.Type == SchemaType.Singleton) { var contentUrl = urlGenerator.ContentUI(appId, schemaId, schemaId.Id); diff --git a/backend/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs b/backend/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs index 82e9ac36e..2250f3886 100644 --- a/backend/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs +++ b/backend/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs @@ -9,7 +9,6 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -using Squidex.Infrastructure.Collections; namespace Squidex.Infrastructure.Json.Newtonsoft { diff --git a/backend/src/Squidex.Shared/Permissions.cs b/backend/src/Squidex.Shared/Permissions.cs index b9f1abf74..2085f0528 100644 --- a/backend/src/Squidex.Shared/Permissions.cs +++ b/backend/src/Squidex.Shared/Permissions.cs @@ -138,33 +138,33 @@ namespace Squidex.Shared public const string AppSchemas = "squidex.apps.{app}.schemas"; public const string AppSchemasRead = "squidex.apps.{app}.schemas.read"; public const string AppSchemasCreate = "squidex.apps.{app}.schemas.create"; - public const string AppSchemasUpdate = "squidex.apps.{app}.schemas.{name}.update"; - public const string AppSchemasScripts = "squidex.apps.{app}.schemas.{name}.scripts"; - public const string AppSchemasPublish = "squidex.apps.{app}.schemas.{name}.publish"; - public const string AppSchemasDelete = "squidex.apps.{app}.schemas.{name}.delete"; + public const string AppSchemasUpdate = "squidex.apps.{app}.schemas.{schema}.update"; + public const string AppSchemasScripts = "squidex.apps.{app}.schemas.{schema}.scripts"; + public const string AppSchemasPublish = "squidex.apps.{app}.schemas.{schema}.publish"; + public const string AppSchemasDelete = "squidex.apps.{app}.schemas.{schema}.delete"; // Contents - public const string AppContents = "squidex.apps.{app}.contents.{name}"; - public const string AppContentsRead = "squidex.apps.{app}.contents.{name}.read"; - public const string AppContentsReadOwn = "squidex.apps.{app}.contents.{name}.read.own"; - public const string AppContentsCreate = "squidex.apps.{app}.contents.{name}.create"; - public const string AppContentsUpdate = "squidex.apps.{app}.contents.{name}.update"; - public const string AppContentsUpdateOwn = "squidex.apps.{app}.contents.{name}.update.own"; - public const string AppContentsChangeStatus = "squidex.apps.{app}.contents.{name}.changestatus"; - public const string AppContentsChangeStatusOwn = "squidex.apps.{app}.contents.{name}.changestatus.own"; - public const string AppContentsUpsert = "squidex.apps.{app}.contents.{name}.upsert"; - public const string AppContentsVersionCreate = "squidex.apps.{app}.contents.{name}.version.create"; - public const string AppContentsVersionCreateOwn = "squidex.apps.{app}.contents.{name}.version.create.own"; - public const string AppContentsVersionDelete = "squidex.apps.{app}.contents.{name}.version.delete"; - public const string AppContentsVersionDeleteOwn = "squidex.apps.{app}.contents.{name}.version.delete.own"; - public const string AppContentsDelete = "squidex.apps.{app}.contents.{name}.delete"; - public const string AppContentsDeleteOwn = "squidex.apps.{app}.contents.{name}.delete.own"; + public const string AppContents = "squidex.apps.{app}.contents.{schema}"; + public const string AppContentsRead = "squidex.apps.{app}.contents.{schema}.read"; + public const string AppContentsReadOwn = "squidex.apps.{app}.contents.{schema}.read.own"; + public const string AppContentsCreate = "squidex.apps.{app}.contents.{schema}.create"; + public const string AppContentsUpdate = "squidex.apps.{app}.contents.{schema}.update"; + public const string AppContentsUpdateOwn = "squidex.apps.{app}.contents.{schema}.update.own"; + public const string AppContentsChangeStatus = "squidex.apps.{app}.contents.{schema}.changestatus"; + public const string AppContentsChangeStatusOwn = "squidex.apps.{app}.contents.{schema}.changestatus.own"; + public const string AppContentsUpsert = "squidex.apps.{app}.contents.{schema}.upsert"; + public const string AppContentsVersionCreate = "squidex.apps.{app}.contents.{schema}.version.create"; + public const string AppContentsVersionCreateOwn = "squidex.apps.{app}.contents.{schema}.version.create.own"; + public const string AppContentsVersionDelete = "squidex.apps.{app}.contents.{schema}.version.delete"; + public const string AppContentsVersionDeleteOwn = "squidex.apps.{app}.contents.{schema}.version.delete.own"; + public const string AppContentsDelete = "squidex.apps.{app}.contents.{schema}.delete"; + public const string AppContentsDeleteOwn = "squidex.apps.{app}.contents.{schema}.delete.own"; public static Permission ForApp(string id, string app = Permission.Any, string schema = Permission.Any) { Guard.NotNull(id, nameof(id)); - return new Permission(id.Replace("{app}", app ?? Permission.Any).Replace("{name}", schema ?? Permission.Any)); + return new Permission(id.Replace("{app}", app ?? Permission.Any).Replace("{schema}", schema ?? Permission.Any)); } } } diff --git a/backend/src/Squidex.Shared/Texts.it.resx b/backend/src/Squidex.Shared/Texts.it.resx index befa49727..3885558d9 100644 --- a/backend/src/Squidex.Shared/Texts.it.resx +++ b/backend/src/Squidex.Shared/Texts.it.resx @@ -460,6 +460,15 @@ Errore nel json, atteso un boolean. + + Invalid json object, expected object with 'schemaId' field. + + + Invalid component. No 'schemaId' field found. + + + Invalid component. Cannot find schema. + Errore nel json, atteso un object latitudine/longitudine. @@ -481,6 +490,9 @@ Il contenuto è collegato ad un altro contenuto e pertanto non può essere cancellato. + + Schema not published. + Il contenuto singleton non può essere aggiornato diff --git a/backend/src/Squidex.Shared/Texts.nl.resx b/backend/src/Squidex.Shared/Texts.nl.resx index 020ab2f1f..54b13e787 100644 --- a/backend/src/Squidex.Shared/Texts.nl.resx +++ b/backend/src/Squidex.Shared/Texts.nl.resx @@ -460,6 +460,15 @@ Ongeldig json-type, verwachte boolean. + + Invalid json object, expected object with 'schemaId' field. + + + Invalid component. No 'schemaId' field found. + + + Invalid component. Cannot find schema. + Ongeldig json-type, verwacht object voor lengte- / breedtegraad. @@ -481,6 +490,9 @@ Er wordt naar de inhoud verwezen door een andere item en kan niet worden verwijderd. + + Schema not published. + Singleton-inhoud kan niet worden bijgewerkt. diff --git a/backend/src/Squidex.Shared/Texts.resx b/backend/src/Squidex.Shared/Texts.resx index fe2053103..e74810c50 100644 --- a/backend/src/Squidex.Shared/Texts.resx +++ b/backend/src/Squidex.Shared/Texts.resx @@ -460,6 +460,15 @@ Invalid json type, expected boolean. + + Invalid json object, expected object with 'schemaId' field. + + + Invalid component. No 'schemaId' field found. + + + Invalid component. Cannot find schema. + Invalid json type, expected latitude/longitude object. @@ -481,6 +490,9 @@ Content is referenced by another content and cannot be deleted or unpublished. + + Schema not published. + Singleton content cannot be updated. diff --git a/backend/src/Squidex.Web/ApiController.cs b/backend/src/Squidex.Web/ApiController.cs index fb71cc02f..d8734329b 100644 --- a/backend/src/Squidex.Web/ApiController.cs +++ b/backend/src/Squidex.Web/ApiController.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; @@ -29,7 +30,7 @@ namespace Squidex.Web { get { - var app = HttpContext.Context().App; + var app = HttpContext.Features.Get()?.App; if (app == null) { @@ -40,6 +41,21 @@ namespace Squidex.Web } } + protected ISchemaEntity Schema + { + get + { + var schema = HttpContext.Features.Get()?.Schema; + + if (schema == null) + { + throw new InvalidOperationException("Not in a schema context."); + } + + return schema; + } + } + protected Resources Resources { get => resources.Value; diff --git a/backend/src/Squidex.Web/ApiPermissionAttribute.cs b/backend/src/Squidex.Web/ApiPermissionAttribute.cs index aabbaa28d..71392b2b1 100644 --- a/backend/src/Squidex.Web/ApiPermissionAttribute.cs +++ b/backend/src/Squidex.Web/ApiPermissionAttribute.cs @@ -43,14 +43,14 @@ namespace Squidex.Web { foreach (var id in permissionIds) { - var app = context.HttpContext.Features.Get()?.AppId.Name; + var app = context.HttpContext.Features.Get()?.App.Name; if (string.IsNullOrWhiteSpace(app)) { app = Permission.Any; } - var schema = context.HttpContext.Features.Get()?.SchemaId.Name; + var schema = context.HttpContext.Features.Get()?.Schema.SchemaDef.Name; if (string.IsNullOrWhiteSpace(schema)) { diff --git a/backend/src/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs b/backend/src/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs index b8b136421..e8bcbaf51 100644 --- a/backend/src/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs +++ b/backend/src/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs @@ -9,6 +9,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Squidex.Domain.Apps.Entities; +using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; @@ -51,7 +52,7 @@ namespace Squidex.Web.CommandMiddlewares throw new InvalidOperationException("Cannot resolve schema."); } - return feature.SchemaId; + return feature.Schema.NamedId(); } } -} \ No newline at end of file +} diff --git a/backend/src/Squidex.Web/IAppFeature.cs b/backend/src/Squidex.Web/IAppFeature.cs index f565fdcf4..77563cf70 100644 --- a/backend/src/Squidex.Web/IAppFeature.cs +++ b/backend/src/Squidex.Web/IAppFeature.cs @@ -5,12 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Infrastructure; +using Squidex.Domain.Apps.Entities.Apps; namespace Squidex.Web { public interface IAppFeature { - NamedId AppId { get; } + IAppEntity App { get; } } } diff --git a/backend/src/Squidex.Web/ISchemaFeature.cs b/backend/src/Squidex.Web/ISchemaFeature.cs index 7bac96660..d3a539e90 100644 --- a/backend/src/Squidex.Web/ISchemaFeature.cs +++ b/backend/src/Squidex.Web/ISchemaFeature.cs @@ -5,12 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Infrastructure; +using Squidex.Domain.Apps.Entities.Schemas; namespace Squidex.Web { public interface ISchemaFeature { - NamedId SchemaId { get; } + ISchemaEntity Schema { get; } } } diff --git a/backend/src/Squidex.Web/Pipeline/AppFeature.cs b/backend/src/Squidex.Web/Pipeline/AppFeature.cs index 9e6b380b5..fe3add818 100644 --- a/backend/src/Squidex.Web/Pipeline/AppFeature.cs +++ b/backend/src/Squidex.Web/Pipeline/AppFeature.cs @@ -5,17 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Infrastructure; +using Squidex.Domain.Apps.Entities.Apps; + +#pragma warning disable SA1313 // Parameter names should begin with lower-case letter namespace Squidex.Web.Pipeline { - public sealed class AppFeature : IAppFeature - { - public NamedId AppId { get; } - - public AppFeature(NamedId appId) - { - AppId = appId; - } - } + public sealed record AppFeature(IAppEntity App) : IAppFeature; } diff --git a/backend/src/Squidex.Web/Pipeline/AppResolver.cs b/backend/src/Squidex.Web/Pipeline/AppResolver.cs index 4d8ff845e..5b2650449 100644 --- a/backend/src/Squidex.Web/Pipeline/AppResolver.cs +++ b/backend/src/Squidex.Web/Pipeline/AppResolver.cs @@ -110,7 +110,7 @@ namespace Squidex.Web.Pipeline return; } - context.HttpContext.Features.Set(new AppFeature(app.NamedId())); + context.HttpContext.Features.Set(new AppFeature(app)); context.HttpContext.Response.Headers.Add("X-AppId", app.Id.ToString()); } else diff --git a/backend/src/Squidex.Web/Pipeline/SchemaFeature.cs b/backend/src/Squidex.Web/Pipeline/SchemaFeature.cs index 116a1489a..c3dbd79ce 100644 --- a/backend/src/Squidex.Web/Pipeline/SchemaFeature.cs +++ b/backend/src/Squidex.Web/Pipeline/SchemaFeature.cs @@ -5,17 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Infrastructure; +using Squidex.Domain.Apps.Entities.Schemas; + +#pragma warning disable SA1313 // Parameter names should begin with lower-case letter namespace Squidex.Web.Pipeline { - public sealed class SchemaFeature : ISchemaFeature - { - public NamedId SchemaId { get; } - - public SchemaFeature(NamedId schemaId) - { - SchemaId = schemaId; - } - } + public sealed record SchemaFeature(ISchemaEntity Schema) : ISchemaFeature; } diff --git a/backend/src/Squidex.Web/Pipeline/SchemaResolver.cs b/backend/src/Squidex.Web/Pipeline/SchemaResolver.cs index 3fcaddba5..7af6a4c51 100644 --- a/backend/src/Squidex.Web/Pipeline/SchemaResolver.cs +++ b/backend/src/Squidex.Web/Pipeline/SchemaResolver.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -31,11 +32,11 @@ namespace Squidex.Web.Pipeline public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { - var appId = context.HttpContext.Features.Get()?.AppId.Id ?? default; + var appId = context.HttpContext.Features.Get()?.App.Id ?? default; if (appId != default) { - var schemaIdOrName = context.RouteData.Values["name"]?.ToString(); + var schemaIdOrName = context.RouteData.Values["schema"]?.ToString(); if (!string.IsNullOrWhiteSpace(schemaIdOrName)) { @@ -47,7 +48,13 @@ namespace Squidex.Web.Pipeline return; } - context.HttpContext.Features.Set(new SchemaFeature(schema.NamedId())); + if (context.ActionDescriptor.EndpointMetadata.Any(x => x is SchemaMustBePublishedAttribute) && !schema.SchemaDef.IsPublished) + { + context.Result = new NotFoundResult(); + return; + } + + context.HttpContext.Features.Set(new SchemaFeature(schema)); } } diff --git a/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs b/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs index 4df691188..bb391da73 100644 --- a/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs +++ b/backend/src/Squidex.Web/Pipeline/UsageMiddleware.cs @@ -48,7 +48,7 @@ namespace Squidex.Web.Pipeline { if (context.Response.StatusCode != StatusCodes.Status429TooManyRequests) { - var appId = context.Features.Get()?.AppId; + var appId = context.Features.Get()?.App.Id; if (appId != null) { @@ -72,13 +72,13 @@ namespace Squidex.Web.Pipeline request.UserClientId = clientId; request.UserId = context.User.OpenIdSubject(); - await usageLog.LogAsync(appId.Id, request); + await usageLog.LogAsync(appId.Value, request); if (request.Costs > 0) { var date = request.Timestamp.ToDateTimeUtc().Date; - await usageTracker.TrackAsync(date, appId.Id.ToString(), + await usageTracker.TrackAsync(date, appId.Value.ToString(), request.UserClientId, request.Costs, request.ElapsedMs, @@ -100,4 +100,4 @@ namespace Squidex.Web.Pipeline return usageBody; } } -} \ No newline at end of file +} diff --git a/backend/src/Squidex.Web/Resources.cs b/backend/src/Squidex.Web/Resources.cs index 9e06d61f6..ffef8a186 100644 --- a/backend/src/Squidex.Web/Resources.cs +++ b/backend/src/Squidex.Web/Resources.cs @@ -213,7 +213,7 @@ namespace Squidex.Web if (schema == Permission.Any) { - var falback = Controller.HttpContext.Features.Get()?.SchemaId.Name; + var falback = Controller.HttpContext.Features.Get()?.Schema.SchemaDef.Name; if (!string.IsNullOrWhiteSpace(falback)) { diff --git a/backend/src/Squidex.Web/SchemaMustBePublishedAttribute.cs b/backend/src/Squidex.Web/SchemaMustBePublishedAttribute.cs new file mode 100644 index 000000000..3216f7b30 --- /dev/null +++ b/backend/src/Squidex.Web/SchemaMustBePublishedAttribute.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; + +namespace Squidex.Web +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public sealed class SchemaMustBePublishedAttribute : Attribute + { + } +} diff --git a/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs b/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs index e27224d28..c9409e7ae 100644 --- a/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs +++ b/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs @@ -120,6 +120,8 @@ namespace Squidex.Areas.Api.Config.OpenApi CreateObjectMap() }; + settings.SchemaType = SchemaType.OpenApi3; + settings.FlattenInheritanceHierarchy = flatten; } diff --git a/backend/src/Squidex/Areas/Api/Config/OpenApi/QueryExtensions.cs b/backend/src/Squidex/Areas/Api/Config/OpenApi/QueryExtensions.cs index ebe834cd3..ff93d1ff1 100644 --- a/backend/src/Squidex/Areas/Api/Config/OpenApi/QueryExtensions.cs +++ b/backend/src/Squidex/Areas/Api/Config/OpenApi/QueryExtensions.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Linq; using NJsonSchema; using NSwag; @@ -26,6 +27,11 @@ namespace Squidex.Areas.Api.Config.OpenApi void AddQuery(OpenApiParameter parameter) { + if (operation.Parameters.Any(x => x.Name == parameter.Name && x.Kind == OpenApiParameterKind.Query)) + { + return; + } + parameter.Kind = OpenApiParameterKind.Query; operation.Parameters.Add(parameter); @@ -84,4 +90,4 @@ namespace Squidex.Areas.Api.Config.OpenApi }); } } -} \ No newline at end of file +} diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs index 386e9d47b..334948465 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs @@ -23,6 +23,7 @@ using Squidex.Web.GraphQL; namespace Squidex.Areas.Api.Controllers.Contents { + [SchemaMustBePublishedAttribute] public sealed class ContentsController : ApiController { private readonly IContentQueryService contentQuery; @@ -125,7 +126,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Queries contents. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The optional ids of the content to fetch. /// The optional json query. /// @@ -136,19 +137,17 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpGet] - [Route("content/{app}/{name}/")] + [Route("content/{app}/{schema}/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous] [ApiCosts(1)] - public async Task GetContents(string app, string name, [FromQuery] string? ids = null, [FromQuery] string? q = null) + public async Task GetContents(string app, string schema, [FromQuery] string? ids = null, [FromQuery] string? q = null) { - var schema = await contentQuery.GetSchemaOrThrowAsync(Context, name); - - var contents = await contentQuery.QueryAsync(Context, name, CreateQuery(ids, q)); + var contents = await contentQuery.QueryAsync(Context, schema, CreateQuery(ids, q)); var response = Deferred.AsyncResponse(() => { - return ContentsDto.FromContentsAsync(contents, Resources, schema, contentWorkflow); + return ContentsDto.FromContentsAsync(contents, Resources, Schema, contentWorkflow); }); return Ok(response); @@ -158,7 +157,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Queries contents. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The required query object. /// /// 200 => Contents returned. @@ -168,19 +167,17 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPost] - [Route("content/{app}/{name}/query")] + [Route("content/{app}/{schema}/query")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous] [ApiCosts(1)] - public async Task GetContentsPost(string app, string name, [FromBody] QueryDto query) + public async Task GetContentsPost(string app, string schema, [FromBody] QueryDto query) { - var schema = await contentQuery.GetSchemaOrThrowAsync(Context, name); - - var contents = await contentQuery.QueryAsync(Context, name, query?.ToQuery() ?? Q.Empty); + var contents = await contentQuery.QueryAsync(Context, schema, query?.ToQuery() ?? Q.Empty); var response = Deferred.AsyncResponse(() => { - return ContentsDto.FromContentsAsync(contents, Resources, schema, contentWorkflow); + return ContentsDto.FromContentsAsync(contents, Resources, Schema, contentWorkflow); }); return Ok(response); @@ -190,7 +187,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Get a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content to fetch. /// /// 200 => Content returned. @@ -200,13 +197,13 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpGet] - [Route("content/{app}/{name}/{id}/")] + [Route("content/{app}/{schema}/{id}/")] [ProducesResponseType(typeof(ContentDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous] [ApiCosts(1)] - public async Task GetContent(string app, string name, DomainId id) + public async Task GetContent(string app, string schema, DomainId id) { - var content = await contentQuery.FindAsync(Context, name, id); + var content = await contentQuery.FindAsync(Context, schema, id); if (content == null) { @@ -222,7 +219,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Get a content item validity. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content to fetch. /// /// 204 => Content is valid. @@ -233,10 +230,10 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpGet] - [Route("content/{app}/{name}/{id}/validity")] + [Route("content/{app}/{schema}/{id}/validity")] [ApiPermissionOrAnonymous] [ApiCosts(1)] - public async Task GetContentValidity(string app, string name, DomainId id) + public async Task GetContentValidity(string app, string schema, DomainId id) { var command = new ValidateContent { ContentId = id }; @@ -249,7 +246,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Get all references of a content. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content to fetch. /// The optional json query. /// @@ -260,11 +257,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpGet] - [Route("content/{app}/{name}/{id}/references")] + [Route("content/{app}/{schema}/{id}/references")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous] [ApiCosts(1)] - public async Task GetReferences(string app, string name, DomainId id, [FromQuery] string? q = null) + public async Task GetReferences(string app, string schema, DomainId id, [FromQuery] string? q = null) { var contents = await contentQuery.QueryAsync(Context, CreateQuery(null, q).WithReferencing(id)); @@ -280,7 +277,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Get a referencing contents of a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content to fetch. /// The optional json query. /// @@ -291,11 +288,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpGet] - [Route("content/{app}/{name}/{id}/referencing")] + [Route("content/{app}/{schema}/{id}/referencing")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous] [ApiCosts(1)] - public async Task GetReferencing(string app, string name, DomainId id, [FromQuery] string? q = null) + public async Task GetReferencing(string app, string schema, DomainId id, [FromQuery] string? q = null) { var contents = await contentQuery.QueryAsync(Context, CreateQuery(null, q).WithReference(id)); @@ -311,7 +308,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Get a content by version. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content to fetch. /// The version fo the content to fetch. /// @@ -322,12 +319,12 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpGet] - [Route("content/{app}/{name}/{id}/{version}/")] + [Route("content/{app}/{schema}/{id}/{version}/")] [ApiPermissionOrAnonymous(Permissions.AppContentsReadOwn)] [ApiCosts(1)] - public async Task GetContentVersion(string app, string name, DomainId id, int version) + public async Task GetContentVersion(string app, string schema, DomainId id, int version) { - var content = await contentQuery.FindAsync(Context, name, id, version); + var content = await contentQuery.FindAsync(Context, schema, id, version); if (content == null) { @@ -343,7 +340,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Create a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The request parameters. /// /// 201 => Content created. @@ -354,24 +351,24 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPost] - [Route("content/{app}/{name}/")] + [Route("content/{app}/{schema}/")] [ProducesResponseType(typeof(ContentsDto), 201)] [ApiPermissionOrAnonymous(Permissions.AppContentsCreate)] [ApiCosts(1)] - public async Task PostContent(string app, string name, CreateContentDto request) + public async Task PostContent(string app, string schema, CreateContentDto request) { var command = request.ToCommand(); var response = await InvokeCommandAsync(command); - return CreatedAtAction(nameof(GetContent), new { app, name, id = command.ContentId }, response); + return CreatedAtAction(nameof(GetContent), new { app, schema, id = command.ContentId }, response); } /// /// Import content items. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The import request. /// /// 200 => Contents created. @@ -382,12 +379,12 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPost] - [Route("content/{app}/{name}/import")] + [Route("content/{app}/{schema}/import")] [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsCreate)] [ApiCosts(5)] [Obsolete("Use bulk endpoint now.")] - public async Task PostContents(string app, string name, [FromBody] ImportContentsDto request) + public async Task PostContents(string app, string schema, [FromBody] ImportContentsDto request) { var command = request.ToCommand(); @@ -403,7 +400,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Bulk update content items. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The bulk update request. /// /// 201 => Contents created, update or delete. @@ -414,11 +411,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPost] - [Route("content/{app}/{name}/bulk")] + [Route("content/{app}/{schema}/bulk")] [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsReadOwn)] [ApiCosts(5)] - public async Task BulkUpdateContents(string app, string name, [FromBody] BulkUpdateContentsDto request) + public async Task BulkUpdateContents(string app, string schema, [FromBody] BulkUpdateContentsDto request) { var command = request.ToCommand(); @@ -434,7 +431,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Upsert a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to update. /// The request parameters. /// @@ -446,11 +443,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPost] - [Route("content/{app}/{name}/{id}/")] + [Route("content/{app}/{schema}/{id}/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsUpsert)] [ApiCosts(1)] - public async Task PostUpsertContent(string app, string name, DomainId id, UpsertContentDto request) + public async Task PostUpsertContent(string app, string schema, DomainId id, UpsertContentDto request) { var command = request.ToCommand(id); @@ -463,7 +460,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Update a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to update. /// The full data for the content item. /// @@ -475,11 +472,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPut] - [Route("content/{app}/{name}/{id}/")] + [Route("content/{app}/{schema}/{id}/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsUpdateOwn)] [ApiCosts(1)] - public async Task PutContent(string app, string name, DomainId id, [FromBody] ContentData request) + public async Task PutContent(string app, string schema, DomainId id, [FromBody] ContentData request) { var command = new UpdateContent { ContentId = id, Data = request }; @@ -492,7 +489,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Patchs a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to patch. /// The patch for the content item. /// @@ -504,11 +501,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPatch] - [Route("content/{app}/{name}/{id}/")] + [Route("content/{app}/{schema}/{id}/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsUpdateOwn)] [ApiCosts(1)] - public async Task PatchContent(string app, string name, DomainId id, [FromBody] ContentData request) + public async Task PatchContent(string app, string schema, DomainId id, [FromBody] ContentData request) { var command = new PatchContent { ContentId = id, Data = request }; @@ -521,7 +518,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Change status of a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to change. /// The status request. /// @@ -533,11 +530,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPut] - [Route("content/{app}/{name}/{id}/status/")] + [Route("content/{app}/{schema}/{id}/status/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsChangeStatusOwn)] [ApiCosts(1)] - public async Task PutContentStatus(string app, string name, DomainId id, [FromBody] ChangeStatusDto request) + public async Task PutContentStatus(string app, string schema, DomainId id, [FromBody] ChangeStatusDto request) { var command = request.ToCommand(id); @@ -550,7 +547,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Create a new draft version. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to create the draft for. /// /// 200 => Content draft created. @@ -560,11 +557,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpPost] - [Route("content/{app}/{name}/{id}/draft/")] + [Route("content/{app}/{schema}/{id}/draft/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsVersionCreateOwn)] [ApiCosts(1)] - public async Task CreateDraft(string app, string name, DomainId id) + public async Task CreateDraft(string app, string schema, DomainId id) { var command = new CreateContentDraft { ContentId = id }; @@ -577,7 +574,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Delete the draft version. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to delete the draft from. /// /// 200 => Content draft deleted. @@ -587,11 +584,11 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can read the generated documentation for your app at /api/content/{appName}/docs. /// [HttpDelete] - [Route("content/{app}/{name}/{id}/draft/")] + [Route("content/{app}/{schema}/{id}/draft/")] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppContentsDeleteOwn)] [ApiCosts(1)] - public async Task DeleteVersion(string app, string name, DomainId id) + public async Task DeleteVersion(string app, string schema, DomainId id) { var command = new DeleteContentDraft { ContentId = id }; @@ -604,7 +601,7 @@ namespace Squidex.Areas.Api.Controllers.Contents /// Delete a content item. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the content item to delete. /// The request parameters. /// @@ -616,10 +613,10 @@ namespace Squidex.Areas.Api.Controllers.Contents /// You can create an generated documentation for your app at /api/content/{appName}/docs. /// [HttpDelete] - [Route("content/{app}/{name}/{id}/")] + [Route("content/{app}/{schema}/{id}/")] [ApiPermissionOrAnonymous(Permissions.AppContentsDeleteOwn)] [ApiCosts(1)] - public async Task DeleteContent(string app, string name, DomainId id, DeleteContentDto request) + public async Task DeleteContent(string app, string schema, DomainId id, DeleteContentDto request) { var command = request.ToCommand(id); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs index dd805fe3c..8d4ab59dd 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationsBuilder.cs @@ -31,9 +31,9 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator public JsonSchema DataSchema { get; init; } - public string FormatText(string text) + public string? FormatText(string text) { - return text?.Replace("schema ", $"'{SchemaDisplayName}' ", StringComparison.OrdinalIgnoreCase)!; + return text?.Replace("[schema]", $"'{SchemaDisplayName}'", StringComparison.Ordinal); } public OperationBuilder AddOperation(string method, string path) diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs index 763f5af89..5cb72fdba 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs @@ -19,6 +19,7 @@ using Squidex.Hosting; using Squidex.Infrastructure.Caching; using Squidex.Properties; using Squidex.Shared; +using SchemaDefType = Squidex.Domain.Apps.Core.Schemas.SchemaType; namespace Squidex.Areas.Api.Controllers.Contents.Generator { @@ -49,16 +50,24 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator requestCache.AddDependency(app.UniqueId, app.Version); + foreach (var schema in schemas) + { + requestCache.AddDependency(schema.UniqueId, schema.Version); + } + var builder = new Builder( app, document, schemaResolver, schemaGenerator); - foreach (var schema in schemas.Where(x => x.SchemaDef.IsPublished)) - { - requestCache.AddDependency(schema.UniqueId, schema.Version); + var validSchemas = schemas.Where(x => + x.SchemaDef.IsPublished && + x.SchemaDef.Type != SchemaDefType.Component && + x.SchemaDef.Fields.Count > 0); + foreach (var schema in validSchemas) + { GenerateSchemaOperations(builder.Schema(schema.SchemaDef, flat)); } @@ -96,7 +105,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Get, "/") .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Query") - .OperationSummary("Query schema contents items.") + .OperationSummary("Query [schema] contents items.") .Describe(Resources.OpenApiSchemaQuery) .HasQueryOptions(true) .Responds(200, "Content items retrieved.", builder.ContentsSchema) @@ -105,14 +114,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Get, "/{id}") .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Get") - .OperationSummary("Get a schema content item.") + .OperationSummary("Get a [schema] content item.") .HasId() .Responds(200, "Content item returned.", builder.ContentSchema); builder.AddOperation(OpenApiOperationMethod.Get, "/{id}/{version}") .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Get") - .OperationSummary("Get a schema content item by id and version.") + .OperationSummary("Get a [schema] content item by id and version.") .HasPath("version", JsonObjectType.Number, "The version of the content item.") .HasId() .Responds(200, "Content item returned.", builder.ContentSchema); @@ -120,7 +129,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Get, "/{id}/validity") .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Validate") - .OperationSummary("Validates a schema content item.") + .OperationSummary("Validates a [schema] content item.") .HasId() .Responds(200, "Content item is valid.") .Responds(400, "Content item is not valid."); @@ -128,7 +137,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Post, "/") .RequirePermission(Permissions.AppContentsCreate) .Operation("Create") - .OperationSummary("Create a schema content item.") + .OperationSummary("Create a [schema] content item.") .HasQuery("publish", JsonObjectType.Boolean, "True to automatically publish the content.") .HasQuery("id", JsonObjectType.String, "The optional custom content id.") .HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody) @@ -138,7 +147,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Post, "/{id}") .RequirePermission(Permissions.AppContentsUpsert) .Operation("Upsert") - .OperationSummary("Upsert a schema content item.") + .OperationSummary("Upsert a [schema] content item.") .HasQuery("publish", JsonObjectType.Boolean, "True to automatically publish the content.") .HasId() .HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody) @@ -148,7 +157,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Put, "/{id}") .RequirePermission(Permissions.AppContentsUpdateOwn) .Operation("Update") - .OperationSummary("Update a schema content item.") + .OperationSummary("Update a [schema] content item.") .HasId() .HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody) .Responds(200, "Content item updated.", builder.ContentSchema) @@ -157,7 +166,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Patch, "/{id}") .RequirePermission(Permissions.AppContentsUpdateOwn) .Operation("Patch") - .OperationSummary("Patch a schema content item.") + .OperationSummary("Patch a [schema] content item.") .HasId() .HasBody("data", builder.DataSchema, Resources.OpenApiSchemaBody) .Responds(200, "Content item updated.", builder.ContentSchema) @@ -166,7 +175,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Put, "/{id}/status") .RequirePermission(Permissions.AppContentsChangeStatusOwn) .Operation("Change") - .OperationSummary("Change the status of a schema content item.") + .OperationSummary("Change the status of a [schema] content item.") .HasId() .HasBody("request", builder.Parent.ChangeStatusSchema, "The request to change content status.") .Responds(200, "Content status updated.", builder.ContentSchema) @@ -175,7 +184,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator builder.AddOperation(OpenApiOperationMethod.Delete, "/{id}") .RequirePermission(Permissions.AppContentsDeleteOwn) .Operation("Delete") - .OperationSummary("Delete a schema content item.") + .OperationSummary("Delete a [schema] content item.") .HasId() .Responds(204, "Content item deleted"); } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsDto.cs index e1edfffdb..5bfd6ce87 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/BulkUpdateContentsDto.cs @@ -12,8 +12,6 @@ using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Validation; -#pragma warning disable CS0618 // Type or member is obsolete - namespace Squidex.Areas.Api.Controllers.Contents.Models { public sealed class BulkUpdateContentsDto @@ -61,6 +59,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models result.Jobs = Jobs?.Select(x => x.ToJob())?.ToArray(); +#pragma warning disable CS0618 // Type or member is obsolete if (result.Jobs != null && Publish) { foreach (var job in result.Jobs) @@ -71,6 +70,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models } } } +#pragma warning restore CS0618 // Type or member is obsolete return result; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs index 2905a6374..dc16dc403 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs @@ -138,13 +138,13 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models { var app = resources.App; - var values = new { app, name = schema, id = Id }; + var values = new { app, schema, id = Id }; AddSelfLink(resources.Url(x => nameof(x.GetContent), values)); if (Version > 0) { - var versioned = new { app, name = schema, id = Id, version = Version - 1 }; + var versioned = new { app, schema, id = Id, version = Version - 1 }; AddGetLink("previous", resources.Url(x => nameof(x.GetContentVersion), versioned)); } @@ -179,10 +179,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models if (content.CanUpdate && resources.CanUpdateContent(schema)) { - AddPutLink("update", resources.Url(x => nameof(x.PutContent), values)); AddPatchLink("patch", resources.Url(x => nameof(x.PatchContent), values)); } + if (content.CanUpdate && resources.CanUpdateContent(schema)) + { + AddPutLink("update", resources.Url(x => nameof(x.PutContent), values)); + } + return this; } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs index 3ffb7ec25..181a24c59 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs @@ -62,7 +62,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models private void CreateLinks(Resources resources, string schema) { - var values = new { app = resources.App, name = schema }; + var values = new { app = resources.App, schema }; AddSelfLink(resources.Url(x => nameof(x.GetContents), values)); @@ -70,7 +70,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models { AddPostLink("create", resources.Url(x => nameof(x.PostContent), values)); - var publishValues = new { values.app, values.name, publish = true }; + var publishValues = new { values.app, values.schema, publish = true }; AddPostLink("create/publish", resources.Url(x => nameof(x.PostContent), publishValues)); } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/CreateContentDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/CreateContentDto.cs index e3824e8fe..67e521751 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/CreateContentDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/CreateContentDto.cs @@ -12,8 +12,6 @@ using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Infrastructure; using StatusType = Squidex.Domain.Apps.Core.Contents.Status; -#pragma warning disable CS0618 // Type or member is obsolete - namespace Squidex.Areas.Api.Controllers.Contents.Models { public class CreateContentDto @@ -56,10 +54,12 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models { command.Status = Status; } +#pragma warning disable CS0618 // Type or member is obsolete else if (Publish) { command.Status = StatusType.Published; } +#pragma warning restore CS0618 // Type or member is obsolete return command; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ImportContentsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ImportContentsDto.cs index a92cb3a05..7a199403f 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ImportContentsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ImportContentsDto.cs @@ -13,8 +13,6 @@ using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Validation; -#pragma warning disable CS0618 // Type or member is obsolete - namespace Squidex.Areas.Api.Controllers.Contents.Models { public sealed class ImportContentsDto @@ -47,6 +45,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models result.Jobs = Datas?.Select(x => new BulkUpdateJob { Type = BulkUpdateContentType.Create, Data = x }).ToArray(); +#pragma warning disable CS0618 // Type or member is obsolete if (result.Jobs != null && Publish) { foreach (var job in result.Jobs) @@ -57,6 +56,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models } } } +#pragma warning restore CS0618 // Type or member is obsolete return result; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs index 83bd2e932..ffc07ebf8 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/UpsertContentDto.cs @@ -12,8 +12,6 @@ using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Infrastructure; using StatusType = Squidex.Domain.Apps.Core.Contents.Status; -#pragma warning disable CS0618 // Type or member is obsolete - namespace Squidex.Areas.Api.Controllers.Contents.Models { public class UpsertContentDto @@ -45,10 +43,12 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models { command.Status = Status; } +#pragma warning disable CS0618 // Type or member is obsolete else if (Publish) { command.Status = StatusType.Published; } +#pragma warning restore CS0618 // Type or member is obsolete return command; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs index 483a41d91..a5e7c20a3 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs @@ -413,18 +413,18 @@ namespace Squidex.Areas.Api.Controllers.Rules /// /// Provide the json schema for the event with the specified name. /// - /// The name of the event. + /// The type name of the event. /// /// 200 => Rule event type found. /// 404 => Rule event not found. /// [HttpGet] - [Route("rules/eventtypes/{name}")] + [Route("rules/eventtypes/{type}")] [ProducesResponseType(typeof(object), StatusCodes.Status200OK)] [AllowAnonymous] - public IActionResult GetEventSchema(string name) + public IActionResult GetEventSchema(string type) { - var schema = eventJsonSchemaGenerator.GetSchema(name); + var schema = eventJsonSchemaGenerator.GetSchema(type); if (schema == null) { @@ -446,4 +446,4 @@ namespace Squidex.Areas.Api.Controllers.Rules return response; } } -} \ No newline at end of file +} diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs index 706f1efb7..17d85661e 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs @@ -40,6 +40,16 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Converters return SimpleMapper.Map(properties, new BooleanFieldPropertiesDto()); } + public FieldPropertiesDto Visit(ComponentFieldProperties properties, None args) + { + return SimpleMapper.Map(properties, new ComponentFieldPropertiesDto()); + } + + public FieldPropertiesDto Visit(ComponentsFieldProperties properties, None args) + { + return SimpleMapper.Map(properties, new ComponentsFieldPropertiesDto()); + } + public FieldPropertiesDto Visit(DateTimeFieldProperties properties, None args) { return SimpleMapper.Map(properties, new DateTimeFieldPropertiesDto()); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs index a5632885b..26baca97a 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs @@ -108,7 +108,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models if (allowUpdate) { - var values = new { app = resources.App, name = schema, id = FieldId }; + var values = new { app = resources.App, schema, id = FieldId }; AddPutLink("update", resources.Url(x => nameof(x.PutField), values)); @@ -132,7 +132,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models if (Properties is ArrayFieldPropertiesDto) { - var parentValues = new { values.app, values.name, parentId = FieldId }; + var parentValues = new { values.app, values.schema, parentId = FieldId }; AddPostLink("fields/add", resources.Url(x => nameof(x.PostNestedField), parentValues)); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentFieldPropertiesDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentFieldPropertiesDto.cs new file mode 100644 index 000000000..d70301f49 --- /dev/null +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentFieldPropertiesDto.cs @@ -0,0 +1,29 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Reflection; + +namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields +{ + public sealed class ComponentFieldPropertiesDto : FieldPropertiesDto + { + /// + /// The id of the embedded schemas. + /// + public ImmutableList? SchemaIds { get; set; } + + public override FieldProperties ToProperties() + { + var result = SimpleMapper.Map(this, new ComponentFieldProperties()); + + return result; + } + } +} diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentsFieldPropertiesDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentsFieldPropertiesDto.cs new file mode 100644 index 000000000..048c7f4c0 --- /dev/null +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ComponentsFieldPropertiesDto.cs @@ -0,0 +1,39 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Reflection; + +namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields +{ + public sealed class ComponentsFieldPropertiesDto : FieldPropertiesDto + { + /// + /// The minimum allowed items for the field value. + /// + public int? MinItems { get; set; } + + /// + /// The maximum allowed items for the field value. + /// + public int? MaxItems { get; set; } + + /// + /// The id of the embedded schemas. + /// + public ImmutableList? SchemaIds { get; set; } + + public override FieldProperties ToProperties() + { + var result = SimpleMapper.Map(this, new ComponentsFieldProperties()); + + return result; + } + } +} diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs index 85c877c13..1d1ccd5eb 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs @@ -51,7 +51,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models if (allowUpdate) { - var values = new { app = resources.App, name = schema, parentId, id = FieldId }; + var values = new { app = resources.App, schema, parentId, id = FieldId }; AddPutLink("update", resources.Url(x => nameof(x.PutNestedField), values)); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs index c463ba750..0b928b20e 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs @@ -151,7 +151,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models protected virtual void CreateLinks(Resources resources) { - var values = new { app = resources.App, name = Name }; + var values = new { app = resources.App, schema = Name }; var allowUpdate = resources.CanUpdateSchema(Name); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs index 15f1592ec..017f58eb4 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs @@ -32,7 +32,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Add a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The field object that needs to be added to the schema. /// /// 201 => Schema field created. @@ -41,24 +41,24 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 409 => Schema field name already in use. /// [HttpPost] - [Route("apps/{app}/schemas/{name}/fields/")] + [Route("apps/{app}/schemas/{schema}/fields/")] [ProducesResponseType(typeof(SchemaDto), 201)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PostField(string app, string name, [FromBody] AddFieldDto request) + public async Task PostField(string app, string schema, [FromBody] AddFieldDto request) { var command = request.ToCommand(); var response = await InvokeCommandAsync(command); - return CreatedAtAction(nameof(SchemasController.GetSchema), "Schemas", new { app, name }, response); + return CreatedAtAction(nameof(SchemasController.GetSchema), "Schemas", new { app, schema }, response); } /// /// Add a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The field object that needs to be added to the schema. /// @@ -68,24 +68,24 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema, field or app not found. /// [HttpPost] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/")] [ProducesResponseType(typeof(SchemaDto), 201)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PostNestedField(string app, string name, long parentId, [FromBody] AddFieldDto request) + public async Task PostNestedField(string app, string schema, long parentId, [FromBody] AddFieldDto request) { var command = request.ToCommand(parentId); var response = await InvokeCommandAsync(command); - return CreatedAtAction(nameof(SchemasController.GetSchema), "Schemas", new { app, name }, response); + return CreatedAtAction(nameof(SchemasController.GetSchema), "Schemas", new { app, schema }, response); } /// /// Configure UI fields. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The request that contains the field names. /// /// 200 => Schema UI fields defined. @@ -93,11 +93,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/ui/")] + [Route("apps/{app}/schemas/{schema}/fields/ui/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutSchemaUIFields(string app, string name, [FromBody] ConfigureUIFieldsDto request) + public async Task PutSchemaUIFields(string app, string schema, [FromBody] ConfigureUIFieldsDto request) { var command = request.ToCommand(); @@ -110,7 +110,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Reorder all fields. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The request that contains the field ids. /// /// 200 => Schema fields reordered. @@ -118,11 +118,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/ordering/")] + [Route("apps/{app}/schemas/{schema}/fields/ordering/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutSchemaFieldOrdering(string app, string name, [FromBody] ReorderFieldsDto request) + public async Task PutSchemaFieldOrdering(string app, string schema, [FromBody] ReorderFieldsDto request) { var command = request.ToCommand(); @@ -135,7 +135,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Reorder all nested fields. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The request that contains the field ids. /// @@ -144,11 +144,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema, field or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/ordering/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/ordering/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutNestedFieldOrdering(string app, string name, long parentId, [FromBody] ReorderFieldsDto request) + public async Task PutNestedFieldOrdering(string app, string schema, long parentId, [FromBody] ReorderFieldsDto request) { var command = request.ToCommand(parentId); @@ -161,7 +161,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Update a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to update. /// The field object that needs to be added to the schema. /// @@ -170,11 +170,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema, field or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutField(string app, string name, long id, [FromBody] UpdateFieldDto request) + public async Task PutField(string app, string schema, long id, [FromBody] UpdateFieldDto request) { var command = request.ToCommand(id); @@ -187,7 +187,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Update a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to update. /// The field object that needs to be added to the schema. @@ -197,11 +197,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema, field or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutNestedField(string app, string name, long parentId, long id, [FromBody] UpdateFieldDto request) + public async Task PutNestedField(string app, string schema, long parentId, long id, [FromBody] UpdateFieldDto request) { var command = request.ToCommand(id, parentId); @@ -214,7 +214,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Lock a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to lock. /// /// 200 => Schema field shown. @@ -225,11 +225,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A locked field cannot be updated or deleted. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/lock/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/lock/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task LockField(string app, string name, long id) + public async Task LockField(string app, string schema, long id) { var command = new LockField { FieldId = id }; @@ -242,7 +242,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Lock a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to lock. /// @@ -254,11 +254,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A locked field cannot be edited or deleted. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/lock/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/lock/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task LockNestedField(string app, string name, long parentId, long id) + public async Task LockNestedField(string app, string schema, long parentId, long id) { var command = new LockField { ParentFieldId = parentId, FieldId = id }; @@ -271,7 +271,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Hide a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to hide. /// /// 200 => Schema field hidden. @@ -282,11 +282,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A hidden field is not part of the API response, but can still be edited in the portal. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/hide/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/hide/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task HideField(string app, string name, long id) + public async Task HideField(string app, string schema, long id) { var command = new HideField { FieldId = id }; @@ -299,7 +299,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Hide a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to hide. /// @@ -311,11 +311,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A hidden field is not part of the API response, but can still be edited in the portal. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/hide/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/hide/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task HideNestedField(string app, string name, long parentId, long id) + public async Task HideNestedField(string app, string schema, long parentId, long id) { var command = new HideField { ParentFieldId = parentId, FieldId = id }; @@ -328,7 +328,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Show a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to show. /// /// 200 => Schema field shown. @@ -339,11 +339,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A hidden field is not part of the API response, but can still be edited in the portal. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/show/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/show/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task ShowField(string app, string name, long id) + public async Task ShowField(string app, string schema, long id) { var command = new ShowField { FieldId = id }; @@ -356,7 +356,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Show a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to show. /// @@ -368,11 +368,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A hidden field is not part of the API response, but can still be edited in the portal. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/show/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/show/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task ShowNestedField(string app, string name, long parentId, long id) + public async Task ShowNestedField(string app, string schema, long parentId, long id) { var command = new ShowField { ParentFieldId = parentId, FieldId = id }; @@ -385,7 +385,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Enable a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to enable. /// /// 200 => Schema field enabled. @@ -396,11 +396,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A disabled field cannot not be edited in the squidex portal anymore, but will be part of the API response. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/enable/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/enable/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task EnableField(string app, string name, long id) + public async Task EnableField(string app, string schema, long id) { var command = new EnableField { FieldId = id }; @@ -413,7 +413,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Enable a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to enable. /// @@ -425,11 +425,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A disabled field cannot not be edited in the squidex portal anymore, but will be part of the API response. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/enable/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/enable/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task EnableNestedField(string app, string name, long parentId, long id) + public async Task EnableNestedField(string app, string schema, long parentId, long id) { var command = new EnableField { ParentFieldId = parentId, FieldId = id }; @@ -442,7 +442,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Disable a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to disable. /// /// 200 => Schema field disabled. @@ -453,11 +453,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A disabled field cannot not be edited in the squidex portal anymore, but will be part of the API response. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/disable/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/disable/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task DisableField(string app, string name, long id) + public async Task DisableField(string app, string schema, long id) { var command = new DisableField { FieldId = id }; @@ -470,7 +470,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Disable a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to disable. /// @@ -482,11 +482,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// A disabled field cannot not be edited in the squidex portal anymore, but will be part of the API response. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/disable/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/disable/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task DisableNestedField(string app, string name, long parentId, long id) + public async Task DisableNestedField(string app, string schema, long parentId, long id) { var command = new DisableField { ParentFieldId = parentId, FieldId = id }; @@ -499,7 +499,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Delete a schema field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The id of the field to disable. /// /// 200 => Schema field deleted. @@ -507,11 +507,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema, field or app not found. /// [HttpDelete] - [Route("apps/{app}/schemas/{name}/fields/{id:long}/")] + [Route("apps/{app}/schemas/{schema}/fields/{id:long}/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task DeleteField(string app, string name, long id) + public async Task DeleteField(string app, string schema, long id) { var command = new DeleteField { FieldId = id }; @@ -524,7 +524,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Delete a nested field. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The parent field id. /// The id of the field to disable. /// @@ -533,11 +533,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema, field or app not found. /// [HttpDelete] - [Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/")] + [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task DeleteNestedField(string app, string name, long parentId, long id) + public async Task DeleteNestedField(string app, string schema, long parentId, long id) { var command = new DeleteField { ParentFieldId = parentId, FieldId = id }; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs index 21381f213..e2dc81616 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs @@ -70,31 +70,24 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Get a schema by name. /// /// The name of the app. - /// The name of the schema to retrieve. + /// The name of the schema to retrieve. /// /// 200 => Schema found. /// 404 => Schema or app not found. /// [HttpGet] - [Route("apps/{app}/schemas/{name}/")] + [Route("apps/{app}/schemas/{schema}/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasRead)] [ApiCosts(0)] - public async Task GetSchema(string app, string name) + public IActionResult GetSchema(string app, string schema) { - var schema = await GetSchemaAsync(name); - - if (schema == null) - { - return NotFound(); - } - var response = Deferred.Response(() => { - return SchemaDto.FromSchema(schema, Resources); + return SchemaDto.FromSchema(Schema, Resources); }); - Response.Headers[HeaderNames.ETag] = schema.ToEtag(); + Response.Headers[HeaderNames.ETag] = Schema.ToEtag(); return Ok(response); } @@ -120,14 +113,14 @@ namespace Squidex.Areas.Api.Controllers.Schemas var response = await InvokeCommandAsync(command); - return CreatedAtAction(nameof(GetSchema), new { app, name = request.Name }, response); + return CreatedAtAction(nameof(GetSchema), new { app, schema = request.Name }, response); } /// /// Update a schema. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The schema object that needs to updated. /// /// 200 => Schema updated. @@ -135,11 +128,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/")] + [Route("apps/{app}/schemas/{schema}/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutSchema(string app, string name, [FromBody] UpdateSchemaDto request) + public async Task PutSchema(string app, string schema, [FromBody] UpdateSchemaDto request) { var command = request.ToCommand(); @@ -152,7 +145,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Synchronize a schema. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The schema object that needs to updated. /// /// 200 => Schema updated. @@ -160,11 +153,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/sync")] + [Route("apps/{app}/schemas/{schema}/sync")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutSchemaSync(string app, string name, [FromBody] SynchronizeSchemaDto request) + public async Task PutSchemaSync(string app, string schema, [FromBody] SynchronizeSchemaDto request) { var command = request.ToCommand(); @@ -177,7 +170,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Update a schema category. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The schema object that needs to updated. /// /// 200 => Schema updated. @@ -185,11 +178,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/category")] + [Route("apps/{app}/schemas/{schema}/category")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutCategory(string app, string name, [FromBody] ChangeCategoryDto request) + public async Task PutCategory(string app, string schema, [FromBody] ChangeCategoryDto request) { var command = request.ToCommand(); @@ -202,7 +195,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Update the preview urls. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The preview urls for the schema. /// /// 200 => Schema updated. @@ -210,11 +203,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/preview-urls")] + [Route("apps/{app}/schemas/{schema}/preview-urls")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutPreviewUrls(string app, string name, [FromBody] ConfigurePreviewUrlsDto request) + public async Task PutPreviewUrls(string app, string schema, [FromBody] ConfigurePreviewUrlsDto request) { var command = request.ToCommand(); @@ -227,7 +220,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Update the scripts. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The schema scripts object that needs to updated. /// /// 200 => Schema updated. @@ -235,11 +228,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/scripts/")] + [Route("apps/{app}/schemas/{schema}/scripts/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasScripts)] [ApiCosts(1)] - public async Task PutScripts(string app, string name, [FromBody] SchemaScriptsDto request) + public async Task PutScripts(string app, string schema, [FromBody] SchemaScriptsDto request) { var command = request.ToCommand(); @@ -252,7 +245,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Update the rules. /// /// The name of the app. - /// The name of the schema. + /// The name of the schema. /// The schema rules object that needs to updated. /// /// 200 => Schema updated. @@ -260,11 +253,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/rules/")] + [Route("apps/{app}/schemas/{schema}/rules/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiCosts(1)] - public async Task PutRules(string app, string name, [FromBody] ConfigureFieldRulesDto request) + public async Task PutRules(string app, string schema, [FromBody] ConfigureFieldRulesDto request) { var command = request.ToCommand(); @@ -277,17 +270,17 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Publish a schema. /// /// The name of the app. - /// The name of the schema to publish. + /// The name of the schema to publish. /// /// 200 => Schema published. /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/publish/")] + [Route("apps/{app}/schemas/{schema}/publish/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasPublish)] [ApiCosts(1)] - public async Task PublishSchema(string app, string name) + public async Task PublishSchema(string app, string schema) { var command = new PublishSchema(); @@ -300,17 +293,17 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Unpublish a schema. /// /// The name of the app. - /// The name of the schema to unpublish. + /// The name of the schema to unpublish. /// /// 200 => Schema unpublished. /// 404 => Schema or app not found. /// [HttpPut] - [Route("apps/{app}/schemas/{name}/unpublish/")] + [Route("apps/{app}/schemas/{schema}/unpublish/")] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(Permissions.AppSchemasPublish)] [ApiCosts(1)] - public async Task UnpublishSchema(string app, string name) + public async Task UnpublishSchema(string app, string schema) { var command = new UnpublishSchema(); @@ -323,16 +316,16 @@ namespace Squidex.Areas.Api.Controllers.Schemas /// Delete a schema. /// /// The name of the app. - /// The name of the schema to delete. + /// The name of the schema to delete. /// /// 204 => Schema deleted. /// 404 => Schema or app not found. /// [HttpDelete] - [Route("apps/{app}/schemas/{name}/")] + [Route("apps/{app}/schemas/{schema}/")] [ApiPermissionOrAnonymous(Permissions.AppSchemasDelete)] [ApiCosts(1)] - public async Task DeleteSchema(string app, string name) + public async Task DeleteSchema(string app, string schema) { await CommandBus.PublishAsync(new DeleteSchema()); @@ -340,30 +333,23 @@ namespace Squidex.Areas.Api.Controllers.Schemas } [HttpGet] - [Route("apps/{app}/schemas/{name}/completion")] + [Route("apps/{app}/schemas/{schema}/completion")] [ApiPermissionOrAnonymous] [ApiCosts(1)] [OpenApiIgnore] - public async Task GetScriptCompletiong(string app, string name) + public IActionResult GetScriptCompletion(string app, string schema) { - var schema = await GetSchemaAsync(name); - - if (schema == null) - { - return NotFound(); - } - var completer = new ScriptingCompletion(); - var completion = completer.GetCompletion(schema.SchemaDef, App.PartitionResolver()); + var completion = completer.GetCompletion(Schema.SchemaDef, App.PartitionResolver()); var result = completion.Select(x => new { x.Name, x.Description }); return Ok(result); } - private Task GetSchemaAsync(string name) + private Task GetSchemaAsync(string schema) { - if (Guid.TryParse(name, out var guid)) + if (Guid.TryParse(schema, out var guid)) { var schemaId = DomainId.Create(guid); @@ -371,7 +357,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas } else { - return appProvider.GetSchemaAsync(AppId, name); + return appProvider.GetSchemaAsync(AppId, schema); } } diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs index 916c67ea3..299b7b026 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs @@ -458,19 +458,19 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas public void Should_serialize_and_deserialize_schema() { var schemaSource = - TestUtils.MixedSchema(SchemaType.Singleton) + TestUtils.MixedSchema(SchemaType.Singleton, false) .ChangeCategory("Category") .SetFieldRules(FieldRule.Hide("2")) .SetFieldsInLists("field2") .SetFieldsInReferences("field1") - .SetPreviewUrls(new Dictionary - { - ["web"] = "Url" - }.ToImmutableDictionary()) .SetScripts(new SchemaScripts { Create = "" - }); + }) + .SetPreviewUrls(new Dictionary + { + ["web"] = "Url" + }.ToImmutableDictionary()); var schemaTarget = schemaSource.SerializeAndDeserialize(); diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs index fb1f0e521..847b3c421 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs @@ -8,6 +8,8 @@ using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ConvertContent @@ -20,60 +22,102 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { schema = new Schema("my-schema") - .AddNumber(1, "field1", Partitioning.Language) - .AddNumber(2, "field2", Partitioning.Invariant) - .AddNumber(3, "field3", Partitioning.Invariant) - .AddAssets(5, "assets1", Partitioning.Invariant) - .AddAssets(6, "assets2", Partitioning.Invariant) - .AddArray(7, "array", Partitioning.Invariant, h => h - .AddNumber(71, "nested1") - .AddNumber(72, "nested2")) - .AddJson(4, "json", Partitioning.Language) - .HideField(2) - .HideField(71, 7) - .UpdateField(3, f => f.Hide()); + .AddComponent(1, "component", Partitioning.Invariant) + .AddComponents(2, "components", Partitioning.Invariant) + .AddAssets(3, "assets1", Partitioning.Invariant) + .AddAssets(4, "assets2", Partitioning.Invariant) + .AddReferences(5, "references", Partitioning.Invariant) + .AddArray(6, "array", Partitioning.Invariant, a => a + .AddAssets(31, "nested")); + + schema.FieldsById[1].SetResolvedSchema(DomainId.Empty, schema); + schema.FieldsById[2].SetResolvedSchema(DomainId.Empty, schema); } [Fact] - public void Should_convert_name_to_name() + public void Should_apply_value_conversion_on_all_levels() { - var input = + var source = new ContentData() - .AddField("field1", + .AddField("references", new ContentFieldData() - .AddLocalized("en", "EN")) - .AddField("field2", + .AddInvariant(JsonValue.Array(1, 2))) + .AddField("assets1", new ContentFieldData() - .AddInvariant(1)) - .AddField("invalid", + .AddInvariant(JsonValue.Array(1))) + .AddField("array", new ContentFieldData() - .AddInvariant(2)); - - var actual = input.Convert(schema, (data, field) => field.Name == "field2" ? null : data); + .AddInvariant( + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(1, 2))))) + .AddField("component", + new ContentFieldData() + .AddInvariant( + JsonValue.Object() + .Add("references", + JsonValue.Array(1, 2)) + .Add("assets1", + JsonValue.Array(1)) + .Add("array", + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(1, 2)))) + .Add(Component.Discriminator, DomainId.Empty))) + .AddField("components", + new ContentFieldData() + .AddInvariant( + JsonValue.Array( + JsonValue.Object() + .Add("references", + JsonValue.Array(1, 2)) + .Add("assets1", + JsonValue.Array(1)) + .Add("array", + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(1, 2)))) + .Add(Component.Discriminator, DomainId.Empty)))); var expected = new ContentData() - .AddField("field1", + .AddField("references", + new ContentFieldData()) + .AddField("assets1", new ContentFieldData() - .AddLocalized("en", "EN")); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Should_be_equal_fields_if_they_have_same_value() - { - var lhs = - new ContentFieldData() - .AddInvariant(2); + .AddInvariant(JsonValue.Array(1))) + .AddField("array", + new ContentFieldData() + .AddInvariant( + JsonValue.Array( + JsonValue.Object()))) + .AddField("component", + new ContentFieldData() + .AddInvariant( + JsonValue.Object() + .Add("assets1", + JsonValue.Array(1)) + .Add("array", + JsonValue.Array( + JsonValue.Object())) + .Add(Component.Discriminator, DomainId.Empty))) + .AddField("components", + new ContentFieldData() + .AddInvariant( + JsonValue.Array( + JsonValue.Object() + .Add("assets1", + JsonValue.Array(1)) + .Add("array", + JsonValue.Array( + JsonValue.Object())) + .Add(Component.Discriminator, DomainId.Empty)))); - var rhs = - new ContentFieldData() - .AddInvariant(2); + var actual = + source.Convert(schema, + FieldConverters.ForValues((data, field, parent) => field.Name != "assets1" ? null : data)); - Assert.True(lhs.Equals(rhs)); - Assert.True(lhs.Equals((object)rhs)); - Assert.Equal(lhs.GetHashCode(), rhs.GetHashCode()); + Assert.Equal(expected, actual); } } } diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/StringFormatterTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/StringFormatterTests.cs index d8240644a..1f10cb003 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/StringFormatterTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/StringFormatterTests.cs @@ -166,6 +166,54 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent Assert.Equal("No", formatted); } + [Fact] + public void Should_format_component_field() + { + var value = JsonValue.Object(); + + var field = Fields.Component(1, "field", Partitioning.Invariant); + + var formatted = StringFormatter.Format(field, value); + + Assert.Equal("{ Component }", formatted); + } + + [Fact] + public void Should_format_components_field_without_items() + { + var value = JsonValue.Array(); + + var field = Fields.Components(1, "field", Partitioning.Invariant); + + var formatted = StringFormatter.Format(field, value); + + Assert.Equal("0 Components", formatted); + } + + [Fact] + public void Should_format_components_field_with_single_item() + { + var value = JsonValue.Array(JsonValue.Object()); + + var field = Fields.Components(1, "field", Partitioning.Invariant); + + var formatted = StringFormatter.Format(field, value); + + Assert.Equal("1 Component", formatted); + } + + [Fact] + public void Should_format_components_field_with_multiple_items() + { + var value = JsonValue.Array(JsonValue.Object(), JsonValue.Object()); + + var field = Fields.Components(1, "field", Partitioning.Invariant); + + var formatted = StringFormatter.Format(field, value); + + Assert.Equal("2 Components", formatted); + } + [Fact] public void Should_format_datetime_field() { diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs index fda05d303..db01389b2 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs @@ -39,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Create(123); - var result = ValueConverters.ExcludeHidden(source, stringField.Hide()); + var result = ValueConverters.ExcludeHidden(source, stringField.Hide(), null); Assert.Null(result); } @@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Create("invalid"); - var result = ValueConverters.ExcludeChangedTypes(TestUtils.DefaultSerializer)(source, numberField); + var result = ValueConverters.ExcludeChangedTypes(TestUtils.DefaultSerializer)(source, numberField, null); Assert.Null(result); } @@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = JsonValue.Array($"url/to/{id1}", $"url/to/{id2}"); - var result = ValueConverters.ResolveAssetUrls(appId, HashSet.Of(path), urlGenerator)(source, field); + var result = ValueConverters.ResolveAssetUrls(appId, HashSet.Of(path), urlGenerator)(source, field, null); Assert.Equal(expected, result); } @@ -81,7 +81,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = source; - var result = ValueConverters.ResolveAssetUrls(appId, HashSet.Of(path), urlGenerator)(source, field); + var result = ValueConverters.ResolveAssetUrls(appId, HashSet.Of(path), urlGenerator)(source, field, null); Assert.Equal(expected, result); } diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs index a0b79b869..628b7d908 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs @@ -25,10 +25,16 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds { schema = new Schema("my-schema") - .AddReferences(1, "references", Partitioning.Invariant) - .AddAssets(2, "assets", Partitioning.Invariant) - .AddArray(3, "array", Partitioning.Invariant, a => a + .AddComponent(1, "component", Partitioning.Invariant) + .AddComponents(2, "components", Partitioning.Invariant) + .AddAssets(3, "assets1", Partitioning.Invariant) + .AddAssets(4, "assets2", Partitioning.Invariant) + .AddReferences(5, "references", Partitioning.Invariant) + .AddArray(6, "array", Partitioning.Invariant, a => a .AddAssets(31, "nested")); + + schema.FieldsById[1].SetResolvedSchema(DomainId.Empty, schema); + schema.FieldsById[2].SetResolvedSchema(DomainId.Empty, schema); } [Fact] @@ -39,7 +45,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds var input = new ContentData() - .AddField("assets", + .AddField("assets1", new ContentFieldData() .AddInvariant(JsonValue.Array(id1.ToString(), id2.ToString()))); @@ -58,7 +64,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds var input = new ContentData() - .AddField("assets", + .AddField("assets1", new ContentFieldData() .AddInvariant(JsonValue.Array(id1.ToString(), id2.ToString()))); @@ -80,7 +86,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds .AddField("references", new ContentFieldData() .AddInvariant(JsonValue.Array(id1, id2))) - .AddField("assets", + .AddField("assets1", new ContentFieldData() .AddInvariant(JsonValue.Array(id1))) .AddField("array", @@ -88,14 +94,41 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds .AddInvariant( JsonValue.Array( JsonValue.Object() - .Add("nested", JsonValue.Array(id1, id2))))); + .Add("nested", JsonValue.Array(id1, id2))))) + .AddField("component", + new ContentFieldData() + .AddInvariant( + JsonValue.Object() + .Add("references", + JsonValue.Array(id1, id2)) + .Add("assets1", + JsonValue.Array(id1)) + .Add("array", + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(id1, id2)))) + .Add(Component.Discriminator, DomainId.Empty))) + .AddField("components", + new ContentFieldData() + .AddInvariant( + JsonValue.Array( + JsonValue.Object() + .Add("references", + JsonValue.Array(id1, id2)) + .Add("assets1", + JsonValue.Array(id1)) + .Add("array", + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(id1, id2)))) + .Add(Component.Discriminator, DomainId.Empty)))); var expected = new ContentData() .AddField("references", new ContentFieldData() .AddInvariant(JsonValue.Array(id2))) - .AddField("assets", + .AddField("assets1", new ContentFieldData() .AddInvariant(JsonValue.Array())) .AddField("array", @@ -103,12 +136,38 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds .AddInvariant( JsonValue.Array( JsonValue.Object() - .Add("nested", JsonValue.Array(id2))))); - - var cleaner = ValueReferencesConverter.CleanReferences(new HashSet { id2 }); - var cleanNested = ValueConverters.ForNested(cleaner); - - var converter = FieldConverters.ForValues(cleaner, cleanNested); + .Add("nested", JsonValue.Array(id2))))) + .AddField("component", + new ContentFieldData() + .AddInvariant( + JsonValue.Object() + .Add("references", + JsonValue.Array(id2)) + .Add("assets1", + JsonValue.Array()) + .Add("array", + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(id2)))) + .Add(Component.Discriminator, DomainId.Empty))) + .AddField("components", + new ContentFieldData() + .AddInvariant( + JsonValue.Array( + JsonValue.Object() + .Add("references", + JsonValue.Array(id2)) + .Add("assets1", + JsonValue.Array()) + .Add("array", + JsonValue.Array( + JsonValue.Object() + .Add("nested", JsonValue.Array(id2)))) + .Add(Component.Discriminator, DomainId.Empty)))); + + var converter = + FieldConverters.ForValues( + ValueReferencesConverter.CleanReferences(new HashSet { id2 })); var actual = source.Convert(schema, converter); diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs index f8fe55ae6..e903c5e0a 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs @@ -18,6 +18,7 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema { public class JsonSchemaTests { + private const int MaxDepth = 5; private readonly Schema schema = TestUtils.MixedSchema(); [Fact] diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentFieldTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentFieldTests.cs new file mode 100644 index 000000000..5981fc1c8 --- /dev/null +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentFieldTests.cs @@ -0,0 +1,137 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Core.TestHelpers; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; +using Xunit; + +namespace Squidex.Domain.Apps.Core.Operations.ValidateContent +{ + public class ComponentFieldTests : IClassFixture + { + private readonly List errors = new List(); + + [Fact] + public void Should_instantiate_field() + { + var (_, sut) = Field(new ComponentFieldProperties()); + + Assert.Equal("my-component", sut.Name); + } + + [Fact] + public async Task Should_not_add_error_if_component_is_null_and_valid() + { + var (_, sut) = Field(new ComponentFieldProperties()); + + await sut.ValidateAsync(null, errors); + + Assert.Empty(errors); + } + + [Fact] + public async Task Should_not_add_error_if_component_is_valid() + { + var (id, sut) = Field(new ComponentFieldProperties()); + + await sut.ValidateAsync(CreateValue(id.ToString(), "component-field", 1), errors); + + Assert.Empty(errors); + } + + [Fact] + public async Task Should_add_error_if_component_is_required() + { + var (_, sut) = Field(new ComponentFieldProperties { IsRequired = true }); + + await sut.ValidateAsync(null, errors); + + errors.Should().BeEquivalentTo( + new[] { "Field is required." }); + } + + [Fact] + public async Task Should_add_error_if_component_value_is_required() + { + var (id, sut) = Field(new ComponentFieldProperties { IsRequired = true }, true); + + await sut.ValidateAsync(CreateValue(id.ToString(), "component-field", null), errors); + + errors.Should().BeEquivalentTo( + new[] { "component-field: Field is required." }); + } + + [Fact] + public async Task Should_add_error_if_value_is_not_valid() + { + var (_, sut) = Field(new ComponentFieldProperties()); + + await sut.ValidateAsync(JsonValue.Create("Invalid"), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid json object, expected object with 'schemaId' field." }); + } + + [Fact] + public async Task Should_add_error_if_value_has_no_discriminator() + { + var (_, sut) = Field(new ComponentFieldProperties()); + + await sut.ValidateAsync(CreateValue(null, "field", 1), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid component. No 'schemaId' field found." }); + } + + [Fact] + public async Task Should_add_error_if_value_has_invalid_discriminator() + { + var (_, sut) = Field(new ComponentFieldProperties()); + + await sut.ValidateAsync(CreateValue("invalid", "field", 1), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid component. Cannot find schema." }); + } + + private static IJsonValue CreateValue(string? type, string key, object? value) + { + var obj = JsonValue.Object(); + + if (type != null) + { + obj[Component.Discriminator] = JsonValue.Create(type); + } + + obj.Add(key, value); + + return obj; + } + + private static (DomainId, RootField) Field(ComponentFieldProperties properties, bool isRequired = false) + { + var schema = + new Schema("my-component") + .AddNumber(1, "component-field", Partitioning.Invariant, + new NumberFieldProperties { IsRequired = isRequired }); + + var id = DomainId.NewGuid(); + + var field = + Fields.Component(1, "my-component", Partitioning.Invariant, properties) + .SetResolvedSchema(id, schema); + + return (id, field); + } + } +} diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentsFieldTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentsFieldTests.cs new file mode 100644 index 000000000..eba1084c4 --- /dev/null +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ComponentsFieldTests.cs @@ -0,0 +1,187 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Core.TestHelpers; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; +using Xunit; + +namespace Squidex.Domain.Apps.Core.Operations.ValidateContent +{ + public class ComponentsFieldTests : IClassFixture + { + private readonly List errors = new List(); + + [Fact] + public void Should_instantiate_field() + { + var (_, sut) = Field(new ComponentsFieldProperties()); + + Assert.Equal("my-components", sut.Name); + } + + [Fact] + public async Task Should_not_add_error_if_components_are_null_and_valid() + { + var (_, sut) = Field(new ComponentsFieldProperties()); + + await sut.ValidateAsync(null, errors); + + Assert.Empty(errors); + } + + [Fact] + public async Task Should_not_add_error_if_components_is_valid() + { + var (id, sut) = Field(new ComponentsFieldProperties()); + + await sut.ValidateAsync(CreateValue(1, id.ToString(), "component-field", 1), errors); + + Assert.Empty(errors); + } + + [Fact] + public async Task Should_not_add_error_if_number_of_components_is_equal_to_min_and_max_components() + { + var (id, sut) = Field(new ComponentsFieldProperties { MinItems = 2, MaxItems = 2 }); + + await sut.ValidateAsync(CreateValue(2, id.ToString(), "component-field", 1), errors); + + Assert.Empty(errors); + } + + [Fact] + public async Task Should_add_error_if_components_are_required() + { + var (_, sut) = Field(new ComponentsFieldProperties { IsRequired = true }); + + await sut.ValidateAsync(null, errors); + + errors.Should().BeEquivalentTo( + new[] { "Field is required." }); + } + + [Fact] + public async Task Should_add_error_if_components_value_is_required() + { + var (id, sut) = Field(new ComponentsFieldProperties { IsRequired = true }, true); + + await sut.ValidateAsync(CreateValue(1, id.ToString(), "component-field", null), errors); + + errors.Should().BeEquivalentTo( + new[] { "[1].component-field: Field is required." }); + } + + [Fact] + public async Task Should_add_error_if_value_is_not_valid() + { + var (_, sut) = Field(new ComponentsFieldProperties()); + + await sut.ValidateAsync(JsonValue.Create("Invalid"), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid json type, expected array of objects." }); + } + + [Fact] + public async Task Should_add_error_if_component_is_not_valid() + { + var (_, sut) = Field(new ComponentsFieldProperties()); + + await sut.ValidateAsync(JsonValue.Array(JsonValue.Create("Invalid")), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid json object, expected object with 'schemaId' field." }); + } + + [Fact] + public async Task Should_add_error_if_component_has_no_discriminator() + { + var (_, sut) = Field(new ComponentsFieldProperties()); + + await sut.ValidateAsync(CreateValue(1, null, "field", 1), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid component. No 'schemaId' field found." }); + } + + [Fact] + public async Task Should_add_error_if_value_has_invalid_discriminator() + { + var (_, sut) = Field(new ComponentsFieldProperties()); + + await sut.ValidateAsync(CreateValue(1, "invalid", "field", 1), errors); + + errors.Should().BeEquivalentTo( + new[] { "Invalid component. Cannot find schema." }); + } + + [Fact] + public async Task Should_add_error_if_value_has_not_enough_components() + { + var (id, sut) = Field(new ComponentsFieldProperties { MinItems = 3 }); + + await sut.ValidateAsync(CreateValue(2, id.ToString(), "component-field", 1), errors); + + errors.Should().BeEquivalentTo( + new[] { "Must have at least 3 item(s)." }); + } + + [Fact] + public async Task Should_add_error_if_value_has_too_much_components() + { + var (id, sut) = Field(new ComponentsFieldProperties { MaxItems = 1 }); + + await sut.ValidateAsync(CreateValue(2, id.ToString(), "component-field", 1), errors); + + errors.Should().BeEquivalentTo( + new[] { "Must not have more than 1 item(s)." }); + } + + private static IJsonValue CreateValue(int count, string? type, string key, object? value) + { + var result = JsonValue.Array(); + + for (var i = 0; i < count; i++) + { + var obj = JsonValue.Object(); + + if (type != null) + { + obj[Component.Discriminator] = JsonValue.Create(type); + } + + obj.Add(key, value); + + result.Add(obj); + } + + return result; + } + + private static (DomainId, RootField) Field(ComponentsFieldProperties properties, bool isRequired = false) + { + var schema = + new Schema("my-component") + .AddNumber(1, "component-field", Partitioning.Invariant, + new NumberFieldProperties { IsRequired = isRequired }); + + var id = DomainId.NewGuid(); + + var field = + Fields.Components(1, "my-components", Partitioning.Invariant, properties) + .SetResolvedSchema(id, schema); + + return (id, field); + } + } +} diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs index 7642d54a7..7d9375d16 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs @@ -26,8 +26,6 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { private static readonly NamedId AppId = NamedId.Of(DomainId.NewGuid(), "my-app"); private static readonly NamedId SchemaId = NamedId.Of(DomainId.NewGuid(), "my-schema"); - private static readonly ISemanticLog Log = A.Fake(); - private static readonly IValidatorsFactory Factory = new DefaultValidatorsFactory(); public static Task ValidateAsync(this IValidator validator, object? value, IList errors, Schema? schema = null, @@ -49,11 +47,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var context = CreateContext(schema, mode, updater, action); - var validators = Factories(factory).SelectMany(x => x.CreateValueValidators(context, field, null!)).ToArray(); - var validator = new AggregateValidator(validators, Log); + var validator = new ValidatorBuilder(factory, context).ValueValidator(field); - return new FieldValidator(validator, field) - .ValidateAsync(value, context, CreateFormatter(errors)); + return validator.ValidateAsync(value, context, CreateFormatter(errors)); } public static async Task ValidatePartialAsync(this ContentData data, PartitionResolver partitionResolver, IList errors, @@ -65,7 +61,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var context = CreateContext(schema, mode, updater, action); - var validator = new ContentValidator(partitionResolver, context, Factories(factory), Log); + var validator = new ValidatorBuilder(factory, context).ContentValidator(partitionResolver); await validator.ValidateInputPartialAsync(data); @@ -84,7 +80,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var context = CreateContext(schema, mode, updater, action); - var validator = new ContentValidator(partitionResolver, context, Factories(factory), Log); + var validator = new ValidatorBuilder(factory, context).ContentValidator(partitionResolver); await validator.ValidateInputAsync(data); @@ -109,18 +105,6 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent }; } - private static IEnumerable Factories(IValidatorsFactory? factory) - { - var result = Enumerable.Repeat(Factory, 1); - - if (factory != null) - { - result = result.Union(Enumerable.Repeat(factory, 1)); - } - - return result; - } - public static ValidationContext CreateContext( Schema? schema = null, ValidationMode mode = ValidationMode.Default, @@ -143,5 +127,49 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent return context; } + + private sealed class ValidatorBuilder + { + private static readonly ISemanticLog Log = A.Fake(); + private static readonly IValidatorsFactory Default = new DefaultValidatorsFactory(); + private readonly IValidatorsFactory? validatorFactory; + private readonly ValidationContext validationContext; + + public ValidatorBuilder(IValidatorsFactory? validatorFactory, ValidationContext validationContext) + { + this.validatorFactory = validatorFactory; + this.validationContext = validationContext; + } + + public ContentValidator ContentValidator(PartitionResolver partitionResolver) + { + return new ContentValidator(partitionResolver, validationContext, CreateFactories(), Log); + } + + public IValidator ValueValidator(IField field) + { + return CreateValueValidator(field); + } + + private IValidator CreateValueValidator(IField field) + { + return new FieldValidator(new AggregateValidator(CreateValueValidators(field), Log), field); + } + + private IEnumerable CreateValueValidators(IField field) + { + return CreateFactories().SelectMany(x => x.CreateValueValidators(validationContext, field, CreateValueValidator)); + } + + private IEnumerable CreateFactories() + { + yield return Default; + + if (validatorFactory != null) + { + yield return validatorFactory; + } + } + } } } diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/ComponentValidatorTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/ComponentValidatorTests.cs new file mode 100644 index 000000000..50d58c03c --- /dev/null +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/ComponentValidatorTests.cs @@ -0,0 +1,65 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Threading.Tasks; +using FakeItEasy; +using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Core.TestHelpers; +using Squidex.Domain.Apps.Core.ValidateContent; +using Squidex.Domain.Apps.Core.ValidateContent.Validators; +using Squidex.Infrastructure.Json.Objects; +using Xunit; + +namespace Squidex.Domain.Apps.Core.Operations.ValidateContent.Validators +{ + public class ComponentValidatorTests : IClassFixture + { + private readonly List errors = new List(); + + [Fact] + public async Task Should_create_validator_from_component_and_invoke() + { + var validator = A.Fake(); + + var componentData = JsonValue.Object(); + var componentObject = new Component("type", componentData, new Schema("my-schema")); + + var isFactoryCalled = false; + + var sut = new ComponentValidator(_ => + { + isFactoryCalled = true; + return validator; + }); + + await sut.ValidateAsync(componentObject, errors); + + Assert.True(isFactoryCalled); + + A.CallTo(() => validator.ValidateAsync(componentData, A._, A._)) + .MustHaveHappened(); + } + + [Fact] + public async Task Should_do_nothing_if_value_is_not_a_component() + { + var isFactoryCalled = false; + + var sut = new ComponentValidator(_ => + { + isFactoryCalled = true; + return null!; + }); + + await sut.ValidateAsync(1, errors); + + Assert.False(isFactoryCalled); + } + } +} diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/TestHelpers/TestUtils.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/TestHelpers/TestUtils.cs index 61b0388cb..7eb7956fa 100644 --- a/backend/tests/Squidex.Domain.Apps.Core.Tests/TestHelpers/TestUtils.cs +++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/TestHelpers/TestUtils.cs @@ -19,6 +19,7 @@ using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules.Json; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; +using Squidex.Infrastructure; using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; @@ -81,8 +82,10 @@ namespace Squidex.Domain.Apps.Core.TestHelpers return new NewtonsoftJsonSerializer(serializerSettings); } - public static Schema MixedSchema(SchemaType type = SchemaType.Default) + public static Schema MixedSchema(SchemaType type = SchemaType.Default, bool withMetadata = true) { + var componentId = DomainId.NewGuid(); + var schema = new Schema("user", type: type) .Publish() .AddArray(101, "root-array", Partitioning.Language, f => f @@ -121,6 +124,10 @@ namespace Squidex.Domain.Apps.Core.TestHelpers new TagsFieldProperties()) .AddUI(113, "root-ui", Partitioning.Language, new UIFieldProperties()) + .AddComponent(114, "root-component", Partitioning.Language, + new ComponentFieldProperties { SchemaId = componentId }) + .AddComponents(115, "root-components", Partitioning.Language, + new ComponentsFieldProperties { SchemaId = componentId }) .Update(new SchemaProperties { Hints = "The User" }) .HideField(104) .HideField(211, 101) @@ -128,6 +135,12 @@ namespace Squidex.Domain.Apps.Core.TestHelpers .DisableField(212, 101) .LockField(105); + if (withMetadata) + { + schema.FieldsById[114].SetResolvedSchema(componentId, schema); + schema.FieldsById[115].SetResolvedSchema(componentId, schema); + } + return schema; } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs index c7cb4b95c..9ce9c22f0 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs @@ -85,7 +85,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject }; var schemaDef = - new Schema("my-schema") + new Schema("my-schema").Publish() .AddNumber(1, "my-field1", Partitioning.Invariant, new NumberFieldProperties { IsRequired = true }) .AddNumber(2, "my-field2", Partitioning.Invariant, diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs index 37f06700d..237f81f03 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs @@ -29,17 +29,57 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards private readonly NamedId appId = NamedId.Of(DomainId.NewGuid(), "my-app"); private readonly NamedId schemaId = NamedId.Of(DomainId.NewGuid(), "my-schema"); private readonly ISchemaEntity normalSchema; + private readonly ISchemaEntity normalUnpublishedSchema; private readonly ISchemaEntity singletonSchema; + private readonly ISchemaEntity singletonUnpublishedSchema; private readonly ClaimsPrincipal user = Mocks.FrontendUser(); private readonly RefToken actor = RefToken.User("123"); public GuardContentTests() { - normalSchema = + normalUnpublishedSchema = Mocks.Schema(appId, schemaId, new Schema(schemaId.Name)); - singletonSchema = + normalSchema = + Mocks.Schema(appId, schemaId, new Schema(schemaId.Name).Publish()); + + singletonUnpublishedSchema = Mocks.Schema(appId, schemaId, new Schema(schemaId.Name, type: SchemaType.Singleton)); + + singletonSchema = + Mocks.Schema(appId, schemaId, new Schema(schemaId.Name, type: SchemaType.Singleton).Publish()); + } + + [Fact] + public void Should_throw_exception_if_creating_content_for_unpublished_schema() + { + var context = CreateContext(CreateContent(Status.Draft), normalUnpublishedSchema); + + Assert.Throws(() => context.MustNotCreateForUnpublishedSchema()); + } + + [Fact] + public void Should_not_throw_exception_if_creating_content_for_unpublished_singleton() + { + var context = CreateContext(CreateContent(Status.Draft, singletonSchema.Id), singletonUnpublishedSchema); + + context.MustNotCreateSingleton(); + } + + [Fact] + public void Should_not_throw_exception_if_creating_content_for_published_schema() + { + var context = CreateContext(CreateContent(Status.Draft, singletonSchema.Id), normalSchema); + + context.MustNotCreateSingleton(); + } + + [Fact] + public void Should_not_throw_exception_if_creating_content_for_published_singleton_schema() + { + var context = CreateContext(CreateContent(Status.Draft, singletonSchema.Id), singletonSchema); + + context.MustNotCreateSingleton(); } [Fact] diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs index 49c6c5f44..a1006965a 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs @@ -41,6 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries { var schemaDef = new Schema(schemaId.Name) + .Publish() .SetScripts(new SchemaScripts { Query = "" }); schema = Mocks.Schema(appId, schemaId, schemaDef); @@ -327,4 +328,4 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries return content; } } -} \ No newline at end of file +} diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/DomainObject/Guards/FieldProperties/ComponentsFieldPropertiesTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/DomainObject/Guards/FieldProperties/ComponentsFieldPropertiesTests.cs new file mode 100644 index 000000000..d71843e2b --- /dev/null +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/DomainObject/Guards/FieldProperties/ComponentsFieldPropertiesTests.cs @@ -0,0 +1,44 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Core.TestHelpers; +using Squidex.Infrastructure.Validation; +using Xunit; + +namespace Squidex.Domain.Apps.Entities.Schemas.DomainObject.Guards.FieldProperties +{ + public class ComponentsFieldPropertiesTests : IClassFixture + { + [Fact] + public void Should_add_error_if_min_items_greater_than_max_items() + { + var sut = new ComponentsFieldProperties { MinItems = 10, MaxItems = 5 }; + + var errors = FieldPropertiesValidator.Validate(sut).ToList(); + + errors.Should().BeEquivalentTo( + new List + { + new ValidationError("Max items must be greater or equal to min items.", "MinItems", "MaxItems") + }); + } + + [Fact] + public void Should_not_add_error_if_min_items_equals_to_max_items() + { + var sut = new ComponentsFieldProperties { MinItems = 2, MaxItems = 2 }; + + var errors = FieldPropertiesValidator.Validate(sut).ToList(); + + Assert.Empty(errors); + } + } +} diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs index eea43fa4c..ab8b3c311 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs @@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas } [Fact] - public async Task Should_return_result_to_schema_only_if_user_has_no_permission() + public async Task Should_not_add_result_to_contents_if_user_has_no_permission() { var ctx = ContextWithPermission(); @@ -54,6 +54,28 @@ namespace Squidex.Domain.Apps.Entities.Schemas .Add("schemaA1 Schema", SearchResultType.Schema, "schemaA1-url")); } + [Fact] + public async Task Should_not_add_result_to_contents_if_schema_is_component() + { + var permission = Permissions.ForApp(Permissions.AppContentsReadOwn, appId.Name, "schemaA1"); + + var ctx = ContextWithPermission(); + + var schema1 = CreateSchema("schemaA1", SchemaType.Component); + + A.CallTo(() => appProvider.GetSchemasAsync(appId.Id)) + .Returns(new List { schema1 }); + + A.CallTo(() => urlGenerator.SchemaUI(appId, schema1.NamedId())) + .Returns("schemaA1-url"); + + var result = await sut.SearchAsync("schema", ctx); + + result.Should().BeEquivalentTo( + new SearchResults() + .Add("schemaA1 Schema", SearchResultType.Schema, "schemaA1-url")); + } + [Fact] public async Task Should_return_result_to_schema_and_contents_if_matching_and_permission_given() { diff --git a/backend/tests/Squidex.Infrastructure.Tests/Collections/ImmutableListTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Collections/ImmutableListTests.cs index ffc93f598..7fa2a8401 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Collections/ImmutableListTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Collections/ImmutableListTests.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using FluentAssertions; using Squidex.Infrastructure.TestHelpers; using System.Linq; using Xunit; diff --git a/backend/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs b/backend/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs index ac7b4e13c..ae61cd8b3 100644 --- a/backend/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs +++ b/backend/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs @@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Routing; using Squidex.Domain.Apps.Entities; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Shared; using Squidex.Shared.Identity; @@ -30,6 +31,8 @@ namespace Squidex.Web private readonly ActionExecutingContext actionExecutingContext; private readonly ActionExecutionDelegate next; private readonly ClaimsIdentity user = new ClaimsIdentity(); + private readonly NamedId appId = NamedId.Of(DomainId.NewGuid(), "my-app"); + private readonly NamedId schemaId = NamedId.Of(DomainId.NewGuid(), "my-schema"); private bool isNextCalled; public ApiPermissionAttributeTests() @@ -62,7 +65,7 @@ namespace Squidex.Web [Fact] public async Task Should_make_permission_check_with_app_feature() { - actionExecutingContext.HttpContext.Features.Set(new AppFeature(NamedId.Of(DomainId.NewGuid(), "my-app"))); + actionExecutingContext.HttpContext.Features.Set(new AppFeature(Mocks.App(appId))); user.AddClaim(new Claim(SquidexClaimTypes.Permissions, "squidex.apps.my-app")); @@ -79,8 +82,8 @@ namespace Squidex.Web [Fact] public async Task Should_make_permission_check_with_schema_feature() { - actionExecutingContext.HttpContext.Features.Set(new AppFeature(NamedId.Of(DomainId.NewGuid(), "my-app"))); - actionExecutingContext.HttpContext.Features.Set(new SchemaFeature(NamedId.Of(DomainId.NewGuid(), "my-schema"))); + actionExecutingContext.HttpContext.Features.Set(new AppFeature(Mocks.App(appId))); + actionExecutingContext.HttpContext.Features.Set(new SchemaFeature(Mocks.Schema(appId, schemaId))); user.AddClaim(new Claim(SquidexClaimTypes.Permissions, "squidex.apps.my-app.schemas.my-schema")); @@ -97,7 +100,7 @@ namespace Squidex.Web [Fact] public async Task Should_return_forbidden_if_user_has_wrong_permission() { - actionExecutingContext.HttpContext.Features.Set(new AppFeature(NamedId.Of(DomainId.NewGuid(), "my-app"))); + actionExecutingContext.HttpContext.Features.Set(new AppFeature(Mocks.App(appId))); user.AddClaim(new Claim(SquidexClaimTypes.Permissions, "squidex.apps.other-app")); diff --git a/backend/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs b/backend/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs index 71d500661..9b57d9717 100644 --- a/backend/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs +++ b/backend/tests/Squidex.Web.Tests/CommandMiddlewares/EnrichWithSchemaIdCommandMiddlewareTests.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Http; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Schemas.Commands; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Web.Pipeline; @@ -29,7 +30,7 @@ namespace Squidex.Web.CommandMiddlewares public EnrichWithSchemaIdCommandMiddlewareTests() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); A.CallTo(() => httpContextAccessor.HttpContext) .Returns(httpContext); @@ -46,7 +47,7 @@ namespace Squidex.Web.CommandMiddlewares [Fact] public async Task Should_assign_schema_id_and_name_to_app_command() { - httpContext.Features.Set(new SchemaFeature(schemaId)); + httpContext.Features.Set(new SchemaFeature(Mocks.Schema(appId, schemaId))); var context = await HandleAsync(new CreateContent()); @@ -56,7 +57,7 @@ namespace Squidex.Web.CommandMiddlewares [Fact] public async Task Should_assign_schema_id_from_id() { - httpContext.Features.Set(new SchemaFeature(schemaId)); + httpContext.Features.Set(new SchemaFeature(Mocks.Schema(appId, schemaId))); var context = await HandleAsync(new UpdateSchema()); @@ -66,7 +67,7 @@ namespace Squidex.Web.CommandMiddlewares [Fact] public async Task Should_not_override_schema_id() { - httpContext.Features.Set(new SchemaFeature(schemaId)); + httpContext.Features.Set(new SchemaFeature(Mocks.Schema(appId, schemaId))); var customId = DomainId.NewGuid(); @@ -78,7 +79,7 @@ namespace Squidex.Web.CommandMiddlewares [Fact] public async Task Should_not_override_schema_id_and_name() { - httpContext.Features.Set(new SchemaFeature(schemaId)); + httpContext.Features.Set(new SchemaFeature(Mocks.Schema(appId, schemaId))); var customId = NamedId.Of(DomainId.NewGuid(), "other-app"); diff --git a/backend/tests/Squidex.Web.Tests/Pipeline/SchemaResolverTests.cs b/backend/tests/Squidex.Web.Tests/Pipeline/SchemaResolverTests.cs index e8a4c2748..3d78e59c0 100644 --- a/backend/tests/Squidex.Web.Tests/Pipeline/SchemaResolverTests.cs +++ b/backend/tests/Squidex.Web.Tests/Pipeline/SchemaResolverTests.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Routing; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.Security; using Squidex.Shared; @@ -49,7 +50,7 @@ namespace Squidex.Web.Pipeline actionExecutingContext = new ActionExecutingContext(actionContext, new List(), new Dictionary(), this); actionExecutingContext.HttpContext = httpContext; actionExecutingContext.HttpContext.User = new ClaimsPrincipal(user); - actionExecutingContext.HttpContext.Features.Set(new AppFeature(appId)); + actionExecutingContext.HttpContext.Features.Set(new AppFeature(Mocks.App(appId))); next = () => { @@ -61,34 +62,63 @@ namespace Squidex.Web.Pipeline sut = new SchemaResolver(appProvider); } + [Fact] + public async Task Should_return_not_found_if_schema_not_published_when_attribute_applied() + { + actionContext.ActionDescriptor.EndpointMetadata.Add(new SchemaMustBePublishedAttribute()); + actionContext.RouteData.Values["schema"] = schemaId.Id.ToString(); + + var schema = CreateSchema(false); + + A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A._, true)) + .Returns(schema); + + await sut.OnActionExecutionAsync(actionExecutingContext, next); + + AssetNotFound(); + } + + [Fact] + public async Task Should_resolve_schema_if_schema_not_published() + { + actionContext.RouteData.Values["schema"] = schemaId.Id.ToString(); + + var schema = CreateSchema(false); + + A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A._, true)) + .Returns(schema); + + await sut.OnActionExecutionAsync(actionExecutingContext, next); + + AssertSchema(schema); + } + [Fact] public async Task Should_return_not_found_if_schema_not_found() { - actionContext.RouteData.Values["name"] = schemaId.Id.ToString(); + actionContext.RouteData.Values["schema"] = schemaId.Id.ToString(); A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A._, true)) .Returns(Task.FromResult(null)); await sut.OnActionExecutionAsync(actionExecutingContext, next); - Assert.IsType(actionExecutingContext.Result); - Assert.False(isNextCalled); + AssetNotFound(); } [Fact] public async Task Should_resolve_schema_from_id() { - actionContext.RouteData.Values["name"] = schemaId.Id.ToString(); + actionContext.RouteData.Values["schema"] = schemaId.Id.ToString(); - var schema = CreateSchema(); + var schema = CreateSchema(true); A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Id, true)) .Returns(schema); await sut.OnActionExecutionAsync(actionExecutingContext, next); - Assert.Equal(schemaId, actionContext.HttpContext.Features.Get().SchemaId); - Assert.True(isNextCalled); + AssertSchema(schema); } [Fact] @@ -96,33 +126,31 @@ namespace Squidex.Web.Pipeline { user.AddClaim(new Claim(OpenIdClaims.ClientId, DefaultClients.Frontend)); - actionContext.RouteData.Values["name"] = schemaId.Id.ToString(); + actionContext.RouteData.Values["schema"] = schemaId.Id.ToString(); - var schema = CreateSchema(); + var schema = CreateSchema(true); A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Id, false)) .Returns(schema); await sut.OnActionExecutionAsync(actionExecutingContext, next); - Assert.Equal(schemaId, actionContext.HttpContext.Features.Get().SchemaId); - Assert.True(isNextCalled); + AssertSchema(schema); } [Fact] public async Task Should_resolve_schema_from_name() { - actionContext.RouteData.Values["name"] = schemaId.Name; + actionContext.RouteData.Values["schema"] = schemaId.Name; - var schema = CreateSchema(); + var schema = CreateSchema(true); A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Name, true)) .Returns(schema); await sut.OnActionExecutionAsync(actionExecutingContext, next); - Assert.Equal(schemaId, actionContext.HttpContext.Features.Get().SchemaId); - Assert.True(isNextCalled); + AssertSchema(schema); } [Fact] @@ -130,22 +158,24 @@ namespace Squidex.Web.Pipeline { user.AddClaim(new Claim(OpenIdClaims.ClientId, DefaultClients.Frontend)); - actionContext.RouteData.Values["name"] = schemaId.Name; + actionContext.RouteData.Values["schema"] = schemaId.Name; - var schema = CreateSchema(); + var schema = CreateSchema(true); A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Name, false)) .Returns(schema); await sut.OnActionExecutionAsync(actionExecutingContext, next); - Assert.Equal(schemaId, actionContext.HttpContext.Features.Get().SchemaId); - Assert.True(isNextCalled); + AssertSchema(schema); } [Fact] - public async Task Should_do_nothing_if_parameter_not_set() + public async Task Should_do_nothing_if_app_feature_not_set() { + actionExecutingContext.HttpContext.Features.Set(null!); + actionExecutingContext.RouteData.Values["schema"] = schemaId.Name; + await sut.OnActionExecutionAsync(actionExecutingContext, next); Assert.True(isNextCalled); @@ -155,11 +185,8 @@ namespace Squidex.Web.Pipeline } [Fact] - public async Task Should_do_nothing_if_app_feature_not_set() + public async Task Should_do_nothing_if_parameter_not_set() { - actionExecutingContext.HttpContext.Features.Set(null!); - actionExecutingContext.RouteData.Values["name"] = schemaId.Name; - await sut.OnActionExecutionAsync(actionExecutingContext, next); Assert.True(isNextCalled); @@ -168,12 +195,31 @@ namespace Squidex.Web.Pipeline .MustNotHaveHappened(); } - private ISchemaEntity CreateSchema() + private void AssetNotFound() + { + Assert.IsType(actionExecutingContext.Result); + Assert.False(isNextCalled); + } + + private void AssertSchema(ISchemaEntity schema) + { + Assert.Equal(schema, actionContext.HttpContext.Features.Get().Schema); + Assert.True(isNextCalled); + } + + private ISchemaEntity CreateSchema(bool published) { + var schema = new Schema(schemaId.Name); + + if (published) + { + schema = schema.Publish(); + } + var schemaEntity = A.Fake(); A.CallTo(() => schemaEntity.SchemaDef) - .Returns(new Schema(schemaId.Name)); + .Returns(schema); A.CallTo(() => schemaEntity.Id) .Returns(schemaId.Id); diff --git a/backend/tests/Squidex.Web.Tests/Pipeline/UsageMiddlewareTests.cs b/backend/tests/Squidex.Web.Tests/Pipeline/UsageMiddlewareTests.cs index 4c68382d0..940658ff5 100644 --- a/backend/tests/Squidex.Web.Tests/Pipeline/UsageMiddlewareTests.cs +++ b/backend/tests/Squidex.Web.Tests/Pipeline/UsageMiddlewareTests.cs @@ -12,6 +12,7 @@ using FakeItEasy; using Microsoft.AspNetCore.Http; using NodaTime; using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; using Squidex.Infrastructure.UsageTracking; using Xunit; @@ -61,7 +62,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_not_track_if_call_blocked() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(13)); httpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests; @@ -79,7 +80,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_track_if_calls_left() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(13)); await sut.InvokeAsync(httpContext, next); @@ -95,7 +96,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_track_request_bytes() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(13)); httpContext.Request.ContentLength = 1024; @@ -112,7 +113,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_track_response_bytes_with_writer() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(13)); await sut.InvokeAsync(httpContext, async x => @@ -133,7 +134,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_track_response_bytes_with_stream() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(13)); await sut.InvokeAsync(httpContext, async x => @@ -154,7 +155,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_track_response_bytes_with_file() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(13)); var tempFileName = Path.GetTempFileName(); @@ -185,7 +186,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_not_track_if_costs_are_zero() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(0)); await sut.InvokeAsync(httpContext, next); @@ -201,7 +202,7 @@ namespace Squidex.Web.Pipeline [Fact] public async Task Should_log_request_even_if_costs_are_zero() { - httpContext.Features.Set(new AppFeature(appId)); + httpContext.Features.Set(new AppFeature(Mocks.App(appId))); httpContext.Features.Set(new ApiCostsAttribute(0)); httpContext.Request.Method = "GET"; diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/SchemaTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/SchemaTests.cs index d90558495..69a986cd9 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/SchemaTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/SchemaTests.cs @@ -53,7 +53,12 @@ namespace TestSuite.ApiTests var schemaName = $"schema-{Guid.NewGuid()}"; // STEP 1: Create schema - var createRequest = new CreateSchemaDto { Name = schemaName, IsSingleton = true }; + var createRequest = new CreateSchemaDto + { + Name = schemaName, + IsSingleton = true, + IsPublished = true + }; var schema = await _.Schemas.PostSchemaAsync(_.AppName, createRequest); diff --git a/frontend/app-config/karma-test-shim.js b/frontend/app-config/karma-test-shim.js index f7d2fbbd6..f806db455 100644 --- a/frontend/app-config/karma-test-shim.js +++ b/frontend/app-config/karma-test-shim.js @@ -14,6 +14,6 @@ testing.getTestBed().initTestEnvironment( ); // Then we find all the tests. -const context = require.context('./../app', true, /\.spec\.ts$/); +const context = require.context('./../app', true, /contents\.forms\.spec\.ts$/); // And load the modules. context.keys().map(context); diff --git a/frontend/app/features/administration/state/users.state.ts b/frontend/app/features/administration/state/users.state.ts index a03d8f937..ea5fd2112 100644 --- a/frontend/app/features/administration/state/users.state.ts +++ b/frontend/app/features/administration/state/users.state.ts @@ -80,7 +80,8 @@ export class UsersState extends State { return of(found); } - return this.usersService.getUser(id).pipe(catchError(() => of(null))); + return this.usersService.getUser(id).pipe( + catchError(() => of(null))); } public load(isReload = false, update: Partial = {}): Observable { diff --git a/frontend/app/features/apps/pages/app.component.html b/frontend/app/features/apps/pages/app.component.html index e2010e10d..ad046dc81 100644 --- a/frontend/app/features/apps/pages/app.component.html +++ b/frontend/app/features/apps/pages/app.component.html @@ -24,7 +24,7 @@ - diff --git a/frontend/app/features/content/declarations.ts b/frontend/app/features/content/declarations.ts index d97edc633..ed461421f 100644 --- a/frontend/app/features/content/declarations.ts +++ b/frontend/app/features/content/declarations.ts @@ -24,7 +24,8 @@ export * from './shared/content-status.component'; export * from './shared/due-time-selector.component'; export * from './shared/forms/array-editor.component'; export * from './shared/forms/array-item.component'; -export * from './shared/forms/array-section.component'; +export * from './shared/forms/component.component'; +export * from './shared/forms/component-section.component'; export * from './shared/forms/assets-editor.component'; export * from './shared/forms/field-editor.component'; export * from './shared/forms/iframe-editor.component'; diff --git a/frontend/app/features/content/module.ts b/frontend/app/features/content/module.ts index 491776fb1..9c1f71601 100644 --- a/frontend/app/features/content/module.ts +++ b/frontend/app/features/content/module.ts @@ -9,16 +9,14 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { CanDeactivateGuard, ContentMustExistGuard, LoadLanguagesGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SqxFrameworkModule, SqxSharedModule } from '@app/shared'; -import { ArrayEditorComponent, ArrayItemComponent, ArraySectionComponent, AssetsEditorComponent, CommentsPageComponent, ContentComponent, ContentCreatorComponent, ContentEditorComponent, ContentEventComponent, ContentFieldComponent, ContentHistoryPageComponent, ContentListCellDirective, ContentListFieldComponent, ContentListHeaderComponent, ContentListWidthPipe, ContentPageComponent, ContentReferencesComponent, ContentsColumnsPipe, ContentSectionComponent, ContentSelectorComponent, ContentSelectorItemComponent, ContentsFiltersPageComponent, ContentsPageComponent, ContentStatusComponent, ContentValueComponent, ContentValueEditorComponent, CustomViewEditorComponent, DueTimeSelectorComponent, FieldEditorComponent, FieldLanguagesComponent, PreviewButtonComponent, ReferenceItemComponent, ReferencesEditorComponent, SchemasPageComponent, SidebarPageComponent, StockPhotoEditorComponent } from './declarations'; -import { ContentExtensionComponent } from './shared/content-extension.component'; -import { IFrameEditorComponent } from './shared/forms/iframe-editor.component'; +import { CanDeactivateGuard, ContentMustExistGuard, LoadLanguagesGuard, LoadSchemasGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SqxFrameworkModule, SqxSharedModule } from '@app/shared'; +import { ArrayEditorComponent, ArrayItemComponent, AssetsEditorComponent, CommentsPageComponent, ComponentComponent, ComponentSectionComponent, ContentComponent, ContentCreatorComponent, ContentEditorComponent, ContentEventComponent, ContentExtensionComponent, ContentFieldComponent, ContentHistoryPageComponent, ContentListCellDirective, ContentListFieldComponent, ContentListHeaderComponent, ContentListWidthPipe, ContentPageComponent, ContentReferencesComponent, ContentsColumnsPipe, ContentSectionComponent, ContentSelectorComponent, ContentSelectorItemComponent, ContentsFiltersPageComponent, ContentsPageComponent, ContentStatusComponent, ContentValueComponent, ContentValueEditorComponent, CustomViewEditorComponent, DueTimeSelectorComponent, FieldEditorComponent, FieldLanguagesComponent, IFrameEditorComponent, PreviewButtonComponent, ReferenceItemComponent, ReferencesEditorComponent, SchemasPageComponent, SidebarPageComponent, StockPhotoEditorComponent } from './declarations'; const routes: Routes = [ { path: '', component: SchemasPageComponent, - canActivate: [LoadLanguagesGuard], + canActivate: [LoadLanguagesGuard, LoadSchemasGuard], children: [ { path: '' @@ -86,9 +84,10 @@ const routes: Routes = [ declarations: [ ArrayEditorComponent, ArrayItemComponent, - ArraySectionComponent, AssetsEditorComponent, CommentsPageComponent, + ComponentComponent, + ComponentSectionComponent, ContentComponent, ContentCreatorComponent, ContentEditorComponent, diff --git a/frontend/app/features/content/pages/content/content-history-page.component.html b/frontend/app/features/content/pages/content/content-history-page.component.html index 9739d4c03..88cf374b1 100644 --- a/frontend/app/features/content/pages/content/content-history-page.component.html +++ b/frontend/app/features/content/pages/content/content-history-page.component.html @@ -29,7 +29,7 @@ - diff --git a/frontend/app/features/content/pages/content/content-page.component.ts b/frontend/app/features/content/pages/content/content-page.component.ts index b0266fbcd..9c8b1e4ac 100644 --- a/frontend/app/features/content/pages/content/content-page.component.ts +++ b/frontend/app/features/content/pages/content/content-page.component.ts @@ -88,7 +88,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD .subscribe(schema => { this.schema = schema; - this.contentForm = new EditContentForm(this.languages, this.schema, this.formContext); + this.contentForm = new EditContentForm(this.languages, this.schema, this.schemasState.schemaMap, this.formContext); })); this.own( @@ -252,7 +252,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD this.contentsState.loadVersion(content, version) .subscribe(dto => { if (compare) { - this.contentFormCompare = new EditContentForm(this.languages, this.schema, this.formContext); + this.contentFormCompare = new EditContentForm(this.languages, this.schema, this.schemasState.schemaMap, this.formContext); this.contentFormCompare.load(dto.payload); this.contentFormCompare.setEnabled(false); diff --git a/frontend/app/features/content/pages/schemas/schemas-page.component.ts b/frontend/app/features/content/pages/schemas/schemas-page.component.ts index da163d70a..7df1714e2 100644 --- a/frontend/app/features/content/pages/schemas/schemas-page.component.ts +++ b/frontend/app/features/content/pages/schemas/schemas-page.component.ts @@ -5,7 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { FormControl } from '@angular/forms'; import { LocalStoreService, SchemaCategory, SchemasState, Settings } from '@app/shared'; @@ -14,7 +14,7 @@ import { LocalStoreService, SchemaCategory, SchemasState, Settings } from '@app/ styleUrls: ['./schemas-page.component.scss'], templateUrl: './schemas-page.component.html' }) -export class SchemasPageComponent implements OnInit { +export class SchemasPageComponent { public schemasFilter = new FormControl(); public isCollapsed: boolean; @@ -30,10 +30,6 @@ export class SchemasPageComponent implements OnInit { this.isCollapsed = localStore.getBoolean(Settings.Local.SCHEMAS_COLLAPSED); } - public ngOnInit() { - this.schemasState.load(); - } - public toggle() { this.isCollapsed = !this.isCollapsed; diff --git a/frontend/app/features/content/shared/forms/array-editor.component.html b/frontend/app/features/content/shared/forms/array-editor.component.html index 72aecaf0e..e68f8cbe2 100644 --- a/frontend/app/features/content/shared/forms/array-editor.component.html +++ b/frontend/app/features/content/shared/forms/array-editor.component.html @@ -1,61 +1,90 @@ - - -
-
- - - -
+ +
+
+ + +
+
-
-
- - - -
- -
- - -
+
+
+ + + + + + + {{ 'contents.arrayNoFields' | sqxTranslate }} + + + + + + + + + + + + + + + + + + {{ 'contents.componentsNoSchema' | sqxTranslate }} + + +
- - - - - {{ 'contents.arrayNoFields' | sqxTranslate }} - - \ No newline at end of file +
+ +
+ +
+ + +
+
+ \ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/array-editor.component.ts b/frontend/app/features/content/shared/forms/array-editor.component.ts index 38dd64573..0fc627d82 100644 --- a/frontend/app/features/content/shared/forms/array-editor.component.ts +++ b/frontend/app/features/content/shared/forms/array-editor.component.ts @@ -7,7 +7,7 @@ import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { ChangeDetectionStrategy, Component, Input, OnChanges, QueryList, SimpleChanges, ViewChildren } from '@angular/core'; -import { AppLanguageDto, ArrayFieldPropertiesDto, disabled$, EditContentForm, FieldArrayForm, FieldArrayItemForm, sorted } from '@app/shared'; +import { AppLanguageDto, ComponentsFieldPropertiesDto, disabled$, EditContentForm, fadeAnimation, FieldArrayForm, ModalModel, ObjectForm, SchemaDto, sorted, Types } from '@app/shared'; import { combineLatest, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ArrayItemComponent } from './array-item.component'; @@ -16,7 +16,10 @@ import { ArrayItemComponent } from './array-item.component'; selector: 'sqx-array-editor', styleUrls: ['./array-editor.component.scss'], templateUrl: './array-editor.component.html', - changeDetection: ChangeDetectionStrategy.OnPush + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [ + fadeAnimation + ] }) export class ArrayEditorComponent implements OnChanges { @Input() @@ -40,23 +43,28 @@ export class ArrayEditorComponent implements OnChanges { @ViewChildren(ArrayItemComponent) public children: QueryList; + public isArray = false; + + public schemasDropdown = new ModalModel(); + public schemasList: ReadonlyArray; + public isDisabled: Observable; public isFull: Observable; - public get field() { - return this.formModel.field; - } - - public get hasFields() { - return this.field.nested.length > 0; + public get hasField() { + return this.formModel.field['nested']?.length > 0; } public ngOnChanges(changes: SimpleChanges) { if (changes['formModel']) { - const properties = this.field.properties as ArrayFieldPropertiesDto; + const maxItems = this.formModel.field.properties['maxItems'] || Number.MAX_VALUE; - const maxItems = properties.maxItems || Number.MAX_VALUE; + if (Types.is(this.formModel.field.properties, ComponentsFieldPropertiesDto)) { + this.schemasList = this.formModel.field.properties.schemaIds?.map(x => this.formModel.globals.schemas[x]).filter(x => !!x) || []; + } else { + this.isArray = true; + } this.isDisabled = disabled$(this.formModel.form); @@ -73,21 +81,29 @@ export class ArrayEditorComponent implements OnChanges { this.formModel.removeItemAt(index); } - public addItem(value?: FieldArrayItemForm) { - this.formModel.addItem(value); + public addCopy(value: ObjectForm) { + this.formModel.addCopy(value); + } + + public addItem() { + this.formModel.addItem(); + } + + public addComponent(schema: SchemaDto) { + this.formModel.addComponent(schema.id); } public clear() { this.formModel.reset(); } - public sort(event: CdkDragDrop>) { + public sort(event: CdkDragDrop>) { this.formModel.sort(sorted(event)); this.reset(); } - public move(item: FieldArrayItemForm, index: number) { + public move(item: ObjectForm, index: number) { this.formModel.move(index, item); this.reset(); diff --git a/frontend/app/features/content/shared/forms/array-item.component.html b/frontend/app/features/content/shared/forms/array-item.component.html index 2865366ee..ad2f98fd2 100644 --- a/frontend/app/features/content/shared/forms/array-item.component.html +++ b/frontend/app/features/content/shared/forms/array-item.component.html @@ -44,7 +44,7 @@
- - +
\ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/array-item.component.ts b/frontend/app/features/content/shared/forms/array-item.component.ts index 927c88c16..61b73d643 100644 --- a/frontend/app/features/content/shared/forms/array-item.component.ts +++ b/frontend/app/features/content/shared/forms/array-item.component.ts @@ -6,10 +6,10 @@ */ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, QueryList, SimpleChanges, ViewChildren } from '@angular/core'; -import { AppLanguageDto, EditContentForm, FieldArrayItemForm, FieldArrayItemValueForm, FieldFormatter, FieldSection, invalid$, NestedFieldDto, StatefulComponent, value$ } from '@app/shared'; +import { AppLanguageDto, ComponentForm, EditContentForm, FieldDto, FieldFormatter, FieldSection, invalid$, ObjectForm, RootFieldDto, StatefulComponent, Types, value$ } from '@app/shared'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { ArraySectionComponent } from './array-section.component'; +import { ComponentSectionComponent } from './component-section.component'; interface State { // The when the section is collapsed. @@ -39,7 +39,7 @@ export class ArrayItemComponent extends StatefulComponent implements OnCh public formContext: any; @Input() - public formModel: FieldArrayItemForm; + public formModel: ObjectForm; @Input() public canUnset?: boolean | null; @@ -62,8 +62,8 @@ export class ArrayItemComponent extends StatefulComponent implements OnCh @Input() public languages: ReadonlyArray; - @ViewChildren(ArraySectionComponent) - public sections: QueryList; + @ViewChildren(ComponentSectionComponent) + public sections: QueryList; public isCollapsed = false; public isInvalid: Observable; @@ -88,14 +88,20 @@ export class ArrayItemComponent extends StatefulComponent implements OnCh private getTitle(value: any) { const values: string[] = []; - for (const field of this.formModel.field.nested) { - const fieldValue = value[field.name]; + if (Types.is(this.formModel, ComponentForm) && this.formModel.schema) { + values.push(this.formModel.schema.displayName); + } + + if (Types.is(this.formModel.field, RootFieldDto)) { + for (const field of this.formModel.field.nested) { + const fieldValue = value[field.name]; - if (fieldValue) { - const formatted = FieldFormatter.format(field, fieldValue); + if (fieldValue) { + const formatted = FieldFormatter.format(field, fieldValue); - if (formatted) { - values.push(formatted); + if (formatted) { + values.push(formatted); + } } } } @@ -133,7 +139,7 @@ export class ArrayItemComponent extends StatefulComponent implements OnCh }); } - public trackBySection(_index: number, section: FieldSection) { + public trackBySection(_index: number, section: FieldSection) { return section.separator?.fieldId; } } \ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/array-section.component.html b/frontend/app/features/content/shared/forms/component-section.component.html similarity index 100% rename from frontend/app/features/content/shared/forms/array-section.component.html rename to frontend/app/features/content/shared/forms/component-section.component.html diff --git a/frontend/app/features/content/shared/forms/array-section.component.scss b/frontend/app/features/content/shared/forms/component-section.component.scss similarity index 100% rename from frontend/app/features/content/shared/forms/array-section.component.scss rename to frontend/app/features/content/shared/forms/component-section.component.scss diff --git a/frontend/app/features/content/shared/forms/array-section.component.ts b/frontend/app/features/content/shared/forms/component-section.component.ts similarity index 67% rename from frontend/app/features/content/shared/forms/array-section.component.ts rename to frontend/app/features/content/shared/forms/component-section.component.ts index 1d4de951a..aede7a160 100644 --- a/frontend/app/features/content/shared/forms/array-section.component.ts +++ b/frontend/app/features/content/shared/forms/component-section.component.ts @@ -6,16 +6,16 @@ */ import { ChangeDetectionStrategy, Component, Input, QueryList, ViewChildren } from '@angular/core'; -import { AppLanguageDto, EditContentForm, FieldArrayItemForm, FieldSection, NestedFieldDto } from '@app/shared'; +import { AbstractContentForm, AppLanguageDto, EditContentForm, FieldDto, FieldSection } from '@app/shared'; import { FieldEditorComponent } from './field-editor.component'; @Component({ - selector: 'sqx-array-section', - styleUrls: ['./array-section.component.scss'], - templateUrl: './array-section.component.html', + selector: 'sqx-component-section', + styleUrls: ['./component-section.component.scss'], + templateUrl: './component-section.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -export class ArraySectionComponent { +export class ComponentSectionComponent { @Input() public form: EditContentForm; @@ -23,7 +23,7 @@ export class ArraySectionComponent { public formContext: any; @Input() - public formSection: FieldSection; + public formSection: FieldSection; @Input() public language: AppLanguageDto; @@ -46,7 +46,7 @@ export class ArraySectionComponent { }); } - public trackByField(_index: number, field: FieldArrayItemForm) { + public trackByField(_index: number, field: AbstractContentForm) { return field.field.fieldId; } } \ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/component.component.html b/frontend/app/features/content/shared/forms/component.component.html new file mode 100644 index 000000000..ccf75e746 --- /dev/null +++ b/frontend/app/features/content/shared/forms/component.component.html @@ -0,0 +1,44 @@ +
+
+ + {{formModel.schema.displayName}} + + +
+ + +
+
+ + + + + + + + + + + + + + + {{ 'contents.componentNoSchema' | sqxTranslate }} + + + +
\ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/component.component.scss b/frontend/app/features/content/shared/forms/component.component.scss new file mode 100644 index 000000000..2acf54f71 --- /dev/null +++ b/frontend/app/features/content/shared/forms/component.component.scss @@ -0,0 +1,5 @@ +.component { + border: 1px solid $color-border; + border-radius: 4px; + padding: 1rem; +} \ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/component.component.ts b/frontend/app/features/content/shared/forms/component.component.ts new file mode 100644 index 000000000..cd58aa62c --- /dev/null +++ b/frontend/app/features/content/shared/forms/component.component.ts @@ -0,0 +1,81 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, QueryList, SimpleChanges, ViewChildren } from '@angular/core'; +import { AppLanguageDto, ComponentFieldPropertiesDto, ComponentForm, EditContentForm, fadeAnimation, FieldDto, FieldSection, ModalModel, ResourceOwner, SchemaDto, Types } from '@app/shared'; +import { ComponentSectionComponent } from './component-section.component'; + +@Component({ + selector: 'sqx-component', + styleUrls: ['./component.component.scss'], + templateUrl: './component.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + animations: [ + fadeAnimation + ] +}) +export class ComponentComponent extends ResourceOwner implements OnChanges { + @Input() + public canUnset?: boolean | null; + + @Input() + public form: EditContentForm; + + @Input() + public formContext: any; + + @Input() + public formModel: ComponentForm; + + @Input() + public language: AppLanguageDto; + + @Input() + public languages: ReadonlyArray; + + @ViewChildren(ComponentSectionComponent) + public sections: QueryList; + + public schemasDropdown = new ModalModel(); + public schemasList: ReadonlyArray; + + constructor( + private readonly changeDetector: ChangeDetectorRef + ) { + super(); + } + + public ngOnChanges(changes: SimpleChanges) { + if (changes['formModel']) { + this.unsubscribeAll(); + + this.own( + this.formModel.form.valueChanges + .subscribe(() => { + this.changeDetector.detectChanges(); + })); + + if (Types.is(this.formModel.field.properties, ComponentFieldPropertiesDto)) { + this.schemasList = this.formModel.field.properties.schemaIds?.map(x => this.formModel.globals.schemas[x]).filter(x => !!x) || []; + } + } + } + + public reset() { + this.sections.forEach(section => { + section.reset(); + }); + } + + public setSchema(schema: SchemaDto) { + this.formModel.selectSchema(schema.id); + } + + public trackBySection(_index: number, section: FieldSection) { + return section.separator?.fieldId; + } +} \ No newline at end of file diff --git a/frontend/app/features/content/shared/forms/field-editor.component.html b/frontend/app/features/content/shared/forms/field-editor.component.html index bd2431dbe..9e8e2b53a 100644 --- a/frontend/app/features/content/shared/forms/field-editor.component.html +++ b/frontend/app/features/content/shared/forms/field-editor.component.html @@ -46,6 +46,26 @@
+ + + + + + + + diff --git a/frontend/app/features/content/shared/list/content.component.html b/frontend/app/features/content/shared/list/content.component.html index ea9fb47d6..f8492bdb1 100644 --- a/frontend/app/features/content/shared/list/content.component.html +++ b/frontend/app/features/content/shared/list/content.component.html @@ -22,7 +22,7 @@ - diff --git a/frontend/app/features/content/shared/references/content-creator.component.html b/frontend/app/features/content/shared/references/content-creator.component.html index 67279c44d..7dcb4b2dc 100644 --- a/frontend/app/features/content/shared/references/content-creator.component.html +++ b/frontend/app/features/content/shared/references/content-creator.component.html @@ -3,7 +3,7 @@
diff --git a/frontend/app/features/content/shared/references/content-creator.component.ts b/frontend/app/features/content/shared/references/content-creator.component.ts index a3e9094da..e2509fd73 100644 --- a/frontend/app/features/content/shared/references/content-creator.component.ts +++ b/frontend/app/features/content/shared/references/content-creator.component.ts @@ -5,8 +5,8 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { AppLanguageDto, ComponentContentsState, ContentDto, EditContentForm, ResourceOwner, SchemaDto, SchemasState, Types } from '@app/shared'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { AppLanguageDto, ComponentContentsState, ContentDto, EditContentForm, ResourceOwner, SchemaDto, SchemasState } from '@app/shared'; @Component({ selector: 'sqx-content-creator', @@ -45,8 +45,7 @@ export class ContentCreatorComponent extends ResourceOwner implements OnInit { constructor( private readonly contentsState: ComponentContentsState, - private readonly schemasState: SchemasState, - private readonly changeDetector: ChangeDetectorRef + private readonly schemasState: SchemasState ) { super(); } @@ -63,28 +62,19 @@ export class ContentCreatorComponent extends ResourceOwner implements OnInit { this.selectSchema(selectedSchema); } - public selectSchema(selected: string | SchemaDto) { - if (Types.is(selected, SchemaDto)) { - selected = selected.id; - } - - this.schemasState.loadSchema(selected, true) - .subscribe(schema => { - if (schema) { - this.schema = schema; - - this.contentsState.schema = schema; - this.contentForm = new EditContentForm(this.languages, this.schema, { user: this.formContext.user }); + public selectSchema(schema: SchemaDto) { + this.schema = schema; - if (this.initialData) { - this.contentForm.load(this.initialData, true); + if (schema) { + this.contentsState.schema = schema; + this.contentForm = new EditContentForm(this.languages, this.schema, this.schemasState.schemaMap, { user: this.formContext.user }); - this.initialData = null; - } + if (this.initialData) { + this.contentForm.load(this.initialData, true); - this.changeDetector.markForCheck(); - } - }); + this.initialData = null; + } + } } public saveAndPublish() { diff --git a/frontend/app/features/content/shared/references/content-selector.component.ts b/frontend/app/features/content/shared/references/content-selector.component.ts index 47ac8e530..716647f3e 100644 --- a/frontend/app/features/content/shared/references/content-selector.component.ts +++ b/frontend/app/features/content/shared/references/content-selector.component.ts @@ -5,8 +5,8 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { ApiUrlConfig, AppsState, ComponentContentsState, ContentDto, LanguageDto, Query, QueryModel, queryModelFromSchema, ResourceOwner, SchemaDto, SchemasState, Types } from '@app/shared'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { ApiUrlConfig, AppsState, ComponentContentsState, ContentDto, LanguageDto, Query, QueryModel, queryModelFromSchema, ResourceOwner, SchemaDto, SchemasState } from '@app/shared'; @Component({ selector: 'sqx-content-selector', @@ -20,6 +20,9 @@ export class ContentSelectorComponent extends ResourceOwner implements OnInit { @Output() public select = new EventEmitter>(); + @Input() + public schemaName?: string | null; + @Input() public schemaIds: ReadonlyArray; @@ -48,8 +51,7 @@ export class ContentSelectorComponent extends ResourceOwner implements OnInit { public readonly appsState: AppsState, public readonly apiUrl: ApiUrlConfig, public readonly contentsState: ComponentContentsState, - public readonly schemasState: SchemasState, - private readonly changeDetector: ChangeDetectorRef + public readonly schemasState: SchemasState ) { super(); } @@ -70,24 +72,15 @@ export class ContentSelectorComponent extends ResourceOwner implements OnInit { this.selectSchema(this.schemas[0]); } - public selectSchema(selected: string | SchemaDto) { - if (Types.is(selected, SchemaDto)) { - selected = selected.id; - } - - this.schemasState.loadSchema(selected, true) - .subscribe(schema => { - if (schema) { - this.schema = schema; + public selectSchema(schema: SchemaDto) { + this.schema = schema; - this.contentsState.schema = schema; - this.contentsState.load(); + if (schema) { + this.contentsState.schema = schema; + this.contentsState.load(); - this.updateModel(); - - this.changeDetector.markForCheck(); - } - }); + this.updateModel(); + } } public reload() { diff --git a/frontend/app/features/rules/pages/rules/rule.component.html b/frontend/app/features/rules/pages/rules/rule.component.html index 5e5d1361f..c87a0f785 100644 --- a/frontend/app/features/rules/pages/rules/rule.component.html +++ b/frontend/app/features/rules/pages/rules/rule.component.html @@ -11,7 +11,7 @@
- diff --git a/frontend/app/features/schemas/declarations.ts b/frontend/app/features/schemas/declarations.ts index df2295476..b6835491b 100644 --- a/frontend/app/features/schemas/declarations.ts +++ b/frontend/app/features/schemas/declarations.ts @@ -19,6 +19,10 @@ export * from './pages/schema/fields/types/assets-ui.component'; export * from './pages/schema/fields/types/assets-validation.component'; export * from './pages/schema/fields/types/boolean-ui.component'; export * from './pages/schema/fields/types/boolean-validation.component'; +export * from './pages/schema/fields/types/component-ui.component'; +export * from './pages/schema/fields/types/component-validation.component'; +export * from './pages/schema/fields/types/components-ui.component'; +export * from './pages/schema/fields/types/components-validation.component'; export * from './pages/schema/fields/types/date-time-ui.component'; export * from './pages/schema/fields/types/date-time-validation.component'; export * from './pages/schema/fields/types/geolocation-ui.component'; diff --git a/frontend/app/features/schemas/module.ts b/frontend/app/features/schemas/module.ts index 8fe96046f..e3e4ae79a 100644 --- a/frontend/app/features/schemas/module.ts +++ b/frontend/app/features/schemas/module.ts @@ -9,18 +9,21 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { HelpComponent, SchemaMustExistGuard, SqxFrameworkModule, SqxSharedModule } from '@app/shared'; -import { ArrayValidationComponent, AssetsUIComponent, AssetsValidationComponent, BooleanUIComponent, BooleanValidationComponent, DateTimeUIComponent, DateTimeValidationComponent, FieldComponent, FieldFormCommonComponent, FieldFormComponent, FieldFormUIComponent, FieldFormValidationComponent, FieldListComponent, FieldWizardComponent, GeolocationUIComponent, GeolocationValidationComponent, JsonUIComponent, JsonValidationComponent, NumberUIComponent, NumberValidationComponent, ReferencesUIComponent, ReferencesValidationComponent, SchemaEditFormComponent, SchemaExportFormComponent, SchemaFieldRulesFormComponent, SchemaFieldsComponent, SchemaFormComponent, SchemaPageComponent, SchemaPreviewUrlsFormComponent, SchemaScriptsFormComponent, SchemasPageComponent, SchemaUIFormComponent, StringUIComponent, StringValidationComponent, TagsUIComponent, TagsValidationComponent } from './declarations'; +import { HelpComponent, LoadSchemasGuard, SchemaMustExistGuard, SqxFrameworkModule, SqxSharedModule } from '@app/shared'; +import { ArrayValidationComponent, AssetsUIComponent, AssetsValidationComponent, BooleanUIComponent, BooleanValidationComponent, ComponentsUIComponent, ComponentsValidationComponent, DateTimeUIComponent, DateTimeValidationComponent, FieldComponent, FieldFormCommonComponent, FieldFormComponent, FieldFormUIComponent, FieldFormValidationComponent, FieldListComponent, FieldWizardComponent, GeolocationUIComponent, GeolocationValidationComponent, JsonUIComponent, JsonValidationComponent, NumberUIComponent, NumberValidationComponent, ReferencesUIComponent, ReferencesValidationComponent, SchemaEditFormComponent, SchemaExportFormComponent, SchemaFieldRulesFormComponent, SchemaFieldsComponent, SchemaFormComponent, SchemaPageComponent, SchemaPreviewUrlsFormComponent, SchemaScriptsFormComponent, SchemasPageComponent, SchemaUIFormComponent, StringUIComponent, StringValidationComponent, TagsUIComponent, TagsValidationComponent } from './declarations'; +import { ComponentUIComponent } from './pages/schema/fields/types/component-ui.component'; +import { ComponentValidationComponent } from './pages/schema/fields/types/component-validation.component'; const routes: Routes = [ { path: '', component: SchemasPageComponent, + canActivate: [LoadSchemasGuard], children: [ { path: ':schemaName', - canActivate: [SchemaMustExistGuard], component: SchemaPageComponent, + canActivate: [SchemaMustExistGuard], children: [ { path: 'help', @@ -50,6 +53,10 @@ const routes: Routes = [ AssetsValidationComponent, BooleanUIComponent, BooleanValidationComponent, + ComponentUIComponent, + ComponentValidationComponent, + ComponentsUIComponent, + ComponentsValidationComponent, DateTimeUIComponent, DateTimeValidationComponent, FieldComponent, diff --git a/frontend/app/features/schemas/pages/schema/fields/field.component.html b/frontend/app/features/schemas/pages/schema/fields/field.component.html index 718a9c0d8..6429ecc85 100644 --- a/frontend/app/features/schemas/pages/schema/fields/field.component.html +++ b/frontend/app/features/schemas/pages/schema/fields/field.component.html @@ -4,7 +4,7 @@ -
+
@@ -41,7 +41,7 @@ - diff --git a/frontend/app/features/schemas/pages/schema/fields/forms/field-form-ui.component.html b/frontend/app/features/schemas/pages/schema/fields/forms/field-form-ui.component.html index 7cbbfca1a..b7fb8b2ae 100644 --- a/frontend/app/features/schemas/pages/schema/fields/forms/field-form-ui.component.html +++ b/frontend/app/features/schemas/pages/schema/fields/forms/field-form-ui.component.html @@ -19,6 +19,12 @@ + + + + + + diff --git a/frontend/app/features/schemas/pages/schema/fields/forms/field-form-validation.component.html b/frontend/app/features/schemas/pages/schema/fields/forms/field-form-validation.component.html index d020c4a07..dea53a959 100644 --- a/frontend/app/features/schemas/pages/schema/fields/forms/field-form-validation.component.html +++ b/frontend/app/features/schemas/pages/schema/fields/forms/field-form-validation.component.html @@ -39,23 +39,37 @@ [properties]="field.rawProperties"> - - + - + - - + + + + + + + + + - + +
+ + +
+ + +
+
+
+ diff --git a/frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.scss b/frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.scss new file mode 100644 index 000000000..85f6907b7 --- /dev/null +++ b/frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.scss @@ -0,0 +1,5 @@ +.minmax { + text-align: center; + text-decoration: none; + width: 2rem; +} \ No newline at end of file diff --git a/frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.ts b/frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.ts new file mode 100644 index 000000000..e3414b966 --- /dev/null +++ b/frontend/app/features/schemas/pages/schema/fields/types/component-validation.component.ts @@ -0,0 +1,31 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { Component, Input } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { FieldDto, ReferencesFieldPropertiesDto, SchemaTagSource } from '@app/shared'; + +@Component({ + selector: 'sqx-component-validation', + styleUrls: ['component-validation.component.scss'], + templateUrl: 'component-validation.component.html' +}) +export class ComponentValidationComponent { + @Input() + public fieldForm: FormGroup; + + @Input() + public field: FieldDto; + + @Input() + public properties: ReferencesFieldPropertiesDto; + + constructor( + public readonly schemasSource: SchemaTagSource + ) { + } +} \ No newline at end of file diff --git a/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.html b/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.html new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.scss b/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.ts b/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.ts new file mode 100644 index 000000000..f14f070d0 --- /dev/null +++ b/frontend/app/features/schemas/pages/schema/fields/types/components-ui.component.ts @@ -0,0 +1,26 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { Component, Input } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { FieldDto, ReferencesFieldPropertiesDto } from '@app/shared'; + +@Component({ + selector: 'sqx-components-ui', + styleUrls: ['components-ui.component.scss'], + templateUrl: 'components-ui.component.html' +}) +export class ComponentsUIComponent { + @Input() + public fieldForm: FormGroup; + + @Input() + public field: FieldDto; + + @Input() + public properties: ReferencesFieldPropertiesDto; +} \ No newline at end of file diff --git a/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.html b/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.html new file mode 100644 index 000000000..dfb4274d8 --- /dev/null +++ b/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.html @@ -0,0 +1,30 @@ +
+
+ + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+ + +
+ + +
+
+
+ diff --git a/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.scss b/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.scss new file mode 100644 index 000000000..85f6907b7 --- /dev/null +++ b/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.scss @@ -0,0 +1,5 @@ +.minmax { + text-align: center; + text-decoration: none; + width: 2rem; +} \ No newline at end of file diff --git a/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.ts b/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.ts new file mode 100644 index 000000000..0739e9485 --- /dev/null +++ b/frontend/app/features/schemas/pages/schema/fields/types/components-validation.component.ts @@ -0,0 +1,31 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { Component, Input } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { FieldDto, ReferencesFieldPropertiesDto, SchemaTagSource } from '@app/shared'; + +@Component({ + selector: 'sqx-components-validation', + styleUrls: ['components-validation.component.scss'], + templateUrl: 'components-validation.component.html' +}) +export class ComponentsValidationComponent { + @Input() + public fieldForm: FormGroup; + + @Input() + public field: FieldDto; + + @Input() + public properties: ReferencesFieldPropertiesDto; + + constructor( + public readonly schemasSource: SchemaTagSource + ) { + } +} \ No newline at end of file diff --git a/frontend/app/features/schemas/pages/schema/schema-page.component.html b/frontend/app/features/schemas/pages/schema/schema-page.component.html index ed70e9a74..be35efdc2 100644 --- a/frontend/app/features/schemas/pages/schema/schema-page.component.html +++ b/frontend/app/features/schemas/pages/schema/schema-page.component.html @@ -41,7 +41,7 @@
- diff --git a/frontend/app/features/schemas/pages/schemas/schema-form.component.html b/frontend/app/features/schemas/pages/schemas/schema-form.component.html index 320a4a755..a3328eeb5 100644 --- a/frontend/app/features/schemas/pages/schemas/schema-form.component.html +++ b/frontend/app/features/schemas/pages/schemas/schema-form.component.html @@ -62,6 +62,23 @@
+
+ +
diff --git a/frontend/app/features/schemas/pages/schemas/schemas-page.component.html b/frontend/app/features/schemas/pages/schemas/schemas-page.component.html index 0397486f5..47ecafbdc 100644 --- a/frontend/app/features/schemas/pages/schemas/schemas-page.component.html +++ b/frontend/app/features/schemas/pages/schemas/schemas-page.component.html @@ -28,7 +28,7 @@ + (remove)="removeCategory(category.displayName)"> diff --git a/frontend/app/features/schemas/pages/schemas/schemas-page.component.ts b/frontend/app/features/schemas/pages/schemas/schemas-page.component.ts index 7416c90d6..092956456 100644 --- a/frontend/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/frontend/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -38,8 +38,8 @@ export class SchemasPageComponent extends ResourceOwner implements OnInit { public ngOnInit() { this.own( this.messageBus.of(SchemaCloning) - .subscribe(m => { - this.import = m.schema; + .subscribe(event => { + this.import = event.schema; this.addSchemaDialog.show(); })); @@ -51,8 +51,6 @@ export class SchemasPageComponent extends ResourceOwner implements OnInit { this.addSchemaDialog.show(); } })); - - this.schemasState.load(); } public removeCategory(name: string) { diff --git a/frontend/app/features/settings/pages/clients/client-connect-form.component.html b/frontend/app/features/settings/pages/clients/client-connect-form.component.html index f47ab8b16..cc6009436 100644 --- a/frontend/app/features/settings/pages/clients/client-connect-form.component.html +++ b/frontend/app/features/settings/pages/clients/client-connect-form.component.html @@ -41,7 +41,7 @@
{{ 'clients.connectWizard.manually' | sqxTranslate }}
- {{ 'clients.connectWizard.manuallyHint' | sqxTranslate }} + {{ 'clients.connectWizard.manuallyHint' | sqxTranslate }}
@@ -49,7 +49,7 @@
{{ 'clients.connectWizard.cli' | sqxTranslate }}
- {{ 'clients.connectWizard.cliHint' | sqxTranslate }} + {{ 'clients.connectWizard.cliHint' | sqxTranslate }}
@@ -57,7 +57,7 @@
{{ 'clients.connectWizard.sdk' | sqxTranslate }}
- {{ 'clients.connectWizard.sdkHint' | sqxTranslate }} + {{ 'clients.connectWizard.sdkHint' | sqxTranslate }}
diff --git a/frontend/app/features/settings/pages/plans/plan.component.html b/frontend/app/features/settings/pages/plans/plan.component.html index ccf78ad74..815da8fb7 100644 --- a/frontend/app/features/settings/pages/plans/plan.component.html +++ b/frontend/app/features/settings/pages/plans/plan.component.html @@ -3,7 +3,7 @@

{{planInfo.plan.name}}

{{planInfo.plan.costs}}
- {{ 'plans.perMonth' | sqxTranslate }} + {{ 'plans.perMonth' | sqxTranslate }}
@@ -38,7 +38,7 @@
{{planInfo.plan.yearlyCosts}}
- {{ 'plans.perYear' | sqxTranslate }} + {{ 'plans.perYear' | sqxTranslate }}
- diff --git a/frontend/app/shared/components/schema-category.component.html b/frontend/app/shared/components/schema-category.component.html index 1021681a9..67d86a2f9 100644 --- a/frontend/app/shared/components/schema-category.component.html +++ b/frontend/app/shared/components/schema-category.component.html @@ -13,12 +13,7 @@

- - {{schemaCategory.name}} - - - {{ 'common.schemas' | sqxTranslate }} - + {{schemaCategory.displayName | sqxTranslate}}

diff --git a/frontend/app/shared/components/schema-category.component.ts b/frontend/app/shared/components/schema-category.component.ts index 0cf145d7c..62400628f 100644 --- a/frontend/app/shared/components/schema-category.component.ts +++ b/frontend/app/shared/components/schema-category.component.ts @@ -1,3 +1,4 @@ + /* * Squidex Headless CMS * @@ -58,7 +59,7 @@ export class SchemaCategoryComponent implements OnChanges { if (this.forContent) { const app = this.appsState.snapshot.selectedApp!; - this.filteredSchemas = this.filteredSchemas.filter(x => x.canReadContents && x.isPublished); + this.filteredSchemas = this.filteredSchemas.filter(x => x.canReadContents && x.isPublished && x.type !== 'Component'); this.filteredSchemas = this.filteredSchemas.filter(x => !app.roleProperties[Settings.AppProperties.HIDE_CONTENTS(x.name)]); } @@ -72,7 +73,7 @@ export class SchemaCategoryComponent implements OnChanges { } public schemaRoute(schema: SchemaDto) { - if (schema.isSingleton && this.forContent) { + if (schema.type === 'Singleton' && this.forContent) { return [schema.name, schema.id, 'history']; } else { return [schema.name]; diff --git a/frontend/app/shared/components/search/queries/query-path.component.html b/frontend/app/shared/components/search/queries/query-path.component.html index 0f1d17e8c..d4538e7ac 100644 --- a/frontend/app/shared/components/search/queries/query-path.component.html +++ b/frontend/app/shared/components/search/queries/query-path.component.html @@ -8,7 +8,7 @@
{{model.fields[field].displayName}}
- {{model.fields[field].description | sqxTranslate: model.fields[field]}} + {{model.fields[field].description | sqxTranslate: model.fields[field]}}
diff --git a/frontend/app/shared/declarations.ts b/frontend/app/shared/declarations.ts index 384f4b2fd..77065e55f 100644 --- a/frontend/app/shared/declarations.ts +++ b/frontend/app/shared/declarations.ts @@ -8,8 +8,8 @@ export * from './components/app-form.component'; export * from './components/assets/asset-dialog.component'; export * from './components/assets/asset-folder-dialog.component'; -export * from './components/assets/asset-folder.component'; export * from './components/assets/asset-folder-dropdown.component'; +export * from './components/assets/asset-folder.component'; export * from './components/assets/asset-history.component'; export * from './components/assets/asset-path.component'; export * from './components/assets/asset-text-editor.component'; @@ -51,6 +51,7 @@ export * from './guards/app-must-exist.guard'; export * from './guards/content-must-exist.guard'; export * from './guards/load-apps.guard'; export * from './guards/load-languages.guard'; +export * from './guards/load-schemas.guard'; export * from './guards/must-be-authenticated.guard'; export * from './guards/must-be-not-authenticated.guard'; export * from './guards/rule-must-exist.guard'; diff --git a/frontend/app/shared/guards/load-schemas.guard.spec.ts b/frontend/app/shared/guards/load-schemas.guard.spec.ts new file mode 100644 index 000000000..5168c79b0 --- /dev/null +++ b/frontend/app/shared/guards/load-schemas.guard.spec.ts @@ -0,0 +1,36 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { SchemasState } from '@app/shared'; +import { of } from 'rxjs'; +import { IMock, Mock, Times } from 'typemoq'; +import { LoadSchemasGuard } from './load-schemas.guard'; + +describe('LoadSchemasGuard', () => { + let schemasState: IMock; + let schemaGuard: LoadSchemasGuard; + + beforeEach(() => { + schemasState = Mock.ofType(); + schemaGuard = new LoadSchemasGuard(schemasState.object); + }); + + it('should load schemas', () => { + schemasState.setup(x => x.load()) + .returns(() => of(null)); + + let result = false; + + schemaGuard.canActivate().subscribe(value => { + result = value; + }); + + expect(result).toBeTruthy(); + + schemasState.verify(x => x.load(), Times.once()); + }); +}); \ No newline at end of file diff --git a/frontend/app/shared/guards/load-schemas.guard.ts b/frontend/app/shared/guards/load-schemas.guard.ts new file mode 100644 index 000000000..d06eef3ff --- /dev/null +++ b/frontend/app/shared/guards/load-schemas.guard.ts @@ -0,0 +1,24 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { Injectable } from '@angular/core'; +import { CanActivate } from '@angular/router'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { SchemasState } from './../state/schemas.state'; + +@Injectable() +export class LoadSchemasGuard implements CanActivate { + constructor( + private readonly schemasState: SchemasState + ) { + } + + public canActivate(): Observable { + return this.schemasState.load().pipe(map(_ => true)); + } +} \ No newline at end of file diff --git a/frontend/app/shared/guards/schema-must-exist-published.guard.spec.ts b/frontend/app/shared/guards/schema-must-exist-published.guard.spec.ts index d12864e6b..e76b537d5 100644 --- a/frontend/app/shared/guards/schema-must-exist-published.guard.spec.ts +++ b/frontend/app/shared/guards/schema-must-exist-published.guard.spec.ts @@ -28,7 +28,7 @@ describe('SchemaMustExistPublishedGuard', () => { schemaGuard = new SchemaMustExistPublishedGuard(schemasState.object, router.object); }); - it('should load schema and return true if found', () => { + it('should load schema and return true if published', () => { schemasState.setup(x => x.select('123')) .returns(() => of({ isPublished: true })); @@ -43,9 +43,39 @@ describe('SchemaMustExistPublishedGuard', () => { router.verify(x => x.navigate(It.isAny()), Times.never()); }); + it('should load schema and return false if component', () => { + schemasState.setup(x => x.select('123')) + .returns(() => of({ isPublished: true, type: 'Component' })); + + let result: boolean; + + schemaGuard.canActivate(route).subscribe(x => { + result = x; + }).unsubscribe(); + + expect(result!).toBeFalsy(); + + router.verify(x => x.navigate(['/404']), Times.once()); + }); + it('should load schema and return false if not found', () => { schemasState.setup(x => x.select('123')) - .returns(() => of({ isPublished: false })); + .returns(() => of(null)); + + let result: boolean; + + schemaGuard.canActivate(route).subscribe(x => { + result = x; + }).unsubscribe(); + + expect(result!).toBeFalsy(); + + router.verify(x => x.navigate(['/404']), Times.once()); + }); + + it('should load schema and return false if not published', () => { + schemasState.setup(x => x.select('123')) + .returns(() => of({ isPublished: false, type: 'Default' })); let result: boolean; diff --git a/frontend/app/shared/guards/schema-must-exist-published.guard.ts b/frontend/app/shared/guards/schema-must-exist-published.guard.ts index 279140bf0..0d8f2bf23 100644 --- a/frontend/app/shared/guards/schema-must-exist-published.guard.ts +++ b/frontend/app/shared/guards/schema-must-exist-published.guard.ts @@ -26,11 +26,11 @@ export class SchemaMustExistPublishedGuard implements CanActivate { const result = this.schemasState.select(schemaName).pipe( tap(schema => { - if (!schema || !schema.isPublished) { + if (!schema || !schema.isPublished || schema.type === 'Component') { this.router.navigate(['/404']); } }), - map(schema => !!schema && schema.isPublished)); + map(schema => schema?.isPublished === true && schema.type !== 'Component')); return result; } diff --git a/frontend/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts b/frontend/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts index aa555b9bb..74adbb825 100644 --- a/frontend/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts +++ b/frontend/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts @@ -33,11 +33,11 @@ describe('SchemaMustNotBeSingletonGuard', () => { schemaGuard = new SchemaMustNotBeSingletonGuard(schemasState.object, router.object); }); - it('should subscribe to schema and return true if not singleton', () => { + it('should subscribe to schema and return true if default', () => { const state: RouterStateSnapshot = { url: 'schemas/name/' }; schemasState.setup(x => x.selectedSchema) - .returns(() => of({ id: '123', isSingleton: false })); + .returns(() => of({ id: '123', type: 'Default' })); let result: boolean; @@ -54,7 +54,7 @@ describe('SchemaMustNotBeSingletonGuard', () => { const state: RouterStateSnapshot = { url: 'schemas/name/' }; schemasState.setup(x => x.selectedSchema) - .returns(() => of({ id: '123', isSingleton: true })); + .returns(() => of({ id: '123', type: 'Singleton' })); let result: boolean; @@ -71,7 +71,7 @@ describe('SchemaMustNotBeSingletonGuard', () => { const state: RouterStateSnapshot = { url: 'schemas/name/new/' }; schemasState.setup(x => x.selectedSchema) - .returns(() => of({ id: '123', isSingleton: true })); + .returns(() => of({ id: '123', type: 'Singleton' })); let result: boolean; diff --git a/frontend/app/shared/guards/schema-must-not-be-singleton.guard.ts b/frontend/app/shared/guards/schema-must-not-be-singleton.guard.ts index a5688f9ac..c6487d5ad 100644 --- a/frontend/app/shared/guards/schema-must-not-be-singleton.guard.ts +++ b/frontend/app/shared/guards/schema-must-not-be-singleton.guard.ts @@ -26,7 +26,7 @@ export class SchemaMustNotBeSingletonGuard implements CanActivate { defined(), take(1), tap(schema => { - if (schema.isSingleton) { + if (schema.type === 'Singleton') { if (state.url.indexOf('/new') >= 0) { const parentUrl = state.url.slice(0, state.url.indexOf(route.url[route.url.length - 1].path)); @@ -36,7 +36,7 @@ export class SchemaMustNotBeSingletonGuard implements CanActivate { } } }), - map(schema => !schema.isSingleton)); + map(schema => schema.type === 'Default')); return result; } diff --git a/frontend/app/shared/module.ts b/frontend/app/shared/module.ts index 0108ccee3..ffec3fc80 100644 --- a/frontend/app/shared/module.ts +++ b/frontend/app/shared/module.ts @@ -14,7 +14,7 @@ import { RouterModule } from '@angular/router'; import { SqxFrameworkModule } from '@app/framework'; import { MentionModule } from 'angular-mentions'; import { NgxDocViewerModule } from 'ngx-doc-viewer'; -import { AppFormComponent, AppLanguagesService, AppMustExistGuard, AppsService, AppsState, AssetComponent, AssetDialogComponent, AssetFolderComponent, AssetFolderDialogComponent, AssetFolderDropdownComponent, AssetHistoryComponent, AssetPathComponent, AssetPreviewUrlPipe, AssetsListComponent, AssetsSelectorComponent, AssetsService, AssetsState, AssetTextEditorComponent, AssetUploaderComponent, AssetUploaderState, AssetUrlPipe, AuthInterceptor, AuthService, AutoSaveService, BackupsService, BackupsState, ClientsService, ClientsState, CommentComponent, CommentsComponent, CommentsService, ContentMustExistGuard, ContentsService, ContentsState, ContributorsService, ContributorsState, FileIconPipe, FilterComparisonComponent, FilterLogicalComponent, FilterNodeComponent, GeolocationEditorComponent, GraphQlService, HelpComponent, HelpMarkdownPipe, HelpService, HistoryComponent, HistoryListComponent, HistoryMessagePipe, HistoryService, ImageCropperComponent, ImageFocusPointComponent, LanguagesService, LanguagesState, LoadAppsGuard, LoadLanguagesGuard, MarkdownEditorComponent, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, NewsService, NotifoComponent, PlansService, PlansState, PreviewableType, QueryComponent, QueryListComponent, QueryPathComponent, ReferencesCheckboxesComponent, ReferencesDropdownComponent, ReferencesTagsComponent, RichEditorComponent, RolesService, RolesState, RuleEventsState, RuleMustExistGuard, RuleSimulatorState, RulesService, RulesState, SavedQueriesComponent, SchemaCategoryComponent, SchemaMustExistGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SchemasService, SchemasState, SchemaTagSource, SearchFormComponent, SearchService, SortingComponent, StockPhotoService, TableHeaderComponent, TranslationsService, UIService, UIState, UnsetAppGuard, UsagesService, UserDtoPicture, UserIdPicturePipe, UserNamePipe, UserNameRefPipe, UserPicturePipe, UserPictureRefPipe, UsersProviderService, UsersService, WorkflowsService, WorkflowsState } from './declarations'; +import { AppFormComponent, AppLanguagesService, AppMustExistGuard, AppsService, AppsState, AssetComponent, AssetDialogComponent, AssetFolderComponent, AssetFolderDialogComponent, AssetFolderDropdownComponent, AssetHistoryComponent, AssetPathComponent, AssetPreviewUrlPipe, AssetsListComponent, AssetsSelectorComponent, AssetsService, AssetsState, AssetTextEditorComponent, AssetUploaderComponent, AssetUploaderState, AssetUrlPipe, AuthInterceptor, AuthService, AutoSaveService, BackupsService, BackupsState, ClientsService, ClientsState, CommentComponent, CommentsComponent, CommentsService, ContentMustExistGuard, ContentsService, ContentsState, ContributorsService, ContributorsState, FileIconPipe, FilterComparisonComponent, FilterLogicalComponent, FilterNodeComponent, GeolocationEditorComponent, GraphQlService, HelpComponent, HelpMarkdownPipe, HelpService, HistoryComponent, HistoryListComponent, HistoryMessagePipe, HistoryService, ImageCropperComponent, ImageFocusPointComponent, LanguagesService, LanguagesState, LoadAppsGuard, LoadLanguagesGuard, LoadSchemasGuard, MarkdownEditorComponent, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, NewsService, NotifoComponent, PlansService, PlansState, PreviewableType, QueryComponent, QueryListComponent, QueryPathComponent, ReferencesCheckboxesComponent, ReferencesDropdownComponent, ReferencesTagsComponent, RichEditorComponent, RolesService, RolesState, RuleEventsState, RuleMustExistGuard, RuleSimulatorState, RulesService, RulesState, SavedQueriesComponent, SchemaCategoryComponent, SchemaMustExistGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SchemasService, SchemasState, SchemaTagSource, SearchFormComponent, SearchService, SortingComponent, StockPhotoService, TableHeaderComponent, TranslationsService, UIService, UIState, UnsetAppGuard, UsagesService, UserDtoPicture, UserIdPicturePipe, UserNamePipe, UserNameRefPipe, UserPicturePipe, UserPictureRefPipe, UsersProviderService, UsersService, WorkflowsService, WorkflowsState } from './declarations'; @NgModule({ imports: [ @@ -150,6 +150,7 @@ export class SqxSharedModule { LanguagesState, LoadAppsGuard, LoadLanguagesGuard, + LoadSchemasGuard, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, NewsService, diff --git a/frontend/app/shared/services/schemas.service.spec.ts b/frontend/app/shared/services/schemas.service.spec.ts index 33e787618..74cf48098 100644 --- a/frontend/app/shared/services/schemas.service.spec.ts +++ b/frontend/app/shared/services/schemas.service.spec.ts @@ -703,7 +703,7 @@ describe('SchemasService', () => { isDisabled: true, partitioning: 'language', properties: { - fieldType: 'DateTime' + fieldType: 'Component' }, _links: {} }, @@ -715,7 +715,7 @@ describe('SchemasService', () => { isDisabled: true, partitioning: 'language', properties: { - fieldType: 'Geolocation' + fieldType: 'Components' }, _links: {} }, @@ -727,7 +727,7 @@ describe('SchemasService', () => { isDisabled: true, partitioning: 'language', properties: { - fieldType: 'Json' + fieldType: 'DateTime' }, _links: {} }, @@ -739,7 +739,7 @@ describe('SchemasService', () => { isDisabled: true, partitioning: 'language', properties: { - fieldType: 'Number' + fieldType: 'Geolocation' }, _links: {} }, @@ -751,7 +751,7 @@ describe('SchemasService', () => { isDisabled: true, partitioning: 'language', properties: { - fieldType: 'References' + fieldType: 'Json' }, _links: {} }, @@ -763,7 +763,7 @@ describe('SchemasService', () => { isDisabled: true, partitioning: 'language', properties: { - fieldType: 'String' + fieldType: 'Number' }, _links: {} }, @@ -774,6 +774,30 @@ describe('SchemasService', () => { isHidden: true, isDisabled: true, partitioning: 'language', + properties: { + fieldType: 'References' + }, + _links: {} + }, + { + fieldId: 21, + name: 'field21', + isLocked: true, + isHidden: true, + isDisabled: true, + partitioning: 'language', + properties: { + fieldType: 'String' + }, + _links: {} + }, + { + fieldId: 22, + name: 'field22', + isLocked: true, + isHidden: true, + isDisabled: true, + partitioning: 'language', properties: { fieldType: 'Tags' }, @@ -840,13 +864,15 @@ export function createSchema(id: number, suffix = '') { ]), new RootFieldDto({}, 12, 'field12', createProperties('Assets'), 'language', true, true, true), new RootFieldDto({}, 13, 'field13', createProperties('Boolean'), 'language', true, true, true), - new RootFieldDto({}, 14, 'field14', createProperties('DateTime'), 'language', true, true, true), - new RootFieldDto({}, 15, 'field15', createProperties('Geolocation'), 'language', true, true, true), - new RootFieldDto({}, 16, 'field16', createProperties('Json'), 'language', true, true, true), - new RootFieldDto({}, 17, 'field17', createProperties('Number'), 'language', true, true, true), - new RootFieldDto({}, 18, 'field18', createProperties('References'), 'language', true, true, true), - new RootFieldDto({}, 19, 'field19', createProperties('String'), 'language', true, true, true), - new RootFieldDto({}, 20, 'field20', createProperties('Tags'), 'language', true, true, true) + new RootFieldDto({}, 14, 'field14', createProperties('Component'), 'language', true, true, true), + new RootFieldDto({}, 15, 'field15', createProperties('Components'), 'language', true, true, true), + new RootFieldDto({}, 16, 'field16', createProperties('DateTime'), 'language', true, true, true), + new RootFieldDto({}, 17, 'field17', createProperties('Geolocation'), 'language', true, true, true), + new RootFieldDto({}, 18, 'field18', createProperties('Json'), 'language', true, true, true), + new RootFieldDto({}, 19, 'field19', createProperties('Number'), 'language', true, true, true), + new RootFieldDto({}, 20, 'field20', createProperties('References'), 'language', true, true, true), + new RootFieldDto({}, 21, 'field21', createProperties('String'), 'language', true, true, true), + new RootFieldDto({}, 22, 'field22', createProperties('Tags'), 'language', true, true, true) ], ['field1'], ['field1'], diff --git a/frontend/app/shared/services/schemas.service.ts b/frontend/app/shared/services/schemas.service.ts index ae730a488..70702f88c 100644 --- a/frontend/app/shared/services/schemas.service.ts +++ b/frontend/app/shared/services/schemas.service.ts @@ -28,7 +28,7 @@ export const MetaFields = { version: 'meta.version' }; -export type SchemaType = 'Default' | 'Singleton'; +export type SchemaType = 'Default' | 'Singleton' | 'Component'; export class SchemaDto { public readonly _links: ResourceLinks; @@ -57,9 +57,6 @@ export class SchemaDto { public readonly defaultListFields: ReadonlyArray; public readonly defaultReferenceFields: ReadonlyArray; - public readonly isSingleton: boolean; - public readonly isDefault: boolean; - constructor(links: ResourceLinks, public readonly id: string, public readonly created: DateTime, @@ -100,9 +97,6 @@ export class SchemaDto { this.displayName = StringHelper.firstNonEmpty(this.properties.label, this.name); - this.isDefault = type === 'Default'; - this.isSingleton = type === 'Singleton'; - if (fields) { this.contentFields = fields.filter(x => x.properties.isContentField); @@ -267,10 +261,6 @@ export class RootFieldDto extends FieldDto { return this.partitioning === 'language'; } - public get isArray() { - return this.properties.fieldType === 'Array'; - } - constructor(links: ResourceLinks, fieldId: number, name: string, properties: FieldPropertiesDto, public readonly partitioning: string, isLocked: boolean = false, diff --git a/frontend/app/shared/services/schemas.types.ts b/frontend/app/shared/services/schemas.types.ts index 24f4468af..3f00a62e6 100644 --- a/frontend/app/shared/services/schemas.types.ts +++ b/frontend/app/shared/services/schemas.types.ts @@ -9,6 +9,8 @@ export type FieldType = 'Array' | 'Assets' | 'Boolean' | + 'Component' | + 'Components' | 'DateTime' | 'Json' | 'Geolocation' | @@ -28,6 +30,12 @@ export const fieldTypes: ReadonlyArray<{ type: FieldType, description: string }> }, { type: 'Boolean', description: 'i18n:schemas.fieldTypes.boolean.description' + }, { + type: 'Component', + description: 'i18n:schemas.fieldTypes.component.description' + }, { + type: 'Components', + description: 'i18n:schemas.fieldTypes.components.description' }, { type: 'DateTime', description: 'i18n:schemas.fieldTypes.dateTime.description' @@ -70,6 +78,12 @@ export function createProperties(fieldType: FieldType, values?: any): FieldPrope case 'Boolean': properties = new BooleanFieldPropertiesDto(); break; + case 'Component': + properties = new ComponentFieldPropertiesDto(); + break; + case 'Components': + properties = new ComponentsFieldPropertiesDto(); + break; case 'DateTime': properties = new DateTimeFieldPropertiesDto(); break; @@ -112,6 +126,10 @@ export interface FieldPropertiesVisitor { visitBoolean(properties: BooleanFieldPropertiesDto): T; + visitComponent(properties: ComponentFieldPropertiesDto): T; + + visitComponents(properties: ComponentsFieldPropertiesDto): T; + visitDateTime(properties: DateTimeFieldPropertiesDto): T; visitGeolocation(properties: GeolocationFieldPropertiesDto): T; @@ -232,6 +250,36 @@ export class BooleanFieldPropertiesDto extends FieldPropertiesDto { } } +export class ComponentFieldPropertiesDto extends FieldPropertiesDto { + public readonly fieldType = 'Component'; + + public readonly schemaIds?: ReadonlyArray; + + public get isComplexUI() { + return true; + } + + public accept(visitor: FieldPropertiesVisitor): T { + return visitor.visitComponent(this); + } +} + +export class ComponentsFieldPropertiesDto extends FieldPropertiesDto { + public readonly fieldType = 'Components'; + + public readonly schemaIds?: ReadonlyArray; + public readonly maxItems?: number; + public readonly minItems?: number; + + public get isComplexUI() { + return true; + } + + public accept(visitor: FieldPropertiesVisitor): T { + return visitor.visitComponents(this); + } +} + export type DateTimeFieldEditor = 'DateTime' | 'Date'; export const DATETIME_FIELD_EDITORS: ReadonlyArray = [ diff --git a/frontend/app/shared/state/contents.forms-helpers.ts b/frontend/app/shared/state/contents.forms-helpers.ts index 2b7cc64c3..44e72cb48 100644 --- a/frontend/app/shared/state/contents.forms-helpers.ts +++ b/frontend/app/shared/state/contents.forms-helpers.ts @@ -9,7 +9,7 @@ import { AbstractControl, ValidatorFn } from '@angular/forms'; import { BehaviorSubject, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { AppLanguageDto } from './../services/app-languages.service'; -import { FieldDto, FieldRule, RootFieldDto } from './../services/schemas.service'; +import { FieldDto, FieldRule, RootFieldDto, SchemaDto } from './../services/schemas.service'; import { fieldInvariant } from './../services/schemas.types'; export abstract class Hidden { @@ -37,8 +37,7 @@ export abstract class Hidden { export class FieldSection extends Hidden { constructor( public readonly separator: TSeparator | undefined, - public readonly fields: ReadonlyArray, - public readonly remoteValidator?: ValidatorFn + public readonly fields: ReadonlyArray ) { super(); } @@ -115,8 +114,17 @@ export type AbstractContentFormState = { isRequired?: boolean }; +export interface FormStructure { + allRules: ReadonlyArray; + partitions: PartitionConfig; + schema: SchemaDto; + schemas: { [id: string ]: SchemaDto }; + remoteValidator?: ValidatorFn; +} + export abstract class AbstractContentForm extends Hidden { private readonly disabled$ = new BehaviorSubject(false); + private readonly rules: ReadonlyArray; public get disabled() { return this.disabled$.value; @@ -127,12 +135,17 @@ export abstract class AbstractContentForm + public readonly isOptional: boolean ) { super(); + + const simplifiedPath = fieldPath.replace('.iv.', '.'); + + this.rules = globals.allRules.filter(x => x.field === fieldPath || x.field === simplifiedPath); } public updateState(context: RuleContext, parentState: AbstractContentFormState) { diff --git a/frontend/app/shared/state/contents.forms.spec.ts b/frontend/app/shared/state/contents.forms.spec.ts index d5b5984b4..302a0e9d0 100644 --- a/frontend/app/shared/state/contents.forms.spec.ts +++ b/frontend/app/shared/state/contents.forms.spec.ts @@ -673,6 +673,6 @@ describe('ContentForm', () => { function createForm(fields: RootFieldDto[], fieldRules: FieldRule[] = []) { return new EditContentForm(languages, - createSchema({ fields, fieldRules }), {}, 0); + createSchema({ fields, fieldRules }), {}, {}, 0); } }); \ No newline at end of file diff --git a/frontend/app/shared/state/contents.forms.ts b/frontend/app/shared/state/contents.forms.ts index f4f87191e..de08d717f 100644 --- a/frontend/app/shared/state/contents.forms.ts +++ b/frontend/app/shared/state/contents.forms.ts @@ -7,15 +7,15 @@ // tslint:disable: readonly-array -import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; -import { Form, Types, UndefinableFormArray, valueAll$ } from '@app/framework'; +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { Form, getRawValue, Types, UndefinableFormArray, UndefinableFormGroup, valueAll$ } from '@app/framework'; import { BehaviorSubject, Observable } from 'rxjs'; import { debounceTime, onErrorResumeNext } from 'rxjs/operators'; import { AppLanguageDto } from './../services/app-languages.service'; import { LanguageDto } from './../services/languages.service'; -import { NestedFieldDto, RootFieldDto, SchemaDto, TableField } from './../services/schemas.service'; -import { fieldInvariant } from './../services/schemas.types'; -import { AbstractContentForm, AbstractContentFormState, CompiledRule, FieldSection, PartitionConfig } from './contents.forms-helpers'; +import { FieldDto, RootFieldDto, SchemaDto, TableField } from './../services/schemas.service'; +import { ComponentFieldPropertiesDto, fieldInvariant } from './../services/schemas.types'; +import { AbstractContentForm, AbstractContentFormState, CompiledRule, FieldSection, FormStructure as FormGlobals, PartitionConfig } from './contents.forms-helpers'; import { FieldDefaultValue, FieldsValidators } from './contents.forms.visitors'; export { FieldSection } from './contents.forms-helpers'; @@ -91,13 +91,18 @@ export class EditContentForm extends Form { return this.valueChange$.value; } - constructor(languages: ReadonlyArray, schema: SchemaDto, + constructor(languages: ReadonlyArray, schema: SchemaDto, schemas: { [id: string ]: SchemaDto }, private context: any, debounce = 100 ) { super(new FormGroup({})); - const compiledPartitions = new PartitionConfig(languages); - const compiledConditions = schema.fieldRules.map(x => new CompiledRule(x)); + const globals: FormGlobals = { + allRules: schema.fieldRules.map(x => new CompiledRule(x)), + schema, + schemas, + partitions: new PartitionConfig(languages), + remoteValidator: this.remoteValidator + }; const sections: FieldSection[] = []; @@ -106,15 +111,16 @@ export class EditContentForm extends Form { for (const field of schema.fields) { if (field.properties.isContentField) { - const child = new FieldForm(field, compiledPartitions, compiledConditions, this.remoteValidator); + const childPath = field.name; + const childForm = new FieldForm(globals, childPath, field); - currentFields.push(child); + currentFields.push(childForm); - this.fields[field.name] = child; + this.fields[field.name] = childForm; - this.form.setControl(field.name, child.form); + this.form.setControl(field.name, childForm.form); } else { - sections.push(new FieldSection(currentSeparator, currentFields, this.remoteValidator)); + sections.push(new FieldSection(currentSeparator, currentFields)); currentFields = []; currentSeparator = field; @@ -122,7 +128,7 @@ export class EditContentForm extends Form { } if (currentFields.length > 0) { - sections.push(new FieldSection(currentSeparator, currentFields, this.remoteValidator)); + sections.push(new FieldSection(currentSeparator, currentFields)); } this.sections = sections; @@ -161,10 +167,8 @@ export class EditContentForm extends Form { } public load(value: any, isInitial?: boolean) { - for (const section of this.sections) { - for (const child of section.fields) { - child.prepareLoad(value[child.field.name]); - } + for (const key of Object.keys(this.fields)) { + this.fields[key].prepareLoad(value?.[key]); } super.load(value); @@ -214,34 +218,43 @@ export class EditContentForm extends Form { } export class FieldForm extends AbstractContentForm { - private readonly partitions: { [partition: string]: (FieldValueForm | FieldArrayForm) } = {}; + private readonly partitions: { [partition: string]: FieldItemForm } = {}; private isRequired: boolean; - constructor(field: RootFieldDto, partitions: PartitionConfig, rules: CompiledRule[], - private readonly remoteValidator?: ValidatorFn - ) { - super(field, new FormGroup({}), false, FieldForm.buildRules(field, rules)); + constructor(globals: FormGlobals, fieldPath: string, field: RootFieldDto) { + super(globals, fieldPath, field, FieldForm.buildForm(), false); - for (const { key, isOptional } of partitions.getAll(field)) { - const child = - field.isArray ? - new FieldArrayForm(field, isOptional, key, rules, this.remoteValidator) : - new FieldValueForm(field, isOptional, key, this.remoteValidator); + for (const { key, isOptional } of globals.partitions.getAll(field)) { + const childPath = `${fieldPath}.${key}`; + const childForm = buildForm(this.globals, childPath, field, isOptional, key); - this.partitions[key] = child; + this.partitions[key] = childForm; - this.form.setControl(key, child.form); + this.form.setControl(key, childForm.form); } this.isRequired = field.properties.isRequired; } public copyFrom(source: FieldForm, key: string) { - this.get(key)?.form.setValue(source.get(key)?.form.value); + const target = this.get(key); + + if (!target) { + return; + } + + const value = source.get(key)?.form.value; + + target.prepareLoad(value); + target.form.reset(source.get(key)?.form.value); } public copyAllFrom(source: FieldForm) { - this.form.setValue(source.form.getRawValue()); + const value = source.form.getRawValue(); + + this.prepareLoad(value); + + this.form.reset(value); } public get(language: string | LanguageDto) { @@ -268,8 +281,8 @@ export class FieldForm extends AbstractContentForm { validators = validators.filter(x => x !== Validators.required); } - if (this.remoteValidator) { - validators.push(this.remoteValidator); + if (this.globals.remoteValidator) { + validators.push(this.globals.remoteValidator); } partition.form.setValidators(validators); @@ -284,46 +297,66 @@ export class FieldForm extends AbstractContentForm { } public prepareLoad(value: any) { - if (Types.isObject(value)) { - for (const key in this.partitions) { - if (this.partitions.hasOwnProperty(key)) { - const child = this.partitions[key]; - - child.prepareLoad(value[key]); - } - } + for (const key of Object.keys(this.partitions)) { + this.partitions[key].prepareLoad(value?.[key]); } } - private static buildRules(field: RootFieldDto, rules: CompiledRule[]) { - return rules.filter(x => x.field === field.name); + private static buildForm() { + return new FormGroup({}); } } -export class FieldValueForm extends AbstractContentForm { - constructor(field: RootFieldDto, isOptional: boolean, key: string, - remoteValidator?: ValidatorFn +export class FieldValueForm extends AbstractContentForm { + private isRequired = false; + + constructor(globals: FormGlobals, path: string, field: FieldDto, + isOptional: boolean, partition: string ) { - super(field, FieldValueForm.buildControl(field, isOptional, key, remoteValidator), isOptional); + super(globals, path, field, + FieldValueForm.buildControl(field, isOptional, partition, globals), + isOptional + ); + + this.isRequired = field.properties.isRequired && !isOptional; + } + + protected updateCustomState(_: any, state: AbstractContentFormState) { + const isRequired = state.isRequired === true; + + if (!this.isOptional && this.isRequired !== isRequired) { + this.isRequired = isRequired; + + let validators = FieldsValidators.create(this.field, true); + + if (isRequired) { + validators.push(Validators.required); + } else { + validators = validators.filter(x => x !== Validators.required); + } + + this.form.setValidators(validators); + this.form.updateValueAndValidity(); + } } - private static buildControl(field: RootFieldDto, isOptional: boolean, key: string, remoteValidator?: ValidatorFn) { - const value = FieldDefaultValue.get(field, key); + private static buildControl(field: FieldDto, isOptional: boolean, partition: string, globals: FormGlobals) { + const value = FieldDefaultValue.get(field, partition); const validators = FieldsValidators.create(field, isOptional); - if (remoteValidator) { - validators.push(remoteValidator); + if (globals.remoteValidator) { + validators.push(globals.remoteValidator); } return new FormControl(value, { validators }); } } -export class FieldArrayForm extends AbstractContentForm { - private readonly item$ = new BehaviorSubject>([]); +export class FieldArrayForm extends AbstractContentForm { + private readonly item$ = new BehaviorSubject>([]); - public get itemChanges(): Observable> { + public get itemChanges(): Observable> { return this.item$; } @@ -331,25 +364,53 @@ export class FieldArrayForm extends AbstractContentForm) { + public set items(value: ReadonlyArray) { this.item$.next(value); } - constructor(field: RootFieldDto, isOptional: boolean, + constructor(globals: FormGlobals, path: string, field: FieldDto, isOptional: boolean, private readonly partition: string, - private readonly allRules: CompiledRule[], - private readonly remoteValidator?: ValidatorFn + private readonly isComponents: boolean ) { - super(field, FieldArrayForm.buildControl(field, isOptional), isOptional); + super(globals, path, field, + FieldArrayForm.buildControl(field, isOptional), + isOptional + ); } public get(index: number) { return this.items[index]; } - public addItem(source?: FieldArrayItemForm) { - const child = new FieldArrayItemForm(this.field, this.isOptional, this.allRules, source, this.partition, this.remoteValidator); + public addCopy(source: ObjectForm) { + if (this.isComponents) { + const child = new ComponentForm(this.globals, this.fieldPath, this.field as RootFieldDto, this.isOptional, this.partition); + + child.load(getRawValue(source.form)); + + this.addChild(child); + } else { + const child = new ArrayItemForm(this.globals, this.fieldPath, this.field as RootFieldDto, this.isOptional, this.partition); + + child.load(getRawValue(source.form)); + + this.addChild(child); + } + } + public addComponent(schemaId?: string) { + const child = new ComponentForm(this.globals, this.fieldPath, this.field, this.isOptional, this.partition, schemaId); + + this.addChild(child); + } + + public addItem() { + const child = new ArrayItemForm(this.globals, this.fieldPath, this.field as RootFieldDto, this.isOptional, this.partition); + + this.addChild(child); + } + + public addChild(child: ObjectForm) { this.items = [...this.items, child]; this.form.push(child.form); @@ -375,7 +436,7 @@ export class FieldArrayForm extends AbstractContentForm) { + public sort(children: ReadonlyArray) { for (let i = 0; i < children.length; i++) { this.form.setControl(i, children[i].form); } @@ -401,63 +462,101 @@ export class FieldArrayForm extends AbstractContentForm value.length) { this.removeItemAt(this.items.length - 1); } } + + for (let i = 0; i < this.items.length; i++) { + this.items[i].prepareLoad(value?.[i]); + } } - private static buildControl(field: RootFieldDto, isOptional: boolean) { + private static buildControl(field: FieldDto, isOptional: boolean) { const validators = FieldsValidators.create(field, isOptional); return new UndefinableFormArray([], validators); } } -export class FieldArrayItemForm extends AbstractContentForm { - private readonly fields: { [key: string]: FieldArrayItemValueForm } = {}; +export type FieldItemForm = ComponentForm | FieldValueForm | FieldArrayForm; - public readonly sections: ReadonlyArray>; +export class ObjectForm extends AbstractContentForm { + private fields: { [key: string]: FieldItemForm } = {}; + private fieldSections: FieldSection[] = []; - constructor(field: RootFieldDto, isOptional: boolean, allRules: CompiledRule[], source: FieldArrayItemForm | undefined, partition: string, - private readonly remoteValidator?: ValidatorFn + public get sections() { + return this.fieldSections; + } + + constructor(globals: FormGlobals, path: string, field: TField, isOptional: boolean, + private readonly partition: string ) { - super(field, new FormGroup({}), isOptional); + super(globals, path, field, ObjectForm.buildControl(field, isOptional, true), isOptional); + } - const sections: FieldSection[] = []; + public get(field: string | { name: string }): FieldItemForm | undefined { + return this.fields[field['name'] || field]; + } - let currentSeparator: NestedFieldDto | undefined = undefined; - let currentFields: FieldArrayItemValueForm[] = []; + protected init(schema?: ReadonlyArray) { + this.fields = {}; + this.fieldSections = []; - for (const nestedField of field.nested) { - if (nestedField.properties.isContentField) { - const child = new FieldArrayItemValueForm(nestedField, field, allRules, isOptional, partition, source, this.remoteValidator); + for (const key of Object.keys(this.form.controls)) { + this.form.removeControl(key); + } - currentFields.push(child); + if (schema) { + this.form.reset({}); - this.fields[nestedField.name] = child; + let currentSeparator: FieldDto | undefined = undefined; + let currentFields: FieldItemForm[] = []; - this.form.setControl(nestedField.name, child.form); - } else { - sections.push(new FieldSection(currentSeparator, currentFields, this.remoteValidator)); + for (const field of schema) { + if (field.properties.isContentField) { + const childPath = `${this.fieldPath}.${field.name}`; + const childForm = buildForm(this.globals, childPath, field, this.isOptional, this.partition); - currentFields = []; - currentSeparator = nestedField; + this.form.setControl(field.name, childForm.form); + + currentFields.push(childForm); + + this.fields[field.name] = childForm; + + } else { + this.fieldSections.push(new FieldSection(currentSeparator, currentFields)); + + currentFields = []; + currentSeparator = field; + } } - } - if (currentFields.length > 0) { - sections.push(new FieldSection(currentSeparator, currentFields, this.remoteValidator)); + if (currentFields.length > 0) { + this.fieldSections.push(new FieldSection(currentSeparator, currentFields)); + } + } else { + this.form.reset(undefined); } + } - this.sections = sections; + public load(data: any) { + this.prepareLoad(data); + + this.form.reset(data); } - public get(field: string | NestedFieldDto): FieldArrayItemValueForm | undefined { - return this.fields[field['name'] || field]; + public prepareLoad(value: any) { + for (const key of Object.keys(this.fields)) { + this.fields[key].prepareLoad(value?.[key]); + } } protected updateCustomState(context: any, state: AbstractContentFormState) { @@ -471,65 +570,83 @@ export class FieldArrayItemForm extends AbstractContentForm { - private isRequired = false; + private static buildControl(field: FieldDto, isOptional: boolean, validate: boolean) { + let validators = [Validators.nullValidator]; - constructor(field: NestedFieldDto, parent: RootFieldDto, rules: CompiledRule[], isOptional: boolean, partition: string, - source: FieldArrayItemForm | undefined, remoteValidator?: ValidatorFn - ) { - super(field, - FieldArrayItemValueForm.buildControl(field, isOptional, partition, remoteValidator, source), - isOptional, - FieldArrayItemValueForm.buildRules(field, parent, rules) - ); + if (validate) { + validators = FieldsValidators.create(field, isOptional); + } - this.isRequired = field.properties.isRequired && !isOptional; + return new UndefinableFormGroup({}, validators); } +} - protected updateCustomState(_: any, state: AbstractContentFormState) { - const isRequired = state.isRequired === true; +export class ArrayItemForm extends ObjectForm { + constructor(globals: FormGlobals, path: string, field: RootFieldDto, isOptional: boolean, partition: string) { + super(globals, path, field, isOptional, partition); - if (!this.isOptional && this.isRequired !== isRequired) { - this.isRequired = isRequired; + this.init(field.nested); + } +} - let validators = FieldsValidators.create(this.field, true); +export class ComponentForm extends ObjectForm { + private schemaId?: string; - if (isRequired) { - validators.push(Validators.required); - } else { - validators = validators.filter(x => x !== Validators.required); - } + public readonly properties: ComponentFieldPropertiesDto; - this.form.setValidators(validators); - this.form.updateValueAndValidity(); - } + public get schema() { + return this.globals.schemas[this.schemaId!]; } - private static buildRules(field: NestedFieldDto, parent: RootFieldDto, rules: CompiledRule[]) { - const fullName = `${parent.name}.${field.name}`; + constructor(globals: FormGlobals, path: string, field: FieldDto, isOptional: boolean, partition: string, schemaId?: string) { + super(globals, path, field, isOptional, partition); + + this.properties = field.properties as ComponentFieldPropertiesDto; - return rules.filter(x => x.field === fullName); + if (schemaId) { + this.selectSchema(schemaId); + } else if (this.properties.schemaIds?.length === 1) { + this.selectSchema(this.properties.schemaIds[0]); + } } - private static buildControl(field: NestedFieldDto, isOptional: boolean, partition: string, remoteValidator?: ValidatorFn, source?: FieldArrayItemForm) { - let value = FieldDefaultValue.get(field, partition); + public selectSchema(schemaId?: string) { + if (this.schemaId !== schemaId) { + this.schemaId = schemaId; - if (source) { - const sourceField = source.form.get(field.name); + if (this.schema) { + this.init(this.schema.fields); - if (sourceField) { - value = sourceField.value; + this.form.setControl('schemaId', new FormControl(schemaId)); + } else { + this.init(undefined); } } + } - const validators = FieldsValidators.create(field, isOptional); + public unset() { + this.selectSchema(undefined); - if (remoteValidator) { - validators.push(remoteValidator); - } + super.unset(); + } - return new FormControl(value, { validators }); + public prepareLoad(value: any) { + this.selectSchema(value?.['schemaId']); + + super.prepareLoad(value); + } +} + +function buildForm(globals: FormGlobals, path: string, field: FieldDto, isOptional: boolean, partition: string) { + switch (field.properties.fieldType) { + case 'Array': + return new FieldArrayForm(globals, path, field, isOptional, partition, false); + case 'Component': + return new ComponentForm(globals, path, field, isOptional, partition); + case 'Components': + return new FieldArrayForm(globals, path, field, isOptional, partition, true); + default: + return new FieldValueForm(globals, path, field, isOptional, partition); } } \ No newline at end of file diff --git a/frontend/app/shared/state/contents.forms.visitors.spec.ts b/frontend/app/shared/state/contents.forms.visitors.spec.ts index 7b0cc2836..c877ece58 100644 --- a/frontend/app/shared/state/contents.forms.visitors.spec.ts +++ b/frontend/app/shared/state/contents.forms.visitors.spec.ts @@ -81,35 +81,51 @@ describe('AssetsField', () => { }); }); -describe('TagsField', () => { - const field = createField({ properties: createProperties('Tags', { isRequired: true, minItems: 1, maxItems: 5 }) }); +describe('ComponentField', () => { + const field = createField({ properties: createProperties('Component', { isRequired: true }) }); it('should create validators', () => { - expect(FieldsValidators.create(field, false).length).toBe(2); + expect(FieldsValidators.create(field, false).length).toBe(1); }); it('should format to empty string if null', () => { expect(FieldFormatter.format(field, null)).toBe(''); }); - it('should format to asset count', () => { - expect(FieldFormatter.format(field, ['hello', 'squidex', 'cms'])).toBe('hello, squidex, cms'); + it('should format to constant', () => { + expect(FieldFormatter.format(field, {})).toBe('{ Component }'); }); - it('should return zero formatting if other type', () => { - expect(FieldFormatter.format(field, 1)).toBe(''); + it('should return default value as null', () => { + expect(FieldDefaultValue.get(field, 'iv')).toBeNull(); }); +}); - it('should return default value from properties', () => { - const field2 = createField({ properties: createProperties('Tags', { defaultValue: ['1', '2'] }) }); +describe('ComponentsField', () => { + const field = createField({ properties: createProperties('Components', { isRequired: true, minItems: 1, maxItems: 5 }) }); - expect(FieldDefaultValue.get(field2, 'iv')).toEqual(['1', '2']); + it('should create validators', () => { + expect(FieldsValidators.create(field, false).length).toBe(2); }); - it('should override default value from localizable properties', () => { - const field2 = createField({ properties: createProperties('Tags', { defaultValue: ['1', '2'], defaultValues: { 'iv': null } }) }); + it('should format to empty string if null', () => { + expect(FieldFormatter.format(field, null)).toBe(''); + }); - expect(FieldDefaultValue.get(field2, 'iv')).toBeNull(); + it('should format to plural count for many items', () => { + expect(FieldFormatter.format(field, [1, 2, 3])).toBe('3 Components'); + }); + + it('should format to plural count for single item', () => { + expect(FieldFormatter.format(field, [1])).toBe('1 Component'); + }); + + it('should return zero formatting if other type', () => { + expect(FieldFormatter.format(field, 1)).toBe('0 Components'); + }); + + it('should return default value as null', () => { + expect(FieldDefaultValue.get(field, 'iv')).toBeNull(); }); }); @@ -395,6 +411,38 @@ describe('StringField', () => { }); }); +describe('TagsField', () => { + const field = createField({ properties: createProperties('Tags', { isRequired: true, minItems: 1, maxItems: 5 }) }); + + it('should create validators', () => { + expect(FieldsValidators.create(field, false).length).toBe(2); + }); + + it('should format to empty string if null', () => { + expect(FieldFormatter.format(field, null)).toBe(''); + }); + + it('should format to asset count', () => { + expect(FieldFormatter.format(field, ['hello', 'squidex', 'cms'])).toBe('hello, squidex, cms'); + }); + + it('should return zero formatting if other type', () => { + expect(FieldFormatter.format(field, 1)).toBe(''); + }); + + it('should return default value from properties', () => { + const field2 = createField({ properties: createProperties('Tags', { defaultValue: ['1', '2'] }) }); + + expect(FieldDefaultValue.get(field2, 'iv')).toEqual(['1', '2']); + }); + + it('should override default value from localizable properties', () => { + const field2 = createField({ properties: createProperties('Tags', { defaultValue: ['1', '2'], defaultValues: { 'iv': null } }) }); + + expect(FieldDefaultValue.get(field2, 'iv')).toBeNull(); + }); +}); + function isUtc() { return new Date().getTimezoneOffset() === 0; } \ No newline at end of file diff --git a/frontend/app/shared/state/contents.forms.visitors.ts b/frontend/app/shared/state/contents.forms.visitors.ts index 8dce7a987..016b83caf 100644 --- a/frontend/app/shared/state/contents.forms.visitors.ts +++ b/frontend/app/shared/state/contents.forms.visitors.ts @@ -13,7 +13,7 @@ import { DateTime, Types, ValidatorsEx } from '@app/framework'; import { ContentDto, ContentReferencesValue } from './../services/contents.service'; import { LanguageDto } from './../services/languages.service'; import { FieldDto, RootFieldDto } from './../services/schemas.service'; -import { ArrayFieldPropertiesDto, AssetsFieldPropertiesDto, BooleanFieldPropertiesDto, DateTimeFieldPropertiesDto, fieldInvariant, FieldPropertiesVisitor, GeolocationFieldPropertiesDto, JsonFieldPropertiesDto, NumberFieldPropertiesDto, ReferencesFieldPropertiesDto, StringFieldPropertiesDto, TagsFieldPropertiesDto, UIFieldPropertiesDto } from './../services/schemas.types'; +import { ArrayFieldPropertiesDto, AssetsFieldPropertiesDto, BooleanFieldPropertiesDto, ComponentFieldPropertiesDto, ComponentsFieldPropertiesDto, DateTimeFieldPropertiesDto, fieldInvariant, FieldPropertiesVisitor, GeolocationFieldPropertiesDto, JsonFieldPropertiesDto, NumberFieldPropertiesDto, ReferencesFieldPropertiesDto, StringFieldPropertiesDto, TagsFieldPropertiesDto, UIFieldPropertiesDto } from './../services/schemas.types'; export class HtmlValue { constructor( @@ -125,6 +125,14 @@ export class FieldFormatter implements FieldPropertiesVisitor { return this.value ? 'Yes' : 'No'; } + public visitComponent(_: ComponentFieldPropertiesDto): string { + return '{ Component }'; + } + + public visitComponents(_: ComponentsFieldPropertiesDto): string { + return this.formatArray('Component', 'Component'); + } + public visitDateTime(properties: DateTimeFieldPropertiesDto): FieldValue { try { const parsed = DateTime.parseISO(this.value); @@ -259,6 +267,18 @@ export class FieldsValidators implements FieldPropertiesVisitor { + return []; + } + + public visitComponents(properties: ComponentsFieldPropertiesDto): ReadonlyArray { + const validators: ValidatorFn[] = [ + ValidatorsEx.betweenLength(properties.minItems, properties.maxItems) + ]; + + return validators; + } + public visitDateTime(_: DateTimeFieldPropertiesDto): ReadonlyArray { return []; } @@ -377,6 +397,14 @@ export class FieldDefaultValue implements FieldPropertiesVisitor { return this.getValue(properties.defaultValue, properties.defaultValues); } + public visitComponent(_: ComponentFieldPropertiesDto): any { + return null; + } + + public visitComponents(_: ComponentsFieldPropertiesDto): any { + return null; + } + public visitGeolocation(_: GeolocationFieldPropertiesDto): any { return null; } diff --git a/frontend/app/shared/state/schemas.forms.ts b/frontend/app/shared/state/schemas.forms.ts index b495fbcc6..cb052961e 100644 --- a/frontend/app/shared/state/schemas.forms.ts +++ b/frontend/app/shared/state/schemas.forms.ts @@ -284,6 +284,16 @@ export class EditFieldFormVisitor implements FieldPropertiesVisitor { this.config['defaultValue'] = undefined; } + public visitComponent() { + this.config['schemaIds'] = undefined; + } + + public visitComponents() { + this.config['schemaIds'] = undefined; + this.config['maxItems'] = undefined; + this.config['minItems'] = undefined; + } + public visitDateTime() { this.config['calculatedDefaultValue'] = undefined; this.config['defaultValue'] = undefined; diff --git a/frontend/app/shared/state/schemas.state.spec.ts b/frontend/app/shared/state/schemas.state.spec.ts index 10ebe17e3..fbf85046f 100644 --- a/frontend/app/shared/state/schemas.state.spec.ts +++ b/frontend/app/shared/state/schemas.state.spec.ts @@ -61,9 +61,10 @@ describe('SchemasState', () => { const categories = getCategories(schemasState); expect(categories!).toEqual([ - { name: '', upper: '', schemas: [] }, - { name: 'schema-category1', upper: 'SCHEMA-CATEGORY1', schemas: [schema1] }, - { name: 'schema-category2', upper: 'SCHEMA-CATEGORY2', schemas: [schema2] } + { displayName: 'i18n:common.components', schemas: [] }, + { displayName: 'i18n:common.schemas', schemas: [] }, + { displayName: 'schema-category1', name: 'schema-category1', schemas: [schema1] }, + { displayName: 'schema-category2', name: 'schema-category2', schemas: [schema2] } ]); schemasService.verifyAll(); @@ -83,10 +84,11 @@ describe('SchemasState', () => { const categories = getCategories(schemasState); expect(categories!).toEqual([ - { name: '', upper: '', schemas: [] }, - { name: 'schema-category1', upper: 'SCHEMA-CATEGORY1', schemas: [schema1] }, - { name: 'schema-category2', upper: 'SCHEMA-CATEGORY2', schemas: [schema2] }, - { name: 'schema-category3', upper: 'SCHEMA-CATEGORY3', schemas: [] } + { displayName: 'i18n:common.components', schemas: [] }, + { displayName: 'i18n:common.schemas', schemas: [] }, + { displayName: 'schema-category1', name: 'schema-category1', schemas: [schema1] }, + { displayName: 'schema-category2', name: 'schema-category2', schemas: [schema2] }, + { displayName: 'schema-category3', name: 'schema-category3', schemas: [] } ]); schemasService.verifyAll(); @@ -151,35 +153,49 @@ describe('SchemasState', () => { const categories = getCategories(schemasState); expect(categories!).toEqual([ - { name: '', upper: '', schemas: [] }, - { name: 'schema-category1', upper: 'SCHEMA-CATEGORY1', schemas: [schema1] }, - { name: 'schema-category2', upper: 'SCHEMA-CATEGORY2', schemas: [schema2] }, - { name: 'schema-category3', upper: 'SCHEMA-CATEGORY3', schemas: [] } + { displayName: 'i18n:common.components', schemas: [] }, + { displayName: 'i18n:common.schemas', schemas: [] }, + { displayName: 'schema-category1', name: 'schema-category1', schemas: [schema1] }, + { displayName: 'schema-category2', name: 'schema-category2', schemas: [schema2] }, + { displayName: 'schema-category3', name: 'schema-category3', schemas: [] } ]); }); it('should not remove category with schemas', () => { - schemasState.addCategory('schema-category1'); + schemasState.removeCategory('schema-category1'); const categories = getCategories(schemasState); expect(categories!).toEqual([ - { name: '', upper: '', schemas: [] }, - { name: 'schema-category1', upper: 'SCHEMA-CATEGORY1', schemas: [schema1] }, - { name: 'schema-category2', upper: 'SCHEMA-CATEGORY2', schemas: [schema2] } + { displayName: 'i18n:common.components', schemas: [] }, + { displayName: 'i18n:common.schemas', schemas: [] }, + { displayName: 'schema-category1', name: 'schema-category1', schemas: [schema1] }, + { displayName: 'schema-category2', name: 'schema-category2', schemas: [schema2] } ]); }); it('should remove category', () => { schemasState.addCategory('schema-category3'); + + const categories1 = getCategories(schemasState); + + expect(categories1).toEqual([ + { displayName: 'i18n:common.components', schemas: [] }, + { displayName: 'i18n:common.schemas', schemas: [] }, + { displayName: 'schema-category1', name: 'schema-category1', schemas: [schema1] }, + { displayName: 'schema-category2', name: 'schema-category2', schemas: [schema2] }, + { displayName: 'schema-category3', name: 'schema-category3', schemas: [] } + ]); + schemasState.removeCategory('schema-category3'); - const categories = getCategories(schemasState); + const categories2 = getCategories(schemasState); - expect(categories!).toEqual([ - { name: '', upper: '', schemas: [] }, - { name: 'schema-category1', upper: 'SCHEMA-CATEGORY1', schemas: [schema1] }, - { name: 'schema-category2', upper: 'SCHEMA-CATEGORY2', schemas: [schema2] } + expect(categories2).toEqual([ + { displayName: 'i18n:common.components', schemas: [] }, + { displayName: 'i18n:common.schemas', schemas: [] }, + { displayName: 'schema-category1', name: 'schema-category1', schemas: [schema1] }, + { displayName: 'schema-category2', name: 'schema-category2', schemas: [schema2] } ]); }); @@ -208,40 +224,6 @@ describe('SchemasState', () => { expect(schemasState.snapshot.selectedSchema).toBe(schemasState.snapshot.schemas[0]); }); - it('should return loaded schema on get', () => { - schemasService.setup(x => x.getSchema(app, schema2.name)) - .returns(() => of(schema2)).verifiable(Times.never()); - - schemasState.loadSchema(schema2.name, true).subscribe(); - schemasState.loadSchema(schema2.name, true).subscribe(); - - expect().nothing(); - }); - - it('should return schema on get and reuse it from selected if caching', () => { - schemasService.setup(x => x.getSchema(app, schema1.name)) - .returns(() => of(schema1)).verifiable(Times.once()); - - schemasState.select(schema1.name).subscribe(); - schemasState.loadSchema(schema1.name, true).subscribe(); - - expect().nothing(); - }); - - it('should not try to load if not found', () => { - schemasService.setup(x => x.getSchema(app, 'failed')) - .returns(() => throwError('Service Error')).verifiable(Times.never()); - - let schemaSelected: SchemaDto; - - schemasState.select('failed').pipe(onErrorResumeNext()).subscribe(x => { - schemaSelected = x!; - }); - - expect(schemaSelected!).toBeNull(); - expect(schemasState.snapshot.selectedSchema).toBeNull(); - }); - it('should return null on select if unselecting schema', () => { let schemaSelected: SchemaDto; diff --git a/frontend/app/shared/state/schemas.state.ts b/frontend/app/shared/state/schemas.state.ts index c9d79a0cd..9424f927d 100644 --- a/frontend/app/shared/state/schemas.state.ts +++ b/frontend/app/shared/state/schemas.state.ts @@ -5,8 +5,10 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ +// tslint:disable: readonly-array + import { Injectable } from '@angular/core'; -import { compareStrings, DialogService, shareMapSubscribed, shareSubscribed, State, Version } from '@app/framework'; +import { DialogService, shareMapSubscribed, shareSubscribed, State, Version } from '@app/framework'; import { EMPTY, Observable, of } from 'rxjs'; import { catchError, finalize, tap } from 'rxjs/operators'; import { AddFieldDto, CreateSchemaDto, FieldDto, FieldRule, NestedFieldDto, RootFieldDto, SchemaDto, SchemasService, UpdateFieldDto, UpdateSchemaDto, UpdateUIFields } from './../services/schemas.service'; @@ -16,7 +18,7 @@ type AnyFieldDto = NestedFieldDto | RootFieldDto; interface Snapshot { // The schema categories. - categories: ReadonlyArray; + categories: Set; // The current schemas. schemas: SchemasList; @@ -35,7 +37,7 @@ interface Snapshot { } export type SchemasList = ReadonlyArray; -export type SchemaCategory = { name: string; schemas: SchemasList; upper: string; }; +export type SchemaCategory = { displayName: string; name?: string; schemas: SchemaDto[]; }; @Injectable() export class SchemasState extends State { @@ -71,12 +73,16 @@ export class SchemasState extends State { return this.snapshot.selectedSchema?.name || ''; } + public get schemaMap() { + return this.snapshot.schemas.toMap(x => x.id); + } + constructor( private readonly appsState: AppsState, private readonly dialogs: DialogService, private readonly schemasService: SchemasService ) { - super({ schemas: [], categories: [] }, 'Schemas'); + super({ schemas: [], categories: new Set() }, 'Schemas'); } public select(idOrName: string | null): Observable { @@ -86,17 +92,11 @@ export class SchemasState extends State { })); } - public loadSchema(idOrName: string | null, cached = false) { + private loadSchema(idOrName: string | null) { if (!idOrName) { return of(null); } - const found = this.snapshot.schemas.find(x => x.id === idOrName || x.name === idOrName); - - if (cached || !found) { - return of(found || null); - } - return this.schemasService.getSchema(this.appName, idOrName).pipe( tap(schema => { this.next(s => { @@ -175,7 +175,7 @@ export class SchemasState extends State { public addCategory(name: string) { this.next(s => { - const categories = [...s.categories, name]; + const categories = new Set([...s.categories, name]); return { ...s, categories }; }, 'Category Added'); @@ -183,7 +183,7 @@ export class SchemasState extends State { public removeCategory(name: string) { this.next(s => { - const categories = s.categories.removed(name); + const categories = new Set([...s.categories].remove(name)); return { ...s, categories }; }, 'Category Removed'); @@ -205,7 +205,7 @@ export class SchemasState extends State { shareSubscribed(this.dialogs)); } - public changeCategory(schema: SchemaDto, name: string): Observable { + public changeCategory(schema: SchemaDto, name?: string): Observable { return this.schemasService.putCategory(this.appName, schema, { name }, schema.version).pipe( tap(updated => { this.replaceSchema(updated); @@ -371,38 +371,55 @@ function getField(x: SchemaDto, request: AddFieldDto, parent?: RootFieldDto): Fi } } -const NO_NAME = ''; +const SPECIAL_SCHEMAS = 'i18n:common.schemas'; +const SPECIAL_COMPONENTS = 'i18n:common.components'; + +function buildCategories(categories: Set, allSchemas: SchemasList): ReadonlyArray { + const schemas: SchemaCategory = { + displayName: SPECIAL_SCHEMAS, + schemas: [] + }; -function buildCategories(categories: ReadonlyArray, allSchemas: SchemasList): ReadonlyArray { - const uniqueCategories: { [name: string]: true } = { - [NO_NAME]: true + const components: SchemaCategory = { + displayName: SPECIAL_COMPONENTS, + schemas: [] }; - for (const category of categories) { - uniqueCategories[category] = true; + const result: SchemaCategory[] = [schemas, components]; + + for (const name of categories) { + result.push({ + displayName: name, + name, + schemas: [] + }); } for (const schema of allSchemas) { - uniqueCategories[getCategory(schema)] = true; - } + const name = schema.category; + + if (name) { + let category = result.find(x => x.name === name); - const result: SchemaCategory[] = []; + if (!category) { + category = { + displayName: name, + name, + schemas: [] + }; - for (const name of Object.keys(uniqueCategories)) { - const schemas = allSchemas.filter(x => isSameCategory(name, x)); + result.push(category); + } - result.push({ name, upper: name.toUpperCase(), schemas }); + category.schemas.push(schema); + } else if (schema.type === 'Component') { + components.schemas.push(schema); + } else { + schemas.schemas.push(schema); + } } - result.sort((a, b) => compareStrings(a.upper, b.upper)); + result.sortByString(x => x.displayName); return result; -} - -function getCategory(schema: SchemaDto) { - return schema.category || NO_NAME; -} - -export function isSameCategory(name: string, schema: SchemaDto): boolean { - return getCategory(schema) === name; } \ No newline at end of file diff --git a/frontend/app/shell/pages/home/home-page.component.html b/frontend/app/shell/pages/home/home-page.component.html index 7604ef21f..3bf3f9e99 100644 --- a/frontend/app/shell/pages/home/home-page.component.html +++ b/frontend/app/shell/pages/home/home-page.component.html @@ -18,8 +18,8 @@
- + {{ 'start.madeBy' | sqxTranslate }}
{{ 'start.madeByCopyright' | sqxTranslate }} -
+
diff --git a/frontend/app/theme/icomoon/Read Me.txt b/frontend/app/theme/icomoon/Read Me.txt new file mode 100644 index 000000000..8491652f8 --- /dev/null +++ b/frontend/app/theme/icomoon/Read Me.txt @@ -0,0 +1,7 @@ +Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. + +To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts + +You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. + +You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection. diff --git a/frontend/app/theme/icomoon/demo.html b/frontend/app/theme/icomoon/demo.html index c23924031..77a6d1bb8 100644 --- a/frontend/app/theme/icomoon/demo.html +++ b/frontend/app/theme/icomoon/demo.html @@ -9,10 +9,24 @@
-

Font Name: icomoon (Glyphs: 137)

+

Font Name: icomoon (Glyphs: 138)

Grid Size: 14

+
+
+ + icon-component +
+
+ + +
+
+ liga: + +
+
@@ -167,6 +181,20 @@
+
+
+ + icon-type-Component +
+
+ + +
+
+ liga: + +
+
@@ -181,6 +209,20 @@
+
+
+ + icon-type-Components +
+
+ + +
+
+ liga: + +
+
diff --git a/frontend/app/theme/icomoon/fonts/icomoon.eot b/frontend/app/theme/icomoon/fonts/icomoon.eot index 413597637c99e6d917940b39ff6e4430bb07b5c5..88493def5f1affc8e731386a962c5223e9111f49 100644 GIT binary patch delta 482 zcmbR9mvO~^Mz$683=Ayw6WPpIzKZs&nCQ^ToOnBH;t830_y5LU85kHRFff$=$Vg30 zk$t8P900lUiSo?we13HpApZ#i1CvEgesbawi^cyK7;0pI zX2|6xRunKSWsGECsI>vASIA4uO`Yk*`5VZO0m`=(6>VWzg6d0J9Cnq!Z zFt$zpz^Kf6P@swb$Yu$qqs5|Z4ABg%%qy9L82Evz3>X|40vQq~w}dO#iz~6oGKz>< zGa8xMGMcC{1r#m}cMg9%0HY`SRGKsPZEmU5W@3!qyrx>2kw47pkM$1g QKR^|XK-{<06ZNYU7#J8QFff#T z$w*C1k?yz>%fL|4!oa{_mH`ytWMb_D^7jDwDjB&Y75u&`O+fww1_maRoc!d(j| diff --git a/frontend/app/theme/icomoon/fonts/icomoon.svg b/frontend/app/theme/icomoon/fonts/icomoon.svg index dbfc77c9e..8a1475b83 100644 --- a/frontend/app/theme/icomoon/fonts/icomoon.svg +++ b/frontend/app/theme/icomoon/fonts/icomoon.svg @@ -94,8 +94,8 @@ - - + + @@ -141,6 +141,7 @@ + diff --git a/frontend/app/theme/icomoon/fonts/icomoon.ttf b/frontend/app/theme/icomoon/fonts/icomoon.ttf index 4fb2ed015b89aac3bb6f689f012894c6c33c8c40..79c83ad6025b096edba4976c1aeb32e06529b0e7 100644 GIT binary patch delta 497 zcmezIo3Z5|;{?U}#M@a642&`i3=BExiNys#S^&uJ0MZ=kIhASd|Bb%_`4boz%70{} zCZ@e&6$K1S86z1OYHfh(74i~uQzd44asCDh!~hkv733F}Ffaq980wx(+%cK4ZL$xe zGV4KsCjKLvOBjz9i?T69Gq5tRWDa8BXHZ};U~pszWJsL+AWXSlT!~GVQAEs|(a6k} z(L_y|-PlMBD8Q!8sH6rIFf(R1RALhq5i?daGBY(%GgfAW@Ie}Yd}YJmj`8u1Ongpp zaZZ0fG4bg;JL~`b1R}SCgkFM)mj=$x1}{N^GF-g8T#Uw?e2QF*|ITsodhv2S00}V% z0kwYyDQ4nziqmyA`1={8hl$s~xesQFQ=Fc&KFp{VUM@~vUQRCFP9TGi56IYTRvN}E zv!X}zYdpWrR|aktPh^MeX)CdTN^9M#H?m9Ogn^-2 z1Y}2UVnqSN62?ddh8hE)dWF2i+*FB~UYx&y0s%k;Z3X$oB@E0!DTdk`6L(BzY@O`G zsLXmmpppOZ<`TxE#hY!*f|+H0RCQK>1$Aa0W4uItHf6AM1oS$JZ`p1OT2cN>l&< diff --git a/frontend/app/theme/icomoon/fonts/icomoon.woff b/frontend/app/theme/icomoon/fonts/icomoon.woff index 053a550d3bb2243bde3be106f128ef65368b9b01..01830d0993636eb8147665bd996045f4ed0be9cc 100644 GIT binary patch delta 542 zcmX@|hw;KcMv-!VH#Y`G1|X;pVBiMRERzlEgeN=Hu}suft53Y0m7Z8!z`($G1t`e@ z#RBO$m1#h+I}8lvKS0?1zwy_M)Wj49hDwk+GZ2=2rv5bpD9FH2#RKH4fG{T$Ykx*= zNd-{MfPsO@0)&NqRqp2GCj-^hWB|>S1K}eUi~r>&Rut$kFw}McH7bDdQpU)<#N1S% z*b1PcHV~fa#reA+zqkbGeuIgBW;3=;p24WhdQhN=|H$S8j7N(_*%+c3SeaKc2Qlyi zO)+3_WC&zPoU9YB>?p3pCd()yX3c11X3J=zrp#_^BnA{<(`Hms0}7ZKvl}Y0iHe9B zD;k-Zny48ovqJbF4M4uK;p7G3lJ(o2;^LfMf{B*~&dvre^_`vdWw>~GxfqQ(`4qVr z|D6MI9)Jkupg5<$pFwJwc%9;Ooelne25Dj9HE`~O8R8VD=d2GisfCw|lb4s1i?q=wz;NgA#{)2W@|Oy8 w#=gxumD)^<(VIi6l^G?&to~TJ#7!3e~CjNuGoAk_>^pqSr0zh)^T07NQ^zW@LL delta 290 zcmccckMYPKMv-!VH#Y`G1|X<&Vc-VQwLd0`*w!c9PESuPE?{6_yaE*CfMS94oXRwy z*c}FjvM(TXw4+u2!AKrX`@o4ep&az-;nO}KU%<=p-Um3VrfCe!z r+@9(VbT)*Z{G-yGv3IjUl{VAn_!nd + + + + + + + image/svg+xml + + single-content + + + + + + single-content + + + + + diff --git a/frontend/app/theme/icomoon/selection.json b/frontend/app/theme/icomoon/selection.json index 1670911c0..12e4b02b1 100644 --- a/frontend/app/theme/icomoon/selection.json +++ b/frontend/app/theme/icomoon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M456.158 36.282c-12.145-0.032-24.18 1.32-35.941 3.974-23.536 5.313-45.906 15.872-65.238 31.342-77.826 61.631-80.817 179.217-6.302 244.772 0.028 0.028 0.084 0.086 0.113 0.114 0.020 0.018 0.038 0.039 0.058 0.057 0.037 0.039 0.074 0.076 0.112 0.112l0.001 0.001c4.727 4.044 7.287 9.964 7.097 16.182-0.003 0.018 0.003 0.038 0 0.057-0.008 0.085-0.012 0.184-0.012 0.284s0.004 0.199 0.013 0.296l-0.001-0.013c0 10.503-8.234 18.737-18.737 18.737h-290.707c-5.436-0.020-10.354 4.898-10.334 10.334v192.479c0.079 40.118 25.509 70.246 57.289 81.875 31.779 11.628 70.726 5.088 96.694-25.494 48.914-57.384 140.83-35.582 158.809 37.644 6.312 27.401 0.010 56.217-17.261 78.411-35.813 45.415-103.666 46.801-141.265 2.839-0.153-0.167-0.32-0.317-0.501-0.448l-0.010-0.007c-0.073-0.080-0.147-0.154-0.224-0.224l-0.003-0.002c-25.873-30.135-64.41-36.684-96.012-25.21-31.887 11.577-57.465 41.733-57.517 81.988v191.003c-0.020 5.436 4.898 10.354 10.334 10.334h745.955c5.436 0.020 10.354-4.898 10.334-10.334l-0.852-616.898c0.020-5.436-4.898-10.354-10.334-10.334h-222.401c-10.503 0-18.737-8.234-18.737-18.737-0.019-5.72 2.466-11.020 6.87-14.592 0.080-0.073 0.154-0.147 0.224-0.224l0.002-0.003 0.227-0.227c97.336-84.032 59.622-244.251-65.125-275.83-0.169-0.034-0.365-0.054-0.566-0.057l-0.002-0c-0.018-0.004-0.038 0.004-0.058 0h-0.113c-11.884-2.753-23.91-4.17-35.884-4.202zM454.682 105.041c6.891 0.035 13.821 0.856 20.667 2.441 73.201 17.648 95.396 109.369 38.439 158.582-30.669 26.067-37.154 65.105-25.38 96.921 11.773 31.813 42.084 57.204 82.329 57.006h164.090v499.65h-629.673l-0.795-133.884c0.026-10.44 8.193-18.619 18.623-18.68 5.89 0.174 11.341 2.823 15.103 7.324 0.055 0.060 0.111 0.116 0.169 0.17l0.002 0.002c0.028 0.028 0.086 0.087 0.114 0.113 65.15 75.665 183.646 73.404 245.737-4.769l0.058-0.058c0.076-0.085 0.151-0.178 0.22-0.275l0.007-0.010c30.825-38.562 42.246-89.164 31.058-137.234-0.010-0.168-0.030-0.324-0.062-0.475l0.004 0.021c-30.581-126.005-192.369-164.654-276.681-66.145-0.019 0.019-0.037 0.038-0.055 0.057l-0.001 0.001c-0.175 0.215-0.297 0.397-0.454 0.624-5.948 8.251-13.969 9.414-21.519 6.699-7.485-2.692-12.925-8.644-12.378-18.623v-0.172c0.003-0.041-0.003-0.073 0-0.113 0.017-0.131 0.045-0.267 0.057-0.397 0.002-0.043 0.003-0.092 0.003-0.142s-0.001-0.1-0.003-0.149l0 0.007v-133.259h233.53c40.255-0.052 70.451-25.629 82.045-57.517 11.514-31.669 4.916-70.308-25.38-96.183 0-0.008 0-0.018 0-0.028s-0-0.020-0-0.030l0 0.002c-0.064-0.053-0.108-0.117-0.172-0.17-0.106-0.123-0.218-0.234-0.337-0.337l-0.004-0.003c-43.965-37.601-42.63-105.454 2.782-141.265 11.117-8.651 23.938-14.535 37.36-17.488 6.716-1.478 13.596-2.249 20.497-2.214z"],"attrs":[{}],"width":839,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["noun_extension_1559208"]},"attrs":[{}],"properties":{"order":138,"id":46,"name":"plugin","prevSize":24,"code":59781},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143zM559.429 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"attrs":[{}],"width":567,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-double-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59773,"name":"angle-double-right"},"setIdx":0,"setId":1,"iconIdx":29},{"icon":{"paths":["M358.286 786.286c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143zM577.714 786.286c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143z"],"attrs":[{}],"width":603,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-double-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":24,"code":59774,"name":"angle-double-left"},"setIdx":0,"setId":1,"iconIdx":30},{"icon":{"paths":["M801.714 168.571c5.714 13.714 2.857 29.714-8 40l-281.714 281.714v424c0 14.857-9.143 28-22.286 33.714-4.571 1.714-9.714 2.857-14.286 2.857-9.714 0-18.857-3.429-25.714-10.857l-146.286-146.286c-6.857-6.857-10.857-16-10.857-25.714v-277.714l-281.714-281.714c-10.857-10.286-13.714-26.286-8-40 5.714-13.143 18.857-22.286 33.714-22.286h731.429c14.857 0 28 9.143 33.714 22.286z"],"attrs":[{}],"width":805,"isMulticolor":false,"isMulticolor2":false,"tags":["filter"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59768,"name":"filter-filled"},"setIdx":0,"setId":1,"iconIdx":31},{"icon":{"paths":["M950.857 932.571v-621.714c0-9.714-8.571-18.286-18.286-18.286h-621.714c-9.714 0-18.286 8.571-18.286 18.286v621.714c0 9.714 8.571 18.286 18.286 18.286h621.714c9.714 0 18.286-8.571 18.286-18.286zM1024 310.857v621.714c0 50.286-41.143 91.429-91.429 91.429h-621.714c-50.286 0-91.429-41.143-91.429-91.429v-621.714c0-50.286 41.143-91.429 91.429-91.429h621.714c50.286 0 91.429 41.143 91.429 91.429zM804.571 91.429v91.429h-73.143v-91.429c0-9.714-8.571-18.286-18.286-18.286h-621.714c-9.714 0-18.286 8.571-18.286 18.286v621.714c0 9.714 8.571 18.286 18.286 18.286h91.429v73.143h-91.429c-50.286 0-91.429-41.143-91.429-91.429v-621.714c0-50.286 41.143-91.429 91.429-91.429h621.714c50.286 0 91.429 41.143 91.429 91.429z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["clone"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59754,"name":"clone"},"setIdx":0,"setId":1,"iconIdx":32},{"icon":{"paths":["M498.787 330.323v-49.548h112.31v-66.065c0-49.548-39.639-89.187-89.187-89.187s-89.187 39.639-89.187 89.187v541.729l89.187 161.858 89.187-161.858v-426.116z","M360.052 716.8h-66.065c-59.458 0-105.703-46.245-105.703-105.703v-254.348c0-59.458 46.245-105.703 105.703-105.703h66.065v-42.942h-66.065c-82.581 0-148.645 66.065-148.645 148.645v254.348c0 82.581 66.065 148.645 148.645 148.645h66.065z","M852.232 260.955c-26.426-33.032-66.065-52.852-109.006-52.852h-59.458v42.942h39.639c42.942 0 82.581 19.819 109.006 52.852l145.342 181.677-142.039 178.374c-26.426 33.032-69.368 52.852-112.31 52.852h-36.335v42.942h56.155c42.942 0 85.884-19.819 112.31-52.852l178.374-221.316z"],"width":1140,"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Tags"],"grid":14},"attrs":[{},{},{}],"properties":{"order":119,"id":1,"name":"control-Tags","prevSize":24,"code":59747},"setIdx":0,"setId":1,"iconIdx":33},{"icon":{"paths":["M384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM998.4 844.8h-614.4c-38.406 15.539-22.811 37.543 0 51.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z","M0 0v307.2h307.2v-307.2zM47.4 47.4h212.4v212.4h-212.4z","M0 716.8v307.2h307.2v-307.2zM47.4 764.2h212.4v212.4h-212.4z","M0 358.4v307.2h307.2v-307.2zM47.4 405.8h212.4v212.4h-212.4z","M89.6 89.6h128v128h-128v-128z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Checkboxes"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":2,"name":"control-Checkboxes, control-List","prevSize":24,"code":59746},"setIdx":0,"setId":1,"iconIdx":34},{"icon":{"paths":["M159.073 665.6l-159.073-134.055 159.073-133.819 36.818 37.29-117.062 96.057 117.062 97.237z","M493.247 536.029q0 33.042-9.441 57.115-9.205 24.073-25.961 40.122-16.521 15.813-39.178 23.601-22.657 7.552-49.327 7.552-26.197 0-48.855-4.012-22.421-3.776-42.954-10.385v-323.338h57.587v78.356l-2.36 47.203q12.981-16.757 30.21-26.905 17.465-10.149 41.774-10.149 21.241 0 37.762 8.496t27.614 24.309q11.329 15.577 17.229 37.998 5.9 22.185 5.9 50.035zM432.828 538.389q0-19.825-2.832-33.75t-8.26-22.893q-5.192-8.969-12.981-12.981-7.552-4.248-17.465-4.248-14.633 0-28.086 11.801-13.217 11.801-28.086 32.098v104.79q6.844 2.596 16.757 4.248 10.149 1.652 20.533 1.652 13.689 0 24.781-5.664 11.329-5.664 19.117-16.049 8.024-10.385 12.273-25.253 4.248-15.105 4.248-33.75z","M700.682 513.608q0.472-13.453-1.416-22.893-1.652-9.441-5.664-15.577-3.776-6.136-9.441-8.968t-12.981-2.832q-12.745 0-26.433 10.621-13.453 10.385-29.738 34.458v151.756h-59.003v-239.789h52.159l2.124 34.93q5.9-9.205 13.217-16.521 7.552-7.316 16.521-12.509 9.205-5.428 20.297-8.26t24.309-2.832q18.173 0 32.098 6.372 14.161 6.136 23.601 18.409 9.677 12.273 14.161 30.918 4.72 18.409 4.012 42.718z","M864.927 397.725l159.073 133.819-159.073 134.055-36.582-37.29 116.826-96.293-116.826-97.001z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Html"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":116,"id":3,"name":"control-Html","prevSize":24,"code":59744},"setIdx":0,"setId":1,"iconIdx":35},{"icon":{"paths":["M251.429 100.58c-87.896 0-160 72.104-160 160v525.714c0 87.896 72.104 160 160 160h525.714c87.896 0 160-72.104 160-160v-525.714c0-87.896-72.104-160-160-160zM251.429 146.295h525.714c62.961 0 114.286 51.325 114.286 114.286v525.714c0 62.961-51.325 114.286-114.286 114.286h-525.714c-62.961 0-114.286-51.325-114.286-114.286v-525.714c0-62.961 51.325-114.286 114.286-114.286z","M251.429 306.295c-0.096-0.001-0.21-0.002-0.323-0.002-12.625 0-22.859 10.235-22.859 22.859s10.235 22.859 22.859 22.859c0.114 0 0.227-0.001 0.34-0.002l-0.017 0h525.714c0.096 0.001 0.21 0.002 0.323 0.002 12.625 0 22.859-10.235 22.859-22.859s-10.235-22.859-22.859-22.859c-0.114 0-0.227 0.001-0.34 0.002l0.017-0z","M251.429 443.438c-0.096-0.001-0.21-0.002-0.323-0.002-12.625 0-22.859 10.235-22.859 22.859s10.235 22.859 22.859 22.859c0.114 0 0.227-0.001 0.34-0.002l-0.017 0h297.143c0.096 0.001 0.21 0.002 0.323 0.002 12.625 0 22.859-10.235 22.859-22.859s-10.235-22.859-22.859-22.859c-0.114 0-0.227 0.001-0.34 0.002l0.017-0z","M251.429 580.58c-0.096-0.001-0.21-0.002-0.323-0.002-12.625 0-22.859 10.235-22.859 22.859s10.235 22.859 22.859 22.859c0.114 0 0.227-0.001 0.34-0.002l-0.017 0h297.143c0.096 0.001 0.21 0.002 0.323 0.002 12.625 0 22.859-10.235 22.859-22.859s-10.235-22.859-22.859-22.859c-0.114 0-0.227 0.001-0.34 0.002l0.017-0z"],"width":1029,"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["single-content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":112,"id":4,"name":"single-content, search-Content","prevSize":24,"code":59736},"setIdx":0,"setId":1,"iconIdx":36},{"icon":{"paths":["M777.143 946.286h-525.714c-89.143 0-160-70.857-160-160v-297.143c0-89.143 70.857-160 160-160h525.714c89.143 0 160 70.857 160 160v297.143c0 89.143-70.857 160-160 160zM251.429 374.857c-64 0-114.286 50.286-114.286 114.286v297.143c0 64 50.286 114.286 114.286 114.286h525.714c64 0 114.286-50.286 114.286-114.286v-297.143c0-64-50.286-114.286-114.286-114.286h-525.714z","M731.429 580.571h-457.143c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h457.143c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M502.857 740.571h-228.571c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h228.571c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M777.143 260.571h-525.714c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h525.714c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M685.714 146.286h-342.857c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h342.857c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z"],"width":1029,"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["multiple-content"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":5,"name":"multiple-content","prevSize":24,"code":59735},"setIdx":0,"setId":1,"iconIdx":37},{"icon":{"paths":["M832 268.8h-657.92c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h657.92c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 453.12h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 642.56h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 832h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-Array"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":108,"id":6,"name":"type-Array","prevSize":24,"code":59734},"setIdx":0,"setId":1,"iconIdx":38},{"icon":{"paths":["M292.571 713.143v128c0 20-16.571 36.571-36.571 36.571h-146.286c-20 0-36.571-16.571-36.571-36.571v-128c0-20 16.571-36.571 36.571-36.571h146.286c20 0 36.571 16.571 36.571 36.571zM309.714 109.714l-16 438.857c-0.571 20-17.714 36.571-37.714 36.571h-146.286c-20 0-37.143-16.571-37.714-36.571l-16-438.857c-0.571-20 15.429-36.571 35.429-36.571h182.857c20 0 36 16.571 35.429 36.571z"],"width":366,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":24,"code":59733,"name":"exclamation"},"setIdx":0,"setId":1,"iconIdx":39},{"icon":{"paths":["M512 26.38l-424.96 242.8v485.64l424.96 242.8 424.96-242.8v-485.64l-424.96-242.8zM512 235.52l245.76 138.24v276.48l-245.76 138.24-245.76-138.24v-276.48l245.76-138.24z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["orleans"],"grid":14},"attrs":[{}],"properties":{"order":99,"id":8,"name":"orleans","prevSize":24,"code":59723},"setIdx":0,"setId":1,"iconIdx":40},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v204.8h51.2v-204.8h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-307.2v51.2h307.2c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4z","M153.6 640v281.6h358.4v-281.6zM179.2 640v-76.8c0-84.48 69.12-153.6 153.6-153.6s153.6 69.12 153.6 153.6v76.8h-51.2v-76.8c0-56.32-46.080-102.4-102.4-102.4s-102.4 46.080-102.4 102.4v76.8z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-lock"],"grid":14},"attrs":[{},{}],"properties":{"order":97,"id":9,"name":"document-lock","prevSize":24,"code":59721},"setIdx":0,"setId":1,"iconIdx":41},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v153.6h51.2v-153.6h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7z","M102.4 357.532h460.8v52.068h-460.8v-52.068z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-unpublish"],"grid":14},"attrs":[{},{}],"properties":{"order":96,"id":10,"name":"document-unpublish","prevSize":24,"code":59711},"setIdx":0,"setId":1,"iconIdx":42},{"icon":{"paths":["M614.286 420.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8-5.714 13.143-5.714 4.571 0 9.714 2.286 13.143 5.714l224.571 224.571 224.571-224.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":24,"code":59648,"name":"angle-down"},"setIdx":0,"setId":1,"iconIdx":43},{"icon":{"paths":["M358.286 310.857c0 4.571-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8 5.714 13.143z"],"width":384,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":12,"prevSize":24,"code":59649,"name":"angle-left"},"setIdx":0,"setId":1,"iconIdx":44},{"icon":{"paths":["M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8-5.714-13.143 0-4.571 2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":347,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":13,"prevSize":24,"code":59697,"name":"angle-right"},"setIdx":0,"setId":1,"iconIdx":45},{"icon":{"paths":["M614.286 676.571c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8 5.714-13.143 5.714-4.571 0-9.714-2.286-13.143-5.714l-224.571-224.571-224.571 224.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":14,"prevSize":24,"code":59651,"name":"angle-up"},"setIdx":0,"setId":1,"iconIdx":46},{"icon":{"paths":["M592 393.6h-156.8c-57.6 0-105.6-48-105.6-105.6v-182.4c0-57.6 48-105.6 105.6-105.6h156.8c57.6 0 105.6 48 105.6 105.6v182.4c-3.2 57.6-48 105.6-105.6 105.6zM432 64c-22.4 0-41.6 19.2-41.6 41.6v182.4c0 22.4 19.2 41.6 41.6 41.6h156.8c22.4 0 41.6-19.2 41.6-41.6v-182.4c0-22.4-19.2-41.6-41.6-41.6h-156.8z","M195.2 1024c-105.6 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c3.2 105.6-86.4 195.2-195.2 195.2zM195.2 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 134.4 131.2 134.4 73.6 0 131.2-60.8 131.2-131.2 3.2-73.6-57.6-134.4-131.2-134.4z","M828.8 1024c-108.8 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c0 105.6-89.6 195.2-195.2 195.2zM828.8 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 131.2 131.2 131.2 73.6 0 131.2-60.8 131.2-131.2s-60.8-131.2-131.2-131.2z","M332.8 640c-6.4 0-12.8 0-16-3.2-16-9.6-19.2-28.8-9.6-44.8l83.2-137.6c9.6-16 28.8-19.2 44.8-9.6s19.2 28.8 9.6 44.8l-83.2 137.6c-6.4 6.4-16 12.8-28.8 12.8z","M691.2 640c-9.6 0-22.4-6.4-28.8-16l-83.2-137.6c-9.6-16-3.2-35.2 9.6-44.8s35.2-3.2 44.8 9.6l83.2 137.6c9.6 16 3.2 35.2-9.6 44.8-6.4 6.4-12.8 6.4-16 6.4z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["api"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":15,"name":"api","prevSize":24,"code":59717},"setIdx":0,"setId":1,"iconIdx":47},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M771.2 860.8h-438.4c-12.8 0-22.4-6.4-28.8-19.2s-3.2-25.6 3.2-35.2l300.8-355.2c6.4-6.4 16-12.8 25.6-12.8s19.2 6.4 25.6 12.8l192 275.2c3.2 3.2 3.2 6.4 3.2 9.6 16 44.8 3.2 73.6-6.4 89.6-22.4 32-70.4 35.2-76.8 35.2zM403.2 796.8h371.2c6.4 0 22.4-3.2 25.6-9.6 3.2-3.2 3.2-12.8 0-25.6l-166.4-236.8-230.4 272z","M332.8 502.4c-76.8 0-140.8-64-140.8-140.8s64-140.8 140.8-140.8 140.8 64 140.8 140.8-60.8 140.8-140.8 140.8zM332.8 284.8c-41.6 0-76.8 32-76.8 76.8s35.2 76.8 76.8 76.8 76.8-35.2 76.8-76.8-32-76.8-76.8-76.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["assets"],"grid":14},"attrs":[{},{},{}],"properties":{"order":95,"id":16,"name":"assets, search-Asset","prevSize":24,"code":59720},"setIdx":0,"setId":1,"iconIdx":48},{"icon":{"paths":["M932.571 548.571c0 20-16.571 36.571-36.571 36.571h-128c0 71.429-15.429 125.143-38.286 165.714l118.857 119.429c14.286 14.286 14.286 37.143 0 51.429-6.857 7.429-16.571 10.857-25.714 10.857s-18.857-3.429-25.714-10.857l-113.143-112.571s-74.857 68.571-172 68.571v-512h-73.143v512c-103.429 0-178.857-75.429-178.857-75.429l-104.571 118.286c-7.429 8-17.143 12-27.429 12-8.571 0-17.143-2.857-24.571-9.143-14.857-13.714-16-36.571-2.857-52l115.429-129.714c-20-39.429-33.143-90.286-33.143-156.571h-128c-20 0-36.571-16.571-36.571-36.571s16.571-36.571 36.571-36.571h128v-168l-98.857-98.857c-14.286-14.286-14.286-37.143 0-51.429s37.143-14.286 51.429 0l98.857 98.857h482.286l98.857-98.857c14.286-14.286 37.143-14.286 51.429 0s14.286 37.143 0 51.429l-98.857 98.857v168h128c20 0 36.571 16.571 36.571 36.571zM658.286 219.429h-365.714c0-101.143 81.714-182.857 182.857-182.857s182.857 81.714 182.857 182.857z"],"width":951,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":17,"prevSize":24,"code":59709,"name":"bug"},"setIdx":0,"setId":1,"iconIdx":49},{"icon":{"paths":["M585.143 402.286c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857s-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714 0-20 16.571-36.571 36.571-36.571h512c20 0 36.571 16.571 36.571 36.571z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":18,"prevSize":24,"code":59692,"name":"caret-down"},"setIdx":0,"setId":1,"iconIdx":50},{"icon":{"paths":["M365.714 256v512c0 20-16.571 36.571-36.571 36.571-9.714 0-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714s4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857 20 0 36.571 16.571 36.571 36.571z"],"width":402,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":24,"code":59690,"name":"caret-left"},"setIdx":0,"setId":1,"iconIdx":51},{"icon":{"paths":["M329.143 512c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857-20 0-36.571-16.571-36.571-36.571v-512c0-20 16.571-36.571 36.571-36.571 9.714 0 18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":329,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":20,"prevSize":24,"code":59689,"name":"caret-right"},"setIdx":0,"setId":1,"iconIdx":52},{"icon":{"paths":["M585.143 694.857c0 20-16.571 36.571-36.571 36.571h-512c-20 0-36.571-16.571-36.571-36.571 0-9.714 4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857s18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":21,"prevSize":24,"code":59691,"name":"caret-up"},"setIdx":0,"setId":1,"iconIdx":53},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M480 448h-211.2c-57.6 0-105.6-48-105.6-105.6v-73.6c0-57.6 48-105.6 105.6-105.6h211.2c57.6 0 105.6 48 105.6 105.6v73.6c0 57.6-48 105.6-105.6 105.6zM268.8 227.2c-22.4 0-41.6 19.2-41.6 41.6v73.6c0 22.4 19.2 41.6 41.6 41.6h211.2c22.4 0 41.6-19.2 41.6-41.6v-73.6c0-22.4-19.2-41.6-41.6-41.6h-211.2z","M828.8 611.2h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M553.6 777.6h-358.4c-19.2 0-32-12.8-32-32s12.8-32 32-32h355.2c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":93,"id":22,"name":"contents, trigger-ContentChanged","prevSize":24,"code":59718},"setIdx":0,"setId":1,"iconIdx":54},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date"],"grid":14},"attrs":[{}],"properties":{"order":71,"id":23,"name":"control-Date","prevSize":24,"code":59702},"setIdx":0,"setId":1,"iconIdx":55},{"icon":{"paths":["M486.4 409.6h51.2c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM230.4 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM230.4 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM51.2 742.4v-435.2h665.6v102.4h51.2v-281.6c0-42.342-34.458-76.8-76.8-76.8h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-256v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v614.4c0 42.342 34.458 76.8 76.8 76.8h332.8v-51.2h-332.8c-14.080 0-25.6-11.469-25.6-25.6zM51.2 128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h256v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128h-665.6v-128zM384 409.6c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM742.4 460.8c-155.546 0-281.6 126.054-281.6 281.6s126.054 281.6 281.6 281.6 281.6-126.054 281.6-281.6-126.054-281.6-281.6-281.6zM742.4 972.8c-127.232 0-230.4-103.168-230.4-230.4s103.168-230.4 230.4-230.4 230.4 103.168 230.4 230.4-103.168 230.4-230.4 230.4zM384 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM384 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM844.8 716.8c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-102.4c-14.131 0-25.6-11.469-25.6-25.6v-102.4c0-14.131 11.469-25.6 25.6-25.6s25.6 11.469 25.6 25.6v76.8h76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date-time"],"grid":14},"attrs":[{}],"properties":{"order":70,"id":24,"name":"control-DateTime","prevSize":24,"code":59703},"setIdx":0,"setId":1,"iconIdx":56},{"icon":{"paths":["M793.6 609.416h-61.838v-28.108h-0.783q-21.135 33.092-62.034 33.092-37.573 0-60.469-26.912-22.896-27.112-22.896-75.554 0-50.635 25.244-81.136t66.144-30.501q38.747 0 54.011 28.308h0.783v-121.405h61.838v302.216zM732.936 510.139v-15.35q0-19.935-11.35-33.092t-29.549-13.157q-20.548 0-32.093 16.546-11.546 16.347-11.546 45.053 0 26.912 11.154 41.465t30.919 14.553q18.786 0 30.528-15.35 11.937-15.35 11.937-40.668zM548.594 609.416h-61.643v-116.421q0-44.455-32.093-44.455-15.264 0-24.853 13.357t-9.589 33.292v114.228h-61.839v-117.617q0-43.259-31.506-43.259-15.851 0-25.44 12.758-9.393 12.758-9.393 34.687v113.431h-61.838v-204.135h61.838v31.896h0.783q9.589-16.347 26.81-26.514 17.417-10.366 37.964-10.366 42.465 0 58.12 38.076 22.896-38.076 67.318-38.076 65.361 0 65.361 82.133v126.987zM0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8zM819.2 0v204.8h204.8v-204.8zM51.2 51.2h102.4v102.4h-102.4zM870.4 51.2h102.4v102.4h-102.4zM281.6 76.8v51.2h102.4v-51.2zM486.4 76.8v51.2h102.4v-51.2zM691.2 76.8v51.2h102.4v-51.2zM896 281.6v102.4h51.2v-102.4zM76.8 384v102.4h51.2v-102.4zM896 486.4v102.4h51.2v-102.4zM76.8 588.8v102.4h51.2v-102.4zM896 691.2v102.4h51.2v-102.4zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8zM51.2 870.4h102.4v102.4h-102.4zM870.4 870.4h102.4v102.4h-102.4zM384 896v51.2h102.4v-51.2zM588.8 896v51.2h102.4v-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Markdown"],"grid":14},"attrs":[{}],"properties":{"order":72,"id":25,"name":"control-Markdown","prevSize":24,"code":59704},"setIdx":0,"setId":1,"iconIdx":57},{"icon":{"paths":["M292.571 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857z"],"width":1024,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["th"],"defaultCode":61450,"grid":14},"attrs":[],"properties":{"name":"grid","id":26,"order":83,"prevSize":24,"code":61450},"setIdx":0,"setId":1,"iconIdx":58},{"icon":{"paths":["M877.714 768v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 475.429v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 182.857v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571z"],"width":877.7142857142857,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["bars","navicon","reorder"],"defaultCode":61641,"grid":14},"attrs":[],"properties":{"name":"list1","id":27,"order":89,"prevSize":24,"code":61641},"setIdx":0,"setId":1,"iconIdx":59},{"icon":{"paths":["M512 64c-131.696 0-239.125 107.4-239.125 239 0 65.8 24.831 146.717 65.375 215.25 19.653 33.221 43.902 63.853 71.75 87.125-59.423 7.524-122.009 9.415-172.125 32-79.809 35.967-144.343 94.74-172.375 178.625-1.5 9.499 0 0-1.5 9v0.499c0 73.995 60.563 134.501 134.375 134.501h627.125c73.888 0 134.5-60.506 134.5-134.5l-1.5-9.375c-27.845-84.263-92.273-143.119-172.125-179-50.17-22.544-112.844-24.421-172.375-31.875 27.792-23.26 52.002-53.831 71.625-87 40.544-68.533 65.375-149.45 65.375-215.25 0-131.6-107.304-239-239-239zM512 124c99.241 0 179 79.875 179 179 0 49.562-21.877 125.381-57 184.75s-81.435 98.75-122 98.75c-40.565 0-86.877-39.381-122-98.75s-57.125-135.188-57.125-184.75c0-99.125 79.884-179 179.125-179zM512 646.5c92.551 0 180.829 14.406 249.75 45.375 66.784 30.009 113.649 74.724 136.5 137.75-2.447 39.259-32.9 70.375-72.75 70.375h-627.125c-39.678 0-70.116-31.051-72.625-70.25 22.978-62.705 69.953-107.523 136.75-137.625 68.937-31.067 157.205-45.625 249.5-45.625z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user-o"],"grid":14},"attrs":[{}],"properties":{"order":64,"id":28,"name":"user-o","prevSize":24,"code":59698},"setIdx":0,"setId":1,"iconIdx":60},{"icon":{"paths":["M217.6 992c-3.2 0-3.2 0-6.4 0h-3.2c-144-25.6-208-144-208-249.6 0-99.2 57.6-208 185.6-240v-147.2c0-19.2 12.8-32 32-32s32 12.8 32 32v172.8c0 16-12.8 28.8-25.6 32-108.8 16-160 102.4-160 182.4s48 166.4 153.6 185.6h6.4c16 3.2 28.8 19.2 25.6 38.4-3.2 16-16 25.6-32 25.6z","M774.4 1001.6c0 0 0 0 0 0-102.4 0-211.2-60.8-243.2-185.6h-176c-19.2 0-32-12.8-32-32s12.8-32 32-32h201.6c16 0 28.8 12.8 32 25.6 16 108.8 102.4 156.8 182.4 160 80 0 166.4-48 185.6-153.6v-3.2c3.2-16 19.2-28.8 38.4-25.6 16 3.2 28.8 19.2 25.6 38.4v3.2c-22.4 140.8-140.8 204.8-246.4 204.8z","M787.2 678.4c-19.2 0-32-12.8-32-32v-176c0-16 12.8-28.8 25.6-32 108.8-16 156.8-102.4 160-182.4 0-80-48-166.4-153.6-185.6h-3.2c-19.2-6.4-32-22.4-28.8-38.4s19.2-28.8 38.4-25.6h3.2c144 25.6 208 144 208 249.6 0 99.2-60.8 208-185.6 240v150.4c0 16-16 32-32 32z","M41.6 246.4c-3.2 0-3.2 0-6.4 0-16-3.2-28.8-19.2-25.6-35.2v-3.2c25.6-144 140.8-208 246.4-208 0 0 3.2 0 3.2 0 99.2 0 208 60.8 240 185.6h147.2c19.2 0 32 12.8 32 32s-12.8 32-32 32h-172.8c-16 0-28.8-12.8-32-25.6-16-108.8-102.4-156.8-182.4-160-80 0-166.4 48-185.6 153.6v3.2c-3.2 16-16 25.6-32 25.6z","M256 387.2c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-25.6 22.4-57.6 35.2-92.8 35.2zM256 192c-16 0-32 6.4-44.8 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-32-19.2-44.8-28.8-19.2-48-19.2z","M771.2 873.6c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-25.6 57.6-38.4 92.8-38.4s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-28.8 25.6-60.8 38.4-92.8 38.4zM771.2 678.4c-19.2 0-35.2 6.4-48 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-35.2-19.2-48-28.8-16-44.8-16z","M745.6 387.2c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 60.8-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM745.6 192c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z","M259.2 873.6c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM259.2 678.4c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z"],"attrs":[{},{},{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["webhooks"],"grid":14},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":29,"name":"rules, search-Rule","prevSize":24,"code":59719},"setIdx":0,"setId":1,"iconIdx":61},{"icon":{"paths":["M470 384l60 60-154 154h392v-428h86v512h-478l154 154-60 60-256-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["subdirectory_arrow_left"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59780,"name":"enter"},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M298 384h214v42h-214v-42zM406 598q80 0 136-56t56-136-56-136-136-56-136 56-56 136 56 136 136 56zM662 598l212 212-64 64-212-212v-34l-12-12q-76 66-180 66-116 0-197-80t-81-196 81-197 197-81 196 81 80 197q0 42-20 95t-46 85l12 12h34z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["zoom_out"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":4,"prevSize":24,"code":59778,"name":"zoom_out"},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M512 426h-86v86h-42v-86h-86v-42h86v-86h42v86h86v42zM406 598q80 0 136-56t56-136-56-136-136-56-136 56-56 136 56 136 136 56zM662 598l212 212-64 64-212-212v-34l-12-12q-76 66-180 66-116 0-197-80t-81-196 81-197 197-81 196 81 80 197q0 42-20 95t-46 85l12 12h34z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["zoom_in"],"grid":24},"attrs":[{}],"properties":{"order":2,"id":3,"prevSize":24,"code":59779,"name":"zoom_in"},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M810 896v-86h86q0 34-26 60t-60 26zM810 554v-84h86v84h-86zM640 214v-86h86v86h-86zM810 726v-86h86v86h-86zM470 982v-940h84v940h-84zM810 128q34 0 60 26t26 60h-86v-86zM128 214q0-34 26-60t60-26h170v86h-170v596h170v86h-170q-34 0-60-26t-26-60v-596zM810 384v-86h86v86h-86zM640 896v-86h86v86h-86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["flip"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":2,"name":"flip","prevSize":24,"code":59775},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M720 660q34-46 44-106h86q-12 92-68 166zM554 764q60-10 106-44l62 62q-72 56-168 68v-86zM850 470h-86q-10-60-44-106l62-60q58 72 68 166zM664 236l-194 190v-166q-92 16-153 87t-61 165 61 165 153 87v86q-126-16-213-112t-87-226 87-226 213-112v-132z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["rotate_right"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"name":"rotate_right","prevSize":24,"code":59776},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M554 174q126 16 213 112t87 226-87 226-213 112v-86q92-16 153-87t61-165-61-165-153-87v166l-194-190 194-194v132zM302 782l62-62q46 34 106 44v86q-96-12-168-68zM260 554q10 58 42 106l-60 60q-56-74-68-166h86zM304 364q-36 52-44 106h-86q12-90 70-166z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["rotate_left"],"grid":24},"attrs":[{}],"properties":{"order":2,"id":0,"name":"rotate_left","prevSize":24,"code":59777},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M810 598v-86h-128v-128h-84v128h-128v86h128v128h84v-128h128zM854 256q36 0 60 25t24 61v426q0 36-24 61t-60 25h-684q-36 0-60-25t-24-61v-512q0-36 24-61t60-25h256l86 86h342z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["create_new_folder"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59771,"name":"create_new_folder"},"setIdx":0,"setId":1,"iconIdx":11},{"icon":{"paths":["M426 170l86 86h342q34 0 59 26t25 60v426q0 34-25 60t-59 26h-684q-34 0-59-26t-25-60v-512q0-34 25-60t59-26h256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["folder"],"grid":24},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":24,"code":59772,"name":"folder"},"setIdx":0,"setId":1,"iconIdx":12},{"icon":{"paths":["M512 256q70 0 120 50t50 120q0 54-64 111t-64 103h-84q0-46 20-79t44-48 44-37 20-50q0-34-26-59t-60-25-60 25-26 59h-84q0-70 50-120t120-50zM512 854q140 0 241-101t101-241-101-241-241-101-241 101-101 241 101 241 241 101zM512 86q176 0 301 125t125 301-125 301-301 125-301-125-125-301 125-301 301-125zM470 768v-86h84v86h-84z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["help_outline"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59770,"name":"help2"},"setIdx":0,"setId":1,"iconIdx":13},{"icon":{"paths":["M236.416 92.117c-6.528-4.267-14.507-6.784-23.083-6.784-23.552 0-42.667 19.115-42.667 42.667v768c-0.043 7.765 2.133 15.872 6.784 23.083 12.757 19.84 39.125 25.557 58.965 12.8l597.333-384c4.864-3.072 9.344-7.424 12.8-12.8 12.757-19.84 6.997-46.208-12.8-58.965zM256 206.165l475.776 305.835-475.776 305.835z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59769,"name":"trigger-Manual, play-line"},"setIdx":0,"setId":1,"iconIdx":14},{"icon":{"paths":["M128 170.667v298.667c0 58.88 23.936 112.299 62.464 150.869s91.989 62.464 150.869 62.464h409.003l-140.501 140.501c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0l213.333-213.333c3.925-3.925 7.083-8.619 9.259-13.824s3.243-10.795 3.243-16.341c0-10.923-4.181-21.845-12.501-30.165l-213.333-213.333c-16.683-16.683-43.691-16.683-60.331 0s-16.683 43.691 0 60.331l140.501 140.501h-409.003c-35.371 0-67.285-14.293-90.496-37.504s-37.504-55.125-37.504-90.496v-298.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["corner-down-right"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59767,"name":"corner-down-right"},"setIdx":0,"setId":1,"iconIdx":15},{"icon":{"paths":["M470 384v-86h84v86h-84zM512 854c188 0 342-154 342-342s-154-342-342-342-342 154-342 342 154 342 342 342zM512 86c236 0 426 190 426 426s-190 426-426 426-426-190-426-426 190-426 426-426zM470 726v-256h84v256h-84z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["info_outline"],"grid":24},"attrs":[{}],"properties":{"order":128,"id":0,"prevSize":24,"code":59764,"name":"info-outline"},"setIdx":0,"setId":1,"iconIdx":16},{"icon":{"paths":["M214 768h596v86h-596v-86zM384 682v-256h-170l298-298 298 298h-170v256h-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["file_upload"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59762,"name":"upload-2"},"setIdx":0,"setId":1,"iconIdx":17},{"icon":{"paths":["M678 726h138l-70-186zM790 426l192 512h-86l-48-128h-202l-48 128h-86l192-512h86zM550 642l-34 88-132-132-214 212-60-60 218-214c-54-60-96-124-128-194h86c26 50 58 98 98 142 62-68 108-146 136-228h-478v-86h300v-84h84v84h300v86h-126c-32 100-84 196-158 278l-2 2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["translate"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59759,"name":"translate"},"setIdx":0,"setId":1,"iconIdx":18},{"icon":{"paths":["M854 470v84h-520l238 240-60 60-342-342 342-342 60 60-238 240h520z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["arrow_back"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59758,"name":"arrow_back"},"setIdx":0,"setId":1,"iconIdx":19},{"icon":{"paths":["M768 512c-25.6 0-42.667 17.067-42.667 42.667v256c0 25.6-17.067 42.667-42.667 42.667h-469.333c-25.6 0-42.667-17.067-42.667-42.667v-469.333c0-25.6 17.067-42.667 42.667-42.667h256c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-256c-72.533 0-128 55.467-128 128v469.333c0 72.533 55.467 128 128 128h469.333c72.533 0 128-55.467 128-128v-256c0-25.6-17.067-42.667-42.667-42.667z","M934.4 110.933c-4.267-8.533-12.8-17.067-21.333-21.333-4.267-4.267-12.8-4.267-17.067-4.267h-256c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h153.6l-396.8 396.8c-17.067 17.067-17.067 42.667 0 59.733 8.533 8.533 17.067 12.8 29.867 12.8s21.333-4.267 29.867-12.8l396.8-396.8v153.6c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-256c0-4.267 0-12.8-4.267-17.067z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["external-link"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":2,"prevSize":24,"code":59757,"name":"external-link"},"setIdx":0,"setId":1,"iconIdx":20},{"icon":{"paths":["M810.667 85.333h-597.333c-72.533 0-128 55.467-128 128v597.333c0 72.533 55.467 128 128 128h597.333c72.533 0 128-55.467 128-128v-597.333c0-72.533-55.467-128-128-128zM853.333 810.667c0 25.6-17.067 42.667-42.667 42.667h-597.333c-25.6 0-42.667-17.067-42.667-42.667v-597.333c0-25.6 17.067-42.667 42.667-42.667h597.333c25.6 0 42.667 17.067 42.667 42.667v597.333z","M682.667 469.333h-341.333c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h341.333c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["minus-square"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":3,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":0,"setId":1,"iconIdx":21},{"icon":{"paths":["M810.667 85.333h-597.333c-72.533 0-128 55.467-128 128v597.333c0 72.533 55.467 128 128 128h597.333c72.533 0 128-55.467 128-128v-597.333c0-72.533-55.467-128-128-128zM853.333 810.667c0 25.6-17.067 42.667-42.667 42.667h-597.333c-25.6 0-42.667-17.067-42.667-42.667v-597.333c0-25.6 17.067-42.667 42.667-42.667h597.333c25.6 0 42.667 17.067 42.667 42.667v597.333z","M682.667 469.333h-128v-128c0-25.6-17.067-42.667-42.667-42.667s-42.667 17.067-42.667 42.667v128h-128c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h128v128c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-128h128c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["plus-square"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":4,"name":"plus-square","prevSize":24,"code":59752},"setIdx":0,"setId":1,"iconIdx":22},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":5,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":0,"setId":1,"iconIdx":23},{"icon":{"paths":["M854 682v-512h-684v598l86-86h598zM854 86c46 0 84 38 84 84v512c0 46-38 86-84 86h-598l-170 170v-768c0-46 38-84 84-84h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["chat_bubble_outline"],"grid":24},"attrs":[{}],"properties":{"order":133,"id":6,"name":"comments","prevSize":24,"code":59743},"setIdx":0,"setId":1,"iconIdx":24},{"icon":{"paths":["M512 128c212 0 384 172 384 384s-172 384-384 384c-88 0-170-30-234-80l60-60c50 34 110 54 174 54 166 0 298-132 298-298s-132-298-298-298-298 132-298 298h128l-172 170-170-170h128c0-212 172-384 384-384zM598 512c0 46-40 86-86 86s-86-40-86-86 40-86 86-86 86 40 86 86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings_backup_restore"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":24,"code":59739,"name":"backup"},"setIdx":0,"setId":1,"iconIdx":25},{"icon":{"paths":["M726 512c0 24-20 42-44 42h-426l-170 172v-598c0-24 18-42 42-42h554c24 0 44 18 44 42v384zM896 256c24 0 42 18 42 42v640l-170-170h-470c-24 0-42-18-42-42v-86h554v-384h86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["question_answer"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":8,"prevSize":24,"code":59738,"name":"support"},"setIdx":0,"setId":1,"iconIdx":26},{"icon":{"paths":["M918 384v128h-128v298h-128v-298h-128v-128h384zM106 170h556v128h-214v512h-128v-512h-214v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["text_fields"],"grid":24},"attrs":[{}],"properties":{"order":75,"id":9,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":0,"setId":1,"iconIdx":27},{"icon":{"paths":["M640 85.333q78 0 149.167 30.5t122.5 81.833 81.833 122.5 30.5 149.167q0 85-35 160.667t-96.667 129.167-140 77.5l21-20.667q18-18.333 28-42.667 9.333-22.667 9.333-49.333 0-6.667-0.333-9.333 59.333-41.333 93.833-105.833t34.5-139.5q0-60.667-23.667-116t-63.667-95.333-95.333-63.667-116-23.667q-55.333 0-106.5 19.833t-90 53.833-65 81.333-33.833 101h-88.667q-70.667 0-120.667 50t-50 120.667q0 38.667 15.167 71.667t39.833 54.167 54.833 33 60.833 11.833h50q11.667 29.333 30 48l37.667 37.333h-117.667q-69.667 0-128.5-34.333t-93.167-93.167-34.333-128.5 34.333-128.5 93.167-93.167 128.5-34.333h22q26.333-74.333 79.333-132.167t126.833-90.833 155.833-33zM554.667 426.667q17.667 0 30.167 12.5t12.5 30.167v281l55-55.333q12.333-12.333 30.333-12.333 18.333 0 30.5 12.167t12.167 30.5q0 18-12.333 30.333l-128 128q-12.333 12.333-30.333 12.333t-30.333-12.333l-128-128q-12.333-13-12.333-30.333 0-17.667 12.5-30.167t30.167-12.5q18 0 30.333 12.333l55 55.333v-281q0-17.667 12.5-30.167t30.167-12.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cloud-download"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":24,"code":59710,"name":"download"},"setIdx":0,"setId":1,"iconIdx":28},{"icon":{"paths":["M512 682.667h-341.333c-5.845 0-11.349-1.152-16.299-3.2-5.205-2.133-9.899-5.333-13.867-9.301s-7.125-8.661-9.301-13.867c-2.048-4.949-3.2-10.453-3.2-16.299v-426.667c0-5.845 1.152-11.349 3.2-16.299 2.133-5.205 5.333-9.899 9.301-13.867s8.661-7.125 13.867-9.301c4.949-2.048 10.453-3.2 16.299-3.2h682.667c5.845 0 11.349 1.152 16.299 3.2 5.205 2.133 9.899 5.333 13.867 9.301s7.125 8.661 9.301 13.867c2.048 4.949 3.2 10.453 3.2 16.299v426.667c0 5.845-1.152 11.349-3.2 16.299-2.133 5.205-5.333 9.899-9.301 13.867s-8.661 7.125-13.867 9.301c-4.949 2.048-10.453 3.2-16.299 3.2zM469.333 768v85.333h-128c-23.552 0-42.667 19.115-42.667 42.667s19.115 42.667 42.667 42.667h341.333c23.552 0 42.667-19.115 42.667-42.667s-19.115-42.667-42.667-42.667h-128v-85.333h298.667c17.28 0 33.835-3.456 48.981-9.728 15.701-6.485 29.781-16 41.557-27.776s21.291-25.856 27.776-41.557c6.229-15.104 9.685-31.659 9.685-48.939v-426.667c0-17.28-3.456-33.835-9.728-48.981-6.485-15.701-16-29.781-27.776-41.557s-25.856-21.291-41.557-27.776c-15.104-6.229-31.659-9.685-48.939-9.685h-682.667c-17.28 0-33.835 3.456-48.981 9.728-15.659 6.485-29.739 16-41.515 27.776s-21.291 25.856-27.776 41.515c-6.272 15.147-9.728 31.701-9.728 48.981v426.667c0 17.28 3.456 33.835 9.728 48.981 6.485 15.701 16 29.781 27.776 41.557s25.856 21.291 41.557 27.776c15.104 6.229 31.659 9.685 48.939 9.685z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["monitor"],"grid":0},"attrs":[{}],"properties":{"order":132,"id":0,"prevSize":24,"code":59765,"name":"type-UI"},"setIdx":0,"setId":1,"iconIdx":62},{"icon":{"paths":["M66.337 575.491l276.668-171.531v-57.177l-331.627 207.614v42.189l331.627 207.614-0-57.177z","M957.663 575.49l-276.668-171.531v-57.177l331.627 207.614v42.189l-331.627 207.614 0-57.177z","M583.295 214.183l-200.825 621.623 53.007 17.527 200.837-621.623z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["prerender"],"grid":0},"attrs":[{},{},{}],"properties":{"order":114,"id":0,"name":"prerender","prevSize":24,"code":59724},"setIdx":0,"setId":1,"iconIdx":63},{"icon":{"paths":["M1024 512c0 282.77-229.23 512-512 512s-512-229.23-512-512c0-282.77 229.23-512 512-512s512 229.23 512 512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["circle"],"grid":0},"attrs":[{}],"properties":{"order":106,"id":1,"name":"circle","prevSize":24,"code":59729},"setIdx":0,"setId":1,"iconIdx":64},{"icon":{"paths":["M512 0c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h128v870.4h-128c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h307.2c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-128v-870.4h128c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.16 0-51.2 23.040-51.2 51.2v460.8c0 28.16 23.040 51.2 51.2 51.2h537.6v-51.2h-512c-15.36 0-25.6-10.24-25.6-25.6v-409.6c0-15.36 10.24-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c15.36 0 25.6 10.24 25.6 25.6v409.6c0 15.36-10.24 25.6-25.6 25.6h-204.8v51.2h230.4c28.16 0 51.2-23.040 51.2-51.2v-460.8c0-28.16-23.040-51.2-51.2-51.2h-230.4z","M386.56 606.72c0 12.8-7.68 23.040-20.48 25.6-28.16 10.24-58.88 15.36-92.16 15.36-35.84 0-66.56-10.24-84.48-25.6s-25.6-38.4-25.6-66.56 10.24-51.2 25.6-66.56c17.92-17.92 46.080-23.040 84.48-23.040h69.12v-38.4c0-35.84-25.6-53.76-64-53.76-23.040 0-46.080 7.68-69.12 20.48-2.56 2.56-5.12 2.56-10.24 2.56-10.24 0-20.48-7.68-20.48-20.48 0-7.68 2.56-12.8 10.24-17.92 30.72-20.48 61.44-25.6 92.16-25.6 56.32 0 104.96 30.72 104.96 92.16v181.76zM345.6 501.76h-69.12c-61.44 0-69.12 28.16-69.12 53.76s7.68 56.32 69.12 56.32c23.040 0 46.080-2.56 69.12-10.24v-99.84z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Slug"],"grid":0},"attrs":[{},{}],"properties":{"order":103,"id":2,"name":"control-Slug","prevSize":24,"code":59727},"setIdx":0,"setId":1,"iconIdx":65},{"icon":{"paths":["M295.954 822.751h-94.705c-47.353 0-88.786-41.434-88.786-88.786v-491.283c0-47.353 41.434-88.786 88.786-88.786h94.705v-59.191h-94.705c-82.867 0-147.977 65.11-147.977 147.977v491.283c0 82.867 65.11 147.977 147.977 147.977h94.705v-59.191z","M970.728 473.526c-82.867-171.653-201.249-378.821-272.277-378.821h-112.462v59.191h112.462c35.514 11.838 136.139 177.572 213.087 337.387-76.948 153.896-177.572 325.549-213.087 337.387h-112.462v59.191h112.462c71.029 0 183.491-207.168 272.277-384.74l5.919-11.838-5.919-17.757z","M266.358 337.341v260.462h59.191v-260.462z","M479.422 337.341v260.462h59.191v-260.462z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["Tags"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":98,"id":3,"name":"type-Tags","prevSize":24,"code":59722},"setIdx":0,"setId":1,"iconIdx":66},{"icon":{"paths":["M512 102.4c-200.4 0-366.954 144.072-402.4 334.2-0.031 0.165-0.069 0.335-0.1 0.5-2.974 16.061-4.76 32.441-5.8 49.1-0.017 0.271-0.084 0.529-0.1 0.8 0.019 0.004 0.080-0.004 0.1 0-0.503 8.31-1.3 16.564-1.3 25 0 226.202 183.398 409.6 409.6 409.6 208.165 0 379.707-155.44 405.8-356.5 0.004-0.033-0.004-0.067 0-0.1 1.94-14.978 3.124-30.16 3.4-45.6 0.044-2.487 0.4-4.903 0.4-7.4 0-226.202-183.398-409.6-409.6-409.6zM512 153.6c185.461 0 337.902 140.924 356.4 321.5-35.181-21.812-84.232-39.9-151.6-39.9-85.35 0-140.891 41.606-194.6 81.9-49.152 36.864-95.55 71.7-163.8 71.7-86.067 0-135.862-54.67-175.9-98.6-9.001-9.901-17.11-17.483-25.4-25.3 23.131-175.603 172.981-311.3 354.9-311.3zM716.8 486.4c77.828 0 125.173 28.221 152.2 52.8-13.96 185.173-168.254 331.2-357 331.2-190.097 0-345.175-148.14-357.2-335.2 41.826 45.372 102.577 104.8 203.6 104.8 85.35 0 140.891-41.606 194.6-81.9 49.152-36.915 95.55-71.7 163.8-71.7z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["activity"],"grid":0},"attrs":[{}],"properties":{"order":12,"id":4,"name":"activity, history, time","prevSize":24,"code":59652},"setIdx":0,"setId":1,"iconIdx":67},{"icon":{"paths":["M512 0c-35.392 0-64 28.608-64 64v384h-384c-35.392 0-64 28.608-64 64s28.608 64 64 64h384v384c0 35.392 28.608 64 64 64s64-28.608 64-64v-384h384c35.392 0 64-28.608 64-64s-28.608-64-64-64h-384v-384c0-35.392-28.608-64-64-64z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["add"],"grid":0},"attrs":[{}],"properties":{"order":13,"id":5,"name":"add, plus","prevSize":24,"code":59653},"setIdx":0,"setId":1,"iconIdx":68},{"icon":{"paths":["M512 102.4c-226.202 0-409.6 183.398-409.6 409.6s183.398 409.6 409.6 409.6c226.202 0 409.6-183.398 409.6-409.6s-183.398-409.6-409.6-409.6zM512 153.6c197.632 0 358.4 160.819 358.4 358.4s-160.768 358.4-358.4 358.4c-197.632 0-358.4-160.819-358.4-358.4s160.768-358.4 358.4-358.4zM691.9 333c-12.893 0.002-25.782 4.882-35.5 14.6l-222.2 221.9-67.7-67.5c-19.19-19.294-51.085-19.215-70.3 0-19.15 19.15-19.15 51.050 0 70.2 0.198 0.2 26.198 26.681 52 53 12.95 13.209 25.761 26.372 35.2 36 4.719 4.814 8.607 8.755 11.2 11.4 1.296 1.322 2.293 2.281 2.9 2.9 0.279 0.282 0.488 0.486 0.6 0.6 0.001 0.001 7.591-7.429 14.6-14.3l-14.5 14.4 0.2 0.2v0.1c19.43 19.327 51.57 19.327 71 0v-0.1l258.1-257.6c19.546-19.447 19.521-51.885-0.1-71.3-9.731-9.679-22.607-14.502-35.5-14.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle"],"grid":0},"attrs":[{}],"properties":{"order":14,"id":6,"name":"check-circle","prevSize":24,"code":59654},"setIdx":0,"setId":1,"iconIdx":69},{"icon":{"paths":["M512 1024c-282.778 0-512-229.222-512-512s229.222-512 512-512 512 229.222 512 512-229.222 512-512 512zM855.808 270.592c-19.2-19.2-50.278-19.2-69.478 0l-376.73 376.73-171.878-171.93c-19.2-19.2-50.278-19.2-69.478 0s-19.2 50.278 0 69.478c0 0 201.523 205.261 204.8 208.486 9.984 10.138 23.347 14.643 36.557 14.080 13.21 0.563 26.573-3.942 36.608-14.029 3.277-3.226 409.6-413.286 409.6-413.286 19.2-19.2 19.2-50.33 0-69.53z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle-filled"],"grid":0},"attrs":[{}],"properties":{"order":27,"id":7,"name":"check-circle-filled","prevSize":24,"code":59655},"setIdx":0,"setId":1,"iconIdx":70},{"icon":{"paths":["M601.024 512l276.736 276.736c24.512 24.576 24.512 64.384 0 89.024-24.64 24.576-64.384 24.576-89.024 0l-276.736-276.736-276.736 276.736c-24.512 24.576-64.384 24.576-89.024 0-24.512-24.64-24.512-64.448 0-89.024l276.736-276.736-276.736-276.736c-24.512-24.576-24.512-64.384 0-89.024 24.64-24.576 64.512-24.576 89.024 0l276.736 276.736 276.736-276.736c24.64-24.576 64.384-24.576 89.024 0 24.512 24.64 24.512 64.448 0 89.024l-276.736 276.736z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["close"],"grid":0},"attrs":[{}],"properties":{"order":28,"id":8,"name":"close","prevSize":24,"code":59656},"setIdx":0,"setId":1,"iconIdx":71},{"icon":{"paths":["M409.6 435.2h-153.6v51.2h153.6v-51.2zM409.6 332.8h-153.6v51.2h153.6v-51.2zM256 691.2h409.6v-51.2h-409.6v51.2zM409.6 230.4h-153.6v51.2h153.6v-51.2zM870.4 179.2h-51.2v-51.2c0-28.262-22.938-51.2-51.2-51.2h-614.4c-28.262 0-51.2 22.938-51.2 51.2v665.6c0 28.262 22.938 51.2 51.2 51.2h51.2v51.2c0 28.262 22.938 51.2 51.2 51.2h614.4c28.262 0 51.2-22.938 51.2-51.2v-665.6c0-28.262-22.938-51.2-51.2-51.2zM179.2 793.6c-14.157 0-25.6-11.443-25.6-25.6v-614.4c0-14.131 11.443-25.6 25.6-25.6h563.2c14.157 0 25.6 11.469 25.6 25.6v614.4c0 14.157-11.443 25.6-25.6 25.6h-563.2zM870.4 870.4c0 14.157-11.443 25.6-25.6 25.6h-563.2c-14.157 0-25.6-11.443-25.6-25.6v-25.6h512c28.262 0 51.2-22.938 51.2-51.2v-563.2h25.6c14.157 0 25.6 11.469 25.6 25.6v614.4zM614.4 230.4h-102.4c-28.262 0-51.2 22.938-51.2 51.2v153.6c0 28.262 22.938 51.2 51.2 51.2h102.4c28.262 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.938-51.2-51.2-51.2zM614.4 435.2h-102.4v-153.6h102.4v153.6zM256 588.8h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":0},"attrs":[{}],"properties":{"order":37,"id":9,"name":"type-References","prevSize":24,"code":59657},"setIdx":0,"setId":1,"iconIdx":72},{"icon":{"paths":["M793.6 844.8c0 14.157-11.443 25.6-25.6 25.6h-665.6c-14.131 0-25.6-11.443-25.6-25.6v-665.6c0-14.157 11.469-25.6 25.6-25.6h665.6c14.157 0 25.6 11.443 25.6 25.6v102.4h51.2v-128c0-28.262-22.938-51.2-51.2-51.2h-716.8c-28.262 0-51.2 22.938-51.2 51.2v716.8c0 28.262 22.938 51.2 51.2 51.2h716.8c28.262 0 51.2-22.938 51.2-51.2v-281.6h-51.2v256zM991.078 237.747c-9.958-9.958-26.035-9.958-35.968 0l-391.91 391.91-238.31-238.31c-9.958-9.958-26.061-9.958-35.942 0-9.958 9.907-9.958 26.010 0 35.942l254.874 254.874c0.461 0.538 0.614 1.203 1.126 1.69 5.043 5.018 11.674 7.475 18.278 7.373 6.605 0.102 13.235-2.355 18.278-7.373 0.512-0.512 0.666-1.178 1.126-1.69l408.448-408.474c9.933-9.933 9.933-26.035 0-35.942z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-checkbox"],"grid":0},"attrs":[{}],"properties":{"order":38,"id":10,"name":"control-Checkbox","prevSize":24,"code":59658},"setIdx":0,"setId":1,"iconIdx":73},{"icon":{"paths":["M51.2 0c-28.262 0-51.2 22.938-51.2 51.2v281.6c0 28.262 22.938 51.2 51.2 51.2h921.6c28.262 0 51.2-22.938 51.2-51.2v-281.6c0-28.262-22.938-51.2-51.2-51.2h-921.6zM76.8 51.2h512v281.6h-512c-14.157 0-25.6-11.443-25.6-25.6v-230.4c0-14.157 11.443-25.6 25.6-25.6zM640 51.2h307.2c14.157 0 25.6 11.443 25.6 25.6v230.4c0 14.157-11.443 25.6-25.6 25.6h-307.2v-281.6zM716.8 153.6c-0.41 0.358 89.139 102.938 89.6 102.4 0.512 0 89.6-95.36 89.6-102.4 0 0.384-172.16 0-179.2 0zM128 435.2c-42.394 0-76.8 34.406-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.406 76.8-76.8s-34.406-76.8-76.8-76.8zM128 486.4c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 486.4c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 640c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 691.2c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 691.2c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 844.8c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 896c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 896c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-dropdown"],"grid":0},"attrs":[{}],"properties":{"order":39,"id":11,"name":"control-Dropdown","prevSize":24,"code":59659},"setIdx":0,"setId":1,"iconIdx":74},{"icon":{"paths":["M512 0c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h128v870.4h-128c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h307.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-128v-870.4h128c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.262 0-51.2 22.938-51.2 51.2v460.8c0 28.262 22.938 51.2 51.2 51.2h537.6v-51.2h-512c-14.131 0-25.6-11.443-25.6-25.6v-409.6c0-14.157 11.469-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c14.157 0 25.6 11.443 25.6 25.6v409.6c0 14.157-11.443 25.6-25.6 25.6h-204.8v51.2h230.4c28.262 0 51.2-22.938 51.2-51.2v-460.8c0-28.262-22.938-51.2-51.2-51.2h-230.4zM285.9 307c-0.589 0.051-1.161 0.048-1.75 0.15-8.243 0.051-16.396 4.474-20.85 13.050l-132.55 306.25c-6.656 12.749-2.866 28.981 8.5 36.2 11.341 7.219 25.97 2.749 32.6-10l27.65-63.85h170.5c0.512 0 0.914-0.224 1.4-0.25l27.45 64.050c6.63 12.749 21.136 17.269 32.4 10.050s15.005-23.451 8.4-36.2l-131.3-306.25c-4.454-8.576-12.432-12.973-20.65-13.050-0.614-0.102-1.211-0.099-1.8-0.15zM285.9 389.15l63.65 148.45h-127.9l64.25-148.45z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-input"],"grid":0},"attrs":[{}],"properties":{"order":41,"id":12,"name":"control-Input","prevSize":24,"code":59660},"setIdx":0,"setId":1,"iconIdx":75},{"icon":{"paths":["M153.6 716.8c-84.787 0-153.6 68.813-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.813 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 972.8c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM153.6 0c-84.787 0-153.6 68.787-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.787 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 256c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 358.4c-84.787 0-153.6 68.787-153.6 153.6 0 84.787 68.813 153.6 153.6 153.6s153.6-68.813 153.6-153.6c0-84.813-68.813-153.6-153.6-153.6zM153.6 614.4c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 102.4c-28.262 0-51.2 22.938-51.2 51.2s22.938 51.2 51.2 51.2c28.262 0 51.2-22.938 51.2-51.2s-22.938-51.2-51.2-51.2zM998.4 844.8h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-radio"],"grid":0},"attrs":[{}],"properties":{"order":42,"id":13,"name":"control-Radio","prevSize":24,"code":59661},"setIdx":0,"setId":1,"iconIdx":76},{"icon":{"paths":["M0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8h-204.8zM819.2 0v204.8h204.8v-204.8h-204.8zM51.2 51.2h102.4v102.4h-102.4v-102.4zM870.4 51.2h102.4v102.4h-102.4v-102.4zM281.6 76.8v51.2h102.4v-51.2h-102.4zM486.4 76.8v51.2h102.4v-51.2h-102.4zM691.2 76.8v51.2h102.4v-51.2h-102.4zM333.25 204.8c-7.091-0.307-14.348 2.097-19.75 7.55l-74.75 74.75c-10.317 10.291-10.317 27.083 0 37.4s27.059 10.317 37.35 0l68.45-68.5h141.85v486.4h-50.7c-7.117-0.307-14.348 2.097-19.75 7.55l-23.6 23.55c-10.317 10.317-10.317 27.083 0 37.4 10.291 10.317 27.109 10.317 37.4 0l17.25-17.3h129.75l18.050 18c10.394 10.368 27.181 10.368 37.6 0 10.368-10.394 10.368-27.181 0-37.6l-24-24c-5.478-5.478-12.682-7.907-19.85-7.6h-50.95v-486.4h141.55l69.25 69.2c10.394 10.368 27.155 10.368 37.6 0 10.368-10.368 10.368-27.181 0-37.6l-75.2-75.2c-5.478-5.478-12.706-7.907-19.9-7.6h-357.65zM896 281.6v102.4h51.2v-102.4h-51.2zM76.8 384v102.4h51.2v-102.4h-51.2zM896 486.4v102.4h51.2v-102.4h-51.2zM76.8 588.8v102.4h51.2v-102.4h-51.2zM896 691.2v102.4h51.2v-102.4h-51.2zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6h-51.2zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8h-204.8zM51.2 870.4h102.4v102.4h-102.4v-102.4zM870.4 870.4h102.4v102.4h-102.4v-102.4zM384 896v51.2h102.4v-51.2h-102.4zM588.8 896v51.2h102.4v-51.2h-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-textarea"],"grid":0},"attrs":[{}],"properties":{"order":17,"id":14,"name":"control-TextArea","prevSize":24,"code":59662},"setIdx":0,"setId":1,"iconIdx":77},{"icon":{"paths":["M332.8 25.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 76.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM332.8 128c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM332.8 179.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8zM332.8 537.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 588.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM691.2 640c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM691.2 691.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-toggle"],"grid":0},"attrs":[{}],"properties":{"order":16,"id":15,"name":"control-Toggle","prevSize":24,"code":59663},"setIdx":0,"setId":1,"iconIdx":78},{"icon":{"paths":["M204.8 51.2c-56.525 0-102.4 45.875-102.4 102.4v512c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4h-409.6zM204.8 102.4h409.6c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2v-512c0-28.314 22.938-51.2 51.2-51.2zM768 204.8v51.2c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2h-51.2c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["copy"],"grid":0},"attrs":[{}],"properties":{"order":90,"id":16,"name":"copy","prevSize":24,"code":59664},"setIdx":0,"setId":1,"iconIdx":79},{"icon":{"paths":["M828.8 1024h-633.6c-105.6 0-195.2-89.6-195.2-195.2v-320c0-281.6 227.2-508.8 505.6-508.8 288 0 518.4 230.4 518.4 518.4v310.4c0 105.6-89.6 195.2-195.2 195.2zM505.6 64c-243.2 0-441.6 198.4-441.6 441.6v320c0 73.6 60.8 134.4 131.2 134.4h630.4c73.6 0 131.2-60.8 131.2-131.2v-310.4c3.2-249.6-201.6-454.4-451.2-454.4z","M512 668.8c-3.2 0-6.4 0-6.4 0-32-3.2-64-19.2-80-48l-192-278.4c-9.6-9.6-9.6-25.6-0-38.4 9.6-9.6 25.6-12.8 38.4-6.4l294.4 172.8c28.8 16 48 44.8 51.2 76.8s-6.4 64-28.8 89.6c-19.2 22.4-48 32-76.8 32zM364.8 428.8l108.8 160c6.4 9.6 19.2 19.2 32 19.2s25.6-3.2 35.2-12.8c9.6-9.6 12.8-22.4 9.6-35.2s-9.6-22.4-19.2-32l-166.4-99.2z","M678.4 364.8c-6.4 0-12.8-3.2-19.2-6.4-16-9.6-19.2-28.8-9.6-44.8l54.4-83.2c9.6-16 28.8-19.2 44.8-9.6 19.2 12.8 22.4 35.2 12.8 48l-54.4 83.2c-6.4 9.6-16 12.8-28.8 12.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["dashboard"],"grid":0},"attrs":[{},{},{}],"properties":{"order":26,"id":17,"name":"dashboard, search-Dashboard","prevSize":24,"code":59665},"setIdx":0,"setId":1,"iconIdx":80},{"icon":{"paths":["M597.35 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.418 25.6 25.6 25.6zM776.55 204.8h-153.6v-51.2c0-28.314-22.886-51.2-51.2-51.2h-102.4c-28.262 0-51.2 22.886-51.2 51.2v51.2h-153.6c-28.262 0-51.2 22.886-51.2 51.2v102.4c0 28.314 22.938 51.2 51.2 51.2v460.8c0 28.314 22.938 51.2 51.2 51.2h409.6c28.314 0 51.2-22.886 51.2-51.2v-460.8c28.314 0 51.2-22.886 51.2-51.2v-102.4c0-28.314-22.938-51.2-51.2-51.2zM469.35 153.6h102.4v51.2h-102.4v-51.2zM725.35 870.4h-409.6v-460.8h409.6v460.8zM776.55 358.4h-512v-102.4h512v102.4zM443.75 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete"],"grid":0},"attrs":[{}],"properties":{"order":29,"id":18,"name":"delete, bin","prevSize":24,"code":59666},"setIdx":0,"setId":1,"iconIdx":81},{"icon":{"paths":["M832 128h-192v-64c0-35.392-28.608-64-64-64h-128c-35.328 0-64 28.608-64 64v64h-192c-35.328 0-64 28.608-64 64v128c0 35.392 28.672 64 64 64v512c0 35.392 28.672 64 64 64h512c35.392 0 64-28.608 64-64v-512c35.392 0 64-28.608 64-64v-128c0-35.392-28.608-64-64-64zM448 64h128v64h-128v-64zM448 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM640 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM832 320h-640v-128h640v128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete-filled"],"grid":0},"attrs":[{}],"properties":{"order":36,"id":19,"name":"delete-filled","prevSize":24,"code":59667},"setIdx":0,"setId":1,"iconIdx":82},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c98.816 0 179.2 80.384 179.2 179.2s-80.384 179.2-179.2 179.2c-98.816 0-179.2-80.384-179.2-179.2s80.384-179.2 179.2-179.2zM227.2 665.6c-12.39 0-22.4 10.061-22.4 22.4v6.4c0 12.39 10.010 22.4 22.4 22.4h211.2c12.39 0 22.4-10.010 22.4-22.4v-6.4c0-12.39-10.061-22.4-22.4-22.4h-211.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-delete"],"grid":0},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":24,"code":59668},"setIdx":0,"setId":1,"iconIdx":83},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c39.934 0 76.475 13.533 106.3 35.7l-250.4 249c-21.807-29.683-35.1-65.924-35.1-105.5 0-98.816 80.384-179.2 179.2-179.2zM477 585.7c21.785 29.674 35 65.947 35 105.5 0 98.816-80.384 179.2-179.2 179.2-39.906 0-76.386-13.561-106.2-35.7l250.4-249z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-disable"],"grid":0},"attrs":[{}],"properties":{"order":40,"id":21,"name":"document-disable","prevSize":24,"code":59669},"setIdx":0,"setId":1,"iconIdx":84},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2l-230.4-256zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7l161.5-179.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-publish"],"grid":0},"attrs":[{}],"properties":{"order":44,"id":22,"name":"document-publish","prevSize":24,"code":59670},"setIdx":0,"setId":1,"iconIdx":85},{"icon":{"paths":["M665.6 51.2v102.4h102.4v-102.4h-102.4zM460.8 153.6h102.4v-102.4h-102.4v102.4zM460.8 358.4h102.4v-102.4h-102.4v102.4zM665.6 358.4h102.4v-102.4h-102.4v102.4zM665.6 563.2h102.4v-102.4h-102.4v102.4zM460.8 563.2h102.4v-102.4h-102.4v102.4zM460.8 768h102.4v-102.4h-102.4v102.4zM665.6 768h102.4v-102.4h-102.4v102.4zM665.6 972.8h102.4v-102.4h-102.4v102.4zM460.8 972.8h102.4v-102.4h-102.4v102.4zM256 153.6h102.4v-102.4h-102.4v102.4zM256 358.4h102.4v-102.4h-102.4v102.4zM256 563.2h102.4v-102.4h-102.4v102.4zM256 768h102.4v-102.4h-102.4v102.4zM256 972.8h102.4v-102.4h-102.4v102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag"],"grid":0},"attrs":[{}],"properties":{"order":43,"id":23,"name":"drag","prevSize":24,"code":59671},"setIdx":0,"setId":1,"iconIdx":86},{"icon":{"paths":["M921.6 281.958c0-70.707-171.878-128.154-384-128.154s-384 57.19-384 127.898c0 10.035 3.789 19.712 10.342 29.030 0-0.051 296.858 406.067 296.858 406.067v256l153.6-51.2v-204.8c0 0 298.752-408.166 299.725-409.702 0 0 7.475-16.64 7.475-25.139zM537.6 204.8c206.899 0 318.208 53.248 332.083 76.8-13.875 23.552-125.184 76.8-332.083 76.8s-318.208-53.248-332.083-76.8c13.875-23.552 125.184-76.8 332.083-76.8zM869.376 345.856v0 0zM573.030 686.592c-6.4 8.755-9.83 19.354-9.83 30.208v167.885l-51.2 17.050v-184.934c0-10.854-3.43-21.453-9.83-30.208l-228.147-312.115c68.762 21.709 161.382 35.123 263.578 35.123 102.298 0 195.021-13.414 263.834-35.174-0.102 0.051-0.205 0.051-0.307 0.102l-228.096 312.064z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["filter"],"grid":0},"attrs":[{}],"properties":{"order":18,"id":24,"name":"filter","prevSize":24,"code":59672},"setIdx":0,"setId":1,"iconIdx":87},{"icon":{"paths":["M512 0c-282.88 0-512 229.248-512 512 0 226.24 146.688 418.112 350.080 485.76 25.6 4.8 35.008-11.008 35.008-24.64 0-12.16-0.448-44.352-0.64-87.040-142.464 30.912-172.48-68.672-172.48-68.672-23.296-59.136-56.96-74.88-56.96-74.88-46.4-31.744 3.584-31.104 3.584-31.104 51.392 3.584 78.4 52.736 78.4 52.736 45.696 78.272 119.872 55.68 149.12 42.56 4.608-33.088 17.792-55.68 32.448-68.48-113.728-12.8-233.216-56.832-233.216-252.992 0-55.872 19.84-101.568 52.672-137.408-5.76-12.928-23.040-64.96 4.48-135.488 0 0 42.88-13.76 140.8 52.48 40.96-11.392 84.48-17.024 128-17.28 43.52 0.256 87.040 5.888 128 17.28 97.28-66.24 140.16-52.48 140.16-52.48 27.52 70.528 10.24 122.56 5.12 135.488 32.64 35.84 52.48 81.536 52.48 137.408 0 196.672-119.68 240-233.6 252.608 17.92 15.36 34.56 46.72 34.56 94.72 0 68.48-0.64 123.52-0.64 140.16 0 13.44 8.96 29.44 35.2 24.32 204.864-67.136 351.424-259.136 351.424-485.056 0-282.752-229.248-512-512-512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["brand","github"],"grid":0},"attrs":[{}],"properties":{"order":77,"id":25,"name":"github","prevSize":24,"code":59713},"setIdx":0,"setId":1,"iconIdx":88},{"icon":{"paths":["M512 512h-204.8v51.2h204.8v-51.2zM768 153.6h-51.2c0-28.314-22.886-51.2-51.2-51.2h-307.2c-28.314 0-51.2 22.886-51.2 51.2h-51.2c-28.314 0-51.2 22.886-51.2 51.2v665.6c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-665.6c0-28.314-22.886-51.2-51.2-51.2zM358.4 153.6h307.2v51.2h-307.2v-51.2zM768 819.2c0 28.314-22.886 51.2-51.2 51.2h-409.6c-28.314 0-51.2-22.886-51.2-51.2v-563.2c0-28.314 22.886-51.2 51.2-51.2 0 28.314 22.886 51.2 51.2 51.2h307.2c28.314 0 51.2-22.886 51.2-51.2 28.314 0 51.2 22.886 51.2 51.2v563.2zM307.2 460.8h409.6v-51.2h-409.6v51.2zM307.2 665.6h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["help"],"grid":0},"attrs":[{}],"properties":{"order":19,"id":26,"name":"help","prevSize":24,"code":59673},"setIdx":0,"setId":1,"iconIdx":89},{"icon":{"paths":["M512 0c-169.421 0-307.2 137.779-307.2 307.2 0 78.643 15.258 164.915 45.261 256.41 23.859 72.55 56.986 148.582 98.56 226.099 70.707 131.635 140.339 220.774 143.309 224.512 4.813 6.195 12.288 9.779 20.070 9.779 7.834 0 15.258-3.584 20.122-9.779 2.97-3.686 72.602-92.826 143.309-224.512 41.574-77.517 74.701-153.549 98.56-226.099 29.952-91.494 45.21-177.766 45.21-256.41 0-169.421-137.83-307.2-307.2-307.2zM630.682 764.672c-46.234 86.374-92.979 154.982-118.682 190.822-25.6-35.635-72.038-103.885-118.221-189.952-62.874-117.146-137.779-291.738-137.779-458.342 0-141.158 114.842-256 256-256s256 114.842 256 256c0 166.298-74.65 340.582-137.318 457.472zM512 153.6c-84.685 0-153.6 68.915-153.6 153.6s68.915 153.6 153.6 153.6 153.6-68.915 153.6-153.6-68.915-153.6-153.6-153.6zM512 409.6c-56.525 0-102.4-45.875-102.4-102.4 0-56.474 45.875-102.4 102.4-102.4 56.474 0 102.4 45.926 102.4 102.4 0 56.525-45.926 102.4-102.4 102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["location"],"grid":0},"attrs":[{}],"properties":{"order":25,"id":27,"name":"location, control-Map, type-Geolocation","prevSize":24,"code":59675},"setIdx":0,"setId":1,"iconIdx":90},{"icon":{"paths":["M512.273 83.782c-0.141 0.056-182.959 84.073-229.418 256.782-4.481 16.584 32.696 9.296 31.036 27.527-2.034 22.136-44.668 31.201-39.109 94.764 5.659 64.734 60.321 130.141 68.527 169.673v27.655c-0.497 8.54-4.566 31.715-18.018 43.036-7.378 6.19-17.322 8.421-30.436 6.782-18.205-2.275-25.449-14.468-28.345-24.309-4.753-16.218-0.322-35.123 10.345-44 10.724-8.924 12.17-24.842 3.236-35.564-8.934-10.712-24.858-12.161-35.582-3.218-25.995 21.64-36.887 61.52-26.491 97 9.815 33.392 36.197 55.884 70.6 60.182 4.903 0.609 9.566 0.909 14 0.909 26.623 0 44.661-10.175 55.582-19.455 32.866-27.97 35.449-74.593 35.636-79.818 0.009-0.309 0.018-0.618 0.018-0.927v-21.218h0.109v-1.418c0-12.351 10.008-22.364 22.382-22.364 11.944 0 21.609 9.346 22.273 21.109v202.491c-0.206 2.912-2.536 29.892-17.891 42.945-7.368 6.274-17.384 8.53-30.545 6.873-18.214-2.275-25.476-14.468-28.364-24.291-4.762-16.228-0.322-35.151 10.345-44.018 10.724-8.933 12.188-24.833 3.255-35.564-8.924-10.694-24.876-12.161-35.6-3.218-26.013 21.631-36.887 61.52-26.491 97 9.796 33.392 36.197 55.893 70.6 60.2 4.903 0.609 9.566 0.891 14 0.891 26.623 0 44.671-10.156 55.564-19.436 32.875-27.97 35.458-74.611 35.636-79.836 0.019-0.328 0.018-0.609 0.018-0.909v-225.636l0.127-0.055v-1c0-12.595 10.219-22.8 22.836-22.8 12.349 0 22.333 9.824 22.727 22.073v227.418c0 0.309-0 0.591 0.018 0.909 0.187 5.216 2.779 51.866 35.655 79.836 10.912 9.28 28.959 19.436 55.582 19.436 4.443 0 9.088-0.282 13.982-0.891 34.394-4.307 60.804-26.818 70.6-60.2 10.405-35.48-0.487-75.36-26.491-97-10.743-8.943-26.676-7.466-35.6 3.218-8.934 10.74-7.488 26.63 3.236 35.564 10.668 8.868 15.135 27.79 10.364 44.018-2.878 9.823-10.159 22.015-28.364 24.291-13.105 1.648-23.050-0.592-30.418-6.782-13.508-11.358-17.558-34.657-18.036-43v-201.818c0.297-12.093 10.14-21.818 22.327-21.818 12.374 0 22.4 10.003 22.4 22.364v1.418h0.073v21.218c0 0.318-0 0.628 0.018 0.927 0.178 5.216 2.779 51.848 35.655 79.818 10.912 9.28 28.941 19.455 55.564 19.455 4.434 0 9.107-0.292 14-0.891 34.394-4.298 60.786-26.818 70.582-60.2 10.405-35.48-0.487-75.351-26.491-97-10.743-8.933-26.667-7.476-35.582 3.236-8.943 10.722-7.488 26.622 3.236 35.545 10.668 8.877 15.117 27.8 10.345 44.018-2.878 9.842-10.159 22.025-28.364 24.291-13.086 1.648-23.050-0.583-30.418-6.764-13.508-11.368-17.549-34.675-18.018-43v-21.018c5.305-54.103 63.095-107.777 69.091-176.364 5.531-63.563-37.121-72.627-39.145-94.764-1.669-18.232 35.498-10.944 31.036-27.527-46.468-172.709-229.269-256.726-229.4-256.782z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["logo"],"grid":0},"attrs":[{}],"properties":{"order":31,"id":28,"name":"logo","prevSize":24,"code":59676},"setIdx":0,"setId":1,"iconIdx":91},{"icon":{"paths":["M947.2 0h-870.4c-42.342 0-76.8 34.458-76.8 76.8v870.4c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-870.4c0-42.342-34.458-76.8-76.8-76.8zM972.8 947.2c0 14.157-11.443 25.6-25.6 25.6h-870.4c-14.131 0-25.6-11.443-25.6-25.6v-870.4c0-14.131 11.469-25.6 25.6-25.6h870.4c14.157 0 25.6 11.469 25.6 25.6v870.4zM665.6 460.8c56.448 0 102.4-45.926 102.4-102.4s-45.952-102.4-102.4-102.4c-56.448 0-102.4 45.926-102.4 102.4s45.952 102.4 102.4 102.4zM665.6 307.2c28.211 0 51.2 22.989 51.2 51.2s-22.989 51.2-51.2 51.2c-28.211 0-51.2-22.989-51.2-51.2s22.989-51.2 51.2-51.2zM896 102.4h-768c-14.131 0-25.6 11.469-25.6 25.6v614.4c0 14.157 11.469 25.6 25.6 25.6h768c14.157 0 25.6-11.443 25.6-25.6v-614.4c0-14.131-11.443-25.6-25.6-25.6zM153.6 716.8v-118.246l164.301-184.858c4.198-4.787 9.728-7.373 15.462-7.475 5.734-0.051 11.29 2.458 15.642 7.040l283.238 303.539h-478.643zM870.4 716.8h-168.090l-315.853-338.432c-14.285-15.334-33.331-23.603-53.709-23.347-20.326 0.256-39.219 9.011-53.094 24.627l-126.054 141.798v-367.846h716.8v563.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["media"],"grid":0},"attrs":[{}],"properties":{"order":30,"id":29,"name":"media, type-Assets, trigger-AssetChanged","prevSize":24,"code":59677},"setIdx":0,"setId":1,"iconIdx":92},{"icon":{"paths":["M128 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM512 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM896 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["more"],"grid":0},"attrs":[{}],"properties":{"order":34,"id":30,"name":"more, dots","prevSize":24,"code":59678},"setIdx":0,"setId":1,"iconIdx":93},{"icon":{"paths":["M877.12 311.104l-66.304 66.368-228.224-228.224 66.368-66.368c25.216-25.152 66.048-25.152 91.264 0l136.896 137.024c25.216 25.216 25.216 65.984 0 91.2zM760.896 427.392l-386.176 386.112c-25.216 25.28-66.048 25.28-91.264 0l-136.96-136.896c-25.216-25.28-25.216-66.112 0-91.264l386.24-386.24 228.16 228.288zM64 896v-191.872l191.936 191.872h-191.936z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pencil"],"grid":0},"attrs":[{}],"properties":{"order":47,"id":31,"name":"pencil","prevSize":24,"code":59679},"setIdx":0,"setId":1,"iconIdx":94},{"icon":{"paths":["M892.083 131.917c-73.523-73.498-193.152-73.498-266.65 0l-157.184 157.107c-9.958 10.035-9.958 26.214 0 36.275 10.061 9.984 26.24 9.984 36.25 0l157.133-157.107c53.504-53.555 140.672-53.555 194.176 0 53.581 53.504 53.581 140.672 0 194.176l-186.138 186.163c-53.53 53.581-140.672 53.581-194.176 0-10.086-10.010-26.24-10.010-36.275 0-10.035 10.086-10.035 26.189 0 36.25 36.787 36.736 84.992 55.117 133.325 55.117s96.589-18.432 133.376-55.117l186.163-186.214c73.498-73.472 73.498-193.152 0-266.65zM519.45 698.726l-157.082 157.082c-53.504 53.555-140.672 53.555-194.176 0-53.581-53.504-53.581-140.672 0-194.176l186.138-186.163c53.53-53.581 140.672-53.581 194.176 0 10.086 9.984 26.189 9.984 36.275 0 10.035-10.086 10.035-26.214 0-36.25-73.549-73.498-193.203-73.498-266.701 0l-186.163 186.163c-73.498 73.574-73.498 193.203 0 266.701 36.787 36.71 85.043 55.117 133.325 55.117 48.333 0 96.538-18.406 133.325-55.117l157.133-157.133c10.010-10.010 10.010-26.189 0-36.224-10.010-9.984-26.189-9.984-36.25 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["reference"],"grid":0},"attrs":[{}],"properties":{"order":45,"id":32,"name":"reference","prevSize":24,"code":59680},"setIdx":0,"setId":1,"iconIdx":95},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-300.8c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v300.8c0 124.8-99.2 224-224 224zM224 339.2c-89.6 0-160 70.4-160 160v300.8c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-300.8c0-89.6-70.4-160-160-160h-576z","M828.8 201.6h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M716.8 64h-409.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h412.8c19.2 0 32 12.8 32 32s-16 32-35.2 32z","M800 416v64c0 48-38.4 83.2-83.2 83.2h-409.6c-44.8 3.2-83.2-35.2-83.2-83.2v-64h-54.4v64c0 76.8 64 140.8 140.8 140.8h406.4c76.8 0 140.8-64 140.8-140.8v-64h-57.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["schemas"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":46,"id":33,"name":"schemas, search-Schema","prevSize":24,"code":59681},"setIdx":0,"setId":1,"iconIdx":96},{"icon":{"paths":["M939.776 1003.776c-27.2 27.008-71.232 27.008-98.368 0l-168.96-168.96c-66.176 38.464-142.016 62.080-224 62.080-247.744 0-448.448-200.832-448.448-448.448 0-247.744 200.704-448.448 448.448-448.448 247.68 0 448.512 200.704 448.512 448.448 0 115.136-44.672 218.944-115.904 298.304l158.656 158.656c27.008 27.136 27.008 71.168 0.064 98.368zM448.448 128.128c-176.896 0-320.32 143.36-320.32 320.32s143.424 320.32 320.32 320.32c176.96 0 320.384-143.36 320.384-320.32s-143.488-320.32-320.384-320.32z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["search"],"grid":0},"attrs":[{}],"properties":{"order":23,"id":34,"name":"search","prevSize":24,"code":59682},"setIdx":0,"setId":1,"iconIdx":97},{"icon":{"paths":["M1019.11 440.755c-1.946-13.747-14.438-23.398-28.16-21.888-16.947 1.843-34.253-0.589-50.048-7.091-52.25-21.504-77.261-81.459-55.757-133.709 6.605-15.846 16.947-29.85 30.208-40.602 10.803-8.653 12.698-24.294 4.352-35.354-28.902-37.99-62.797-71.706-100.838-100.045-10.701-8.090-25.805-6.451-34.662 3.661-28.8 33.254-75.546 44.262-116.198 27.546-40.704-16.742-66.099-57.498-63.206-101.453 0.845-13.338-8.755-25.19-21.99-27.008-47.002-6.605-94.797-6.605-142.054 0.077-13.722 1.946-23.398 14.387-21.862 28.211 1.843 16.896-0.614 34.202-7.168 49.997-21.504 52.25-81.408 77.21-133.632 55.706-15.821-6.502-29.85-16.947-40.602-30.157-8.653-10.752-24.32-12.698-35.379-4.301-37.99 28.851-71.68 62.694-100.045 100.762-8.090 10.701-6.451 25.83 3.635 34.637 33.28 28.902 44.288 75.597 27.546 116.301-16.742 40.653-57.498 66.048-101.427 63.155-13.363-0.845-25.19 8.755-26.982 21.99-6.63 47.002-6.63 94.822 0.102 142.080 1.946 13.696 14.387 23.322 28.16 21.811 16.896-1.818 34.202 0.691 50.022 7.168 52.224 21.53 77.21 81.459 55.706 133.734-6.502 15.795-16.947 29.773-30.157 40.525-10.803 8.73-12.698 24.346-4.352 35.354 28.877 38.042 62.822 71.731 100.813 100.122 1.741 1.357 3.661 2.355 5.606 3.2 9.933 4.045 21.709 1.536 29.082-6.938 28.826-33.178 75.571-44.262 116.275-27.52 40.653 16.742 66.048 57.498 63.13 101.453-0.819 13.338 8.755 25.165 22.067 27.059 47.002 6.579 94.72 6.554 142.029-0.102 13.645-1.971 23.347-14.464 21.811-28.237-1.843-16.947 0.691-34.253 7.194-50.048 21.504-52.25 81.459-77.21 133.658-55.68 15.795 6.528 29.85 16.947 40.55 30.157 8.704 10.803 24.346 12.698 35.405 4.326 37.99-28.902 71.654-62.746 100.096-100.813 7.987-10.675 6.4-25.805-3.712-34.662-33.254-28.826-44.288-75.571-27.546-116.224 16.742-40.73 57.498-66.099 101.453-63.232 13.338 0.922 25.139-8.678 27.008-21.965 6.554-47.002 6.502-94.771-0.128-142.003zM971.059 554.010c-56.141 5.274-105.702 41.114-127.642 94.464s-12.058 113.613 24.090 156.902c-17.69 21.478-37.453 41.318-58.854 59.315-12.749-11.213-27.392-20.352-43.238-26.854-78.259-32.282-168.243 5.197-200.499 83.584-6.502 15.718-10.291 32.563-11.29 49.536-27.853 2.56-55.859 2.637-83.61 0.077-5.274-56.090-41.114-105.677-94.464-127.616-53.35-21.99-113.613-11.981-156.928 24.064-21.504-17.69-41.318-37.453-59.29-58.88 11.213-12.723 20.352-27.392 26.906-43.136 32.205-78.387-5.274-168.294-83.584-200.55-15.821-6.502-32.589-10.342-49.613-11.366-2.534-27.853-2.586-55.859 0-83.558 56.090-5.299 105.626-41.088 127.565-94.438 21.965-53.402 12.058-113.638-24.090-156.902 17.69-21.555 37.478-41.395 58.88-59.341 12.749 11.213 27.392 20.352 43.213 26.854 78.285 32.256 168.218-5.248 200.474-83.558 6.528-15.795 10.342-32.589 11.366-49.613 27.853-2.509 55.808-2.56 83.558 0 5.299 56.090 41.139 105.6 94.49 127.59 53.35 21.939 113.638 12.006 156.902-24.090 21.504 17.741 41.293 37.453 59.29 58.854-11.213 12.8-20.352 27.392-26.854 43.213-32.256 78.31 5.248 168.294 83.507 200.499 15.846 6.502 32.691 10.342 49.638 11.392 2.56 27.853 2.611 55.808 0.077 83.558zM512 307.2c-113.101 0-204.8 91.699-204.8 204.8 0 113.126 91.699 204.826 204.8 204.826s204.8-91.699 204.8-204.826c0-113.101-91.699-204.8-204.8-204.8zM512 665.626c-84.813 0-153.6-68.813-153.6-153.626 0-84.838 68.787-153.6 153.6-153.6 84.838 0 153.6 68.762 153.6 153.6 0 84.813-68.762 153.626-153.6 153.626z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings"],"grid":0},"attrs":[{}],"properties":{"order":22,"id":35,"name":"settings, search-Setting","prevSize":24,"code":59683},"setIdx":0,"setId":1,"iconIdx":98},{"icon":{"paths":["M77.005 102.605h128v332.8c0 14.131 11.418 25.6 25.6 25.6 14.106 0 25.6-11.469 25.6-25.6v-332.8h128c14.106 0 25.6-11.469 25.6-25.6 0-14.157-11.494-25.6-25.6-25.6h-307.2c-14.182 0-25.6 11.443-25.6 25.6 0 14.106 11.418 25.6 25.6 25.6zM947.405 716.979h-179.2v-102.4h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-204.8c-14.182 0-25.6 11.443-25.6 25.6v358.4c0 14.157 11.418 25.6 25.6 25.6 14.157 0 25.6-11.443 25.6-25.6v-179.2h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.494-25.6-25.6-25.6zM965.094 58.47c-9.958-9.933-26.112-9.933-36.045 0l-870.605 870.579c-9.958 9.984-9.958 26.086 0 36.045 10.010 9.984 26.112 9.984 36.045 0l870.605-870.579c9.958-9.933 9.958-26.086 0-36.045z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-boolean"],"grid":0},"attrs":[{}],"properties":{"order":21,"id":36,"name":"type-Boolean","prevSize":24,"code":59684},"setIdx":0,"setId":1,"iconIdx":99},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-datetime"],"grid":0},"attrs":[{}],"properties":{"order":24,"id":37,"name":"type-DateTime","prevSize":24,"code":59685},"setIdx":0,"setId":1,"iconIdx":100},{"icon":{"paths":["M179.2 256c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6h-25.6c-56.55 0-102.4 45.85-102.4 102.4v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 56.55 45.85 102.4 102.4 102.4h25.6c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-30.746-13.85-58.061-35.328-76.8 21.478-18.765 35.328-46.029 35.328-76.8v-179.2zM972.8 486.4h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-56.55-45.85-102.4-102.4-102.4h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 30.771 13.85 58.035 35.328 76.8-21.478 18.739-35.328 46.054-35.328 76.8v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h25.6c56.55 0 102.4-45.85 102.4-102.4v-179.2c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6zM512 332.8c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6c0-14.131-11.443-25.6-25.6-25.6zM512 435.2c-14.157 0-25.6 11.469-25.6 25.6v204.8c0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6v-204.8c0-14.131-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["json"],"grid":0},"attrs":[{}],"properties":{"order":20,"id":38,"name":"type-Json, json","prevSize":24,"code":59674},"setIdx":0,"setId":1,"iconIdx":101},{"icon":{"paths":["M256 665.6h-76.8v-332.8c0-14.131-11.469-25.6-25.6-25.6h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h51.2v307.2h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6zM614.4 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6v179.2c0 14.131 11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-179.2v-128h179.2c14.131 0 25.6-11.469 25.6-25.6v-179.2c0-14.131-11.469-25.6-25.6-25.6zM972.8 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6v-358.4c0-14.131-11.469-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-number"],"grid":0},"attrs":[{}],"properties":{"order":32,"id":39,"name":"type-Number","prevSize":24,"code":59686},"setIdx":0,"setId":1,"iconIdx":102},{"icon":{"paths":["M870.4 921.6h-716.8c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h716.8c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM194.688 817.152c13.030 5.555 28.083-0.461 33.613-13.44l125.030-291.712h317.338l125.005 291.712c4.173 9.677 13.568 15.488 23.526 15.488 3.405 0 6.81-0.64 10.112-2.048 13.005-5.606 18.995-20.659 13.44-33.638l-131.61-306.944c-0.051-0.051-0.051-0.154-0.102-0.205l-175.488-409.6c-4.045-9.472-13.312-15.565-23.552-15.565s-19.507 6.093-23.552 15.514l-175.488 409.6c-0.051 0.051-0.051 0.154-0.102 0.205l-131.61 306.97c-5.53 13.005 0.461 28.058 13.44 33.664zM512 141.773l136.704 319.027h-273.408l136.704-319.027z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-string"],"grid":0},"attrs":[{}],"properties":{"order":48,"id":40,"name":"type-String","prevSize":24,"code":59687},"setIdx":0,"setId":1,"iconIdx":103},{"icon":{"paths":["M955.221 848c0-0.109 10.752 0 0 0-52.751-161.392-240.461-224-443.178-224-202.269 0-389.979 63.392-443.066 224-11.2-0.109 0-1.232 0 0 0 61.936 49.615 112 110.654 112h664.823c61.151 0 110.766-50.064 110.766-112zM290.399 288c0 123.648 99.231 336 221.645 336s221.645-212.352 221.645-336c0-123.648-99.231-224-221.645-224s-221.645 100.352-221.645 224z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user"],"grid":0},"attrs":[{}],"properties":{"order":33,"id":41,"name":"user","prevSize":24,"code":59688},"setIdx":0,"setId":1,"iconIdx":104},{"icon":{"paths":["M469.333 614.997v281.003c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-281.003l97.835 97.835c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331l-170.667-170.667c-0.085-0.085-0.171-0.171-0.256-0.256-4.053-3.968-8.661-6.955-13.568-9.003-5.12-2.133-10.624-3.2-16.085-3.243-0.171 0-0.341 0-0.469 0-5.461 0.043-10.965 1.109-16.085 3.243-4.949 2.048-9.557 5.035-13.568 9.003-0.085 0.085-0.171 0.171-0.256 0.256l-170.667 170.667c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0zM890.411 822.101c30.379-16.555 56.149-38.443 76.672-63.915 21.333-26.411 36.949-56.619 46.379-88.576s12.629-65.835 9.003-99.584c-3.456-32.512-13.269-64.896-29.824-95.232-14.208-26.069-32.384-48.768-53.376-67.669-21.717-19.541-46.421-34.944-72.875-45.952-30.891-12.8-64.171-19.584-98.048-19.84h-22.528c-13.312-37.717-32.085-72.235-55.168-102.912-30.635-40.661-68.821-74.453-111.915-99.84s-91.179-42.411-141.568-49.536c-48.597-6.784-99.243-4.395-149.504 8.619s-95.744 35.413-134.912 64.939c-40.661 30.635-74.453 68.821-99.84 111.915s-42.411 91.179-49.493 141.568c-6.827 48.555-4.395 99.2 8.576 149.461 15.872 61.312 45.781 115.627 84.267 158.421 15.744 17.536 42.752 18.944 60.245 3.2s18.944-42.752 3.2-60.245c-29.355-32.64-52.693-74.667-65.109-122.752-10.155-39.253-11.989-78.592-6.699-116.224 5.504-39.125 18.773-76.501 38.571-110.123s46.080-63.317 77.653-87.083c30.379-22.869 65.664-40.32 104.917-50.475s78.592-11.989 116.224-6.699c39.125 5.504 76.544 18.731 110.123 38.528s63.317 46.080 87.083 77.653c22.869 30.379 40.32 65.664 50.475 104.917 4.907 18.56 21.547 32 41.301 32h53.461c22.869 0.171 45.269 4.736 65.92 13.312 17.707 7.339 34.133 17.621 48.512 30.592 13.909 12.501 25.984 27.605 35.541 45.099 11.093 20.352 17.579 41.899 19.883 63.488 2.389 22.443 0.256 45.013-6.016 66.432s-16.725 41.515-30.933 59.093c-13.611 16.896-30.763 31.445-51.115 42.581-20.693 11.264-28.331 37.205-17.024 57.899s37.205 28.331 57.899 17.024z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload-cloud"],"grid":0},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":24,"code":59763,"name":"upload-3"},"setIdx":0,"setId":1,"iconIdx":105},{"icon":{"paths":["M853.333 640v170.667c0 5.845-1.152 11.349-3.2 16.299-2.133 5.205-5.333 9.899-9.301 13.867s-8.661 7.125-13.867 9.301c-4.949 2.048-10.453 3.2-16.299 3.2h-597.333c-5.845 0-11.349-1.152-16.299-3.2-5.205-2.133-9.899-5.333-13.867-9.301s-7.125-8.661-9.301-13.867c-2.048-4.949-3.2-10.453-3.2-16.299v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v170.667c0 17.28 3.456 33.835 9.728 48.981 6.485 15.701 16 29.781 27.776 41.557s25.856 21.291 41.557 27.776c15.104 6.229 31.659 9.685 48.939 9.685h597.333c17.28 0 33.835-3.456 48.981-9.728 15.701-6.485 29.781-16 41.557-27.776s21.291-25.856 27.776-41.557c6.229-15.104 9.685-31.659 9.685-48.939v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667zM469.333 230.997v409.003c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-409.003l140.501 140.501c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331l-213.333-213.333c-0.043-0.043-0.128-0.085-0.171-0.171-4.053-4.011-8.704-7.040-13.653-9.088-10.453-4.309-22.229-4.309-32.683 0-4.949 2.048-9.6 5.077-13.653 9.088-0.043 0.043-0.128 0.085-0.171 0.171l-213.333 213.333c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload"],"grid":0},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59761,"name":"upload-4"},"setIdx":0,"setId":1,"iconIdx":106},{"icon":{"paths":["M621.254 877.254l320-320c24.994-24.992 24.994-65.516 0-90.51l-320-320c-24.994-24.992-65.516-24.992-90.51 0-24.994 24.994-24.994 65.516 0 90.51l210.746 210.746h-613.49c-35.346 0-64 28.654-64 64s28.654 64 64 64h613.49l-210.746 210.746c-12.496 12.496-18.744 28.876-18.744 45.254s6.248 32.758 18.744 45.254c24.994 24.994 65.516 24.994 90.51 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["arrow-right","right","next"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59766,"name":"arrow-right"},"setIdx":0,"setId":1,"iconIdx":107},{"icon":{"paths":["M448 576h128v-256h192l-256-256-256 256h192zM640 432v98.712l293.066 109.288-421.066 157.018-421.066-157.018 293.066-109.288v-98.712l-384 144v256l512 192 512-192v-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload","load","arrow"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59760,"name":"upload"},"setIdx":0,"setId":1,"iconIdx":108},{"icon":{"paths":["M585.143 548.557c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z","M585.143 219.443c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-bottom"],"grid":16},"attrs":[{},{}],"properties":{"order":125,"id":0,"name":"caret-bottom","prevSize":32,"code":59755},"setIdx":0,"setId":1,"iconIdx":109},{"icon":{"paths":["M585.143 804.577c0 20.005-16.567 36.571-36.571 36.571h-512c-20.005 0-36.571-16.567-36.571-36.571 0-9.728 3.986-18.871 10.862-25.71l256-256c6.839-6.839 16.018-10.862 25.71-10.862s18.871 3.986 25.71 10.862l256 256c6.839 6.839 10.862 16.018 10.862 25.71z","M585.143 475.423c0 20.005-16.567 36.571-36.571 36.571h-512c-20.005 0-36.571-16.567-36.571-36.571 0-9.728 3.986-18.871 10.862-25.71l256-256c6.839-6.839 16.018-10.862 25.71-10.862s18.871 3.986 25.71 10.862l256 256c6.839 6.839 10.862 16.018 10.862 25.71z"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-top"],"grid":16},"attrs":[{},{}],"properties":{"order":124,"id":1,"name":"caret-top","prevSize":32,"code":59756},"setIdx":0,"setId":1,"iconIdx":110},{"icon":{"paths":["M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M408.906 587.72l-35.3-37 138.1-131.9 138 131.9-35.3 37-102.7-98.1z","M511.706 773.12l-138.1-131.9 35.3-37 102.8 98.1 102.7-98.1 35.3 37z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["show"],"grid":16},"attrs":[{},{},{}],"properties":{"order":123,"id":2,"name":"show","prevSize":32,"code":59748},"setIdx":0,"setId":1,"iconIdx":111},{"icon":{"paths":["M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M348.394 15.988c-28.314 0-51.2 22.886-51.2 51.2v23.7h51.2v-23.7h307.2l204.8 204.8v512h-23.8v51.2h23.8c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2z","M408.906 587.72l-35.3-37 138.1-131.9 138 131.9-35.3 37-102.7-98.1z","M511.706 773.12l-138.1-131.9 35.3-37 102.8 98.1 102.7-98.1 35.3 37z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["show-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":122,"id":3,"name":"show-all","prevSize":32,"code":59749},"setIdx":0,"setId":1,"iconIdx":112},{"icon":{"paths":["M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M408.9 418.8l-35.3 37 138 131.9 138.1-131.9-35.3-37-102.8 98.1z","M511.6 604.2l-138 131.9 35.3 37 102.7-98.1 102.8 98.1 35.3-37z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hide"],"grid":16},"attrs":[{},{},{}],"properties":{"order":121,"id":4,"name":"hide","prevSize":32,"code":59750},"setIdx":0,"setId":1,"iconIdx":113},{"icon":{"paths":["M408.9 418.8l-35.3 37 138.1 131.9 138-131.9-35.3-37-102.7 98.1z","M511.7 604.2l-138.1 131.9 35.3 37 102.8-98.1 102.7 98.1 35.3-37z","M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M348.394 15.988c-28.314 0-51.2 22.886-51.2 51.2v23.7h51.2v-23.7h307.2l204.8 204.8v512h-23.8v51.2h23.8c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hide-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":120,"id":5,"name":"hide-all","prevSize":32,"code":59751},"setIdx":0,"setId":1,"iconIdx":114},{"icon":{"paths":["M512 1024c-136.76 0-265.334-53.258-362.040-149.96-96.702-96.706-149.96-225.28-149.96-362.040 0-96.838 27.182-191.134 78.606-272.692 50-79.296 120.664-143.372 204.356-185.3l43 85.832c-68.038 34.084-125.492 86.186-166.15 150.67-41.746 66.208-63.812 142.798-63.812 221.49 0 229.382 186.618 416 416 416s416-186.618 416-416c0-78.692-22.066-155.282-63.81-221.49-40.66-64.484-98.114-116.584-166.15-150.67l43-85.832c83.692 41.928 154.358 106.004 204.356 185.3 51.422 81.558 78.604 175.854 78.604 272.692 0 136.76-53.258 265.334-149.96 362.040-96.706 96.702-225.28 149.96-362.040 149.96z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["spinner","loading","loading-wheel","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":6,"prevSize":32,"code":59737,"name":"spinner2"},"setIdx":0,"setId":1,"iconIdx":115},{"icon":{"paths":["M1024 397.050l-353.78-51.408-158.22-320.582-158.216 320.582-353.784 51.408 256 249.538-60.432 352.352 316.432-166.358 316.432 166.358-60.434-352.352 256.002-249.538z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-full","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59741,"name":"star-full"},"setIdx":0,"setId":1,"iconIdx":116},{"icon":{"paths":["M1024 397.050l-353.78-51.408-158.22-320.582-158.216 320.582-353.784 51.408 256 249.538-60.432 352.352 316.432-166.358 316.432 166.358-60.434-352.352 256.002-249.538zM512 753.498l-223.462 117.48 42.676-248.83-180.786-176.222 249.84-36.304 111.732-226.396 111.736 226.396 249.836 36.304-180.788 176.222 42.678 248.83-223.462-117.48z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-empty","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":8,"prevSize":32,"code":59742,"name":"star-empty"},"setIdx":0,"setId":1,"iconIdx":117},{"icon":{"paths":["M1024 226.4c-37.6 16.8-78.2 28-120.6 33 43.4-26 76.6-67.2 92.4-116.2-40.6 24-85.6 41.6-133.4 51-38.4-40.8-93-66.2-153.4-66.2-116 0-210 94-210 210 0 16.4 1.8 32.4 5.4 47.8-174.6-8.8-329.4-92.4-433-219.6-18 31-28.4 67.2-28.4 105.6 0 72.8 37 137.2 93.4 174.8-34.4-1-66.8-10.6-95.2-26.2 0 0.8 0 1.8 0 2.6 0 101.8 72.4 186.8 168.6 206-17.6 4.8-36.2 7.4-55.4 7.4-13.6 0-26.6-1.4-39.6-3.8 26.8 83.4 104.4 144.2 196.2 146-72 56.4-162.4 90-261 90-17 0-33.6-1-50.2-3 93.2 59.8 203.6 94.4 322.2 94.4 386.4 0 597.8-320.2 597.8-597.8 0-9.2-0.2-18.2-0.6-27.2 41-29.4 76.6-66.4 104.8-108.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["twitter","brand","tweet","social"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":9,"prevSize":32,"code":59740,"name":"twitter"},"setIdx":0,"setId":1,"iconIdx":118},{"icon":{"paths":["M728.992 512c137.754-87.334 231.008-255.208 231.008-448 0-21.676-1.192-43.034-3.478-64h-889.042c-2.29 20.968-3.48 42.326-3.48 64 0 192.792 93.254 360.666 231.006 448-137.752 87.334-231.006 255.208-231.006 448 0 21.676 1.19 43.034 3.478 64h889.042c2.288-20.966 3.478-42.324 3.478-64 0.002-192.792-93.252-360.666-231.006-448zM160 960c0-186.912 80.162-345.414 224-397.708v-100.586c-143.838-52.29-224-210.792-224-397.706v0h704c0 186.914-80.162 345.416-224 397.706v100.586c143.838 52.294 224 210.796 224 397.708h-704zM619.626 669.594c-71.654-40.644-75.608-93.368-75.626-125.366v-64.228c0-31.994 3.804-84.914 75.744-125.664 38.504-22.364 71.808-56.348 97.048-98.336h-409.582c25.266 42.032 58.612 76.042 97.166 98.406 71.654 40.644 75.606 93.366 75.626 125.366v64.228c0 31.992-3.804 84.914-75.744 125.664-72.622 42.18-126.738 125.684-143.090 226.336h501.67c-16.364-100.708-70.53-184.248-143.212-226.406z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hour-glass","loading","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":32,"code":59732,"name":"hour-glass"},"setIdx":0,"setId":1,"iconIdx":119},{"icon":{"paths":["M192 512c0-12.18 0.704-24.196 2.030-36.022l-184.98-60.104c-5.916 31.14-9.050 63.264-9.050 96.126 0 147.23 62.166 279.922 161.654 373.324l114.284-157.296c-52.124-56.926-83.938-132.758-83.938-216.028zM832 512c0 83.268-31.812 159.102-83.938 216.028l114.284 157.296c99.488-93.402 161.654-226.094 161.654-373.324 0-32.862-3.132-64.986-9.048-96.126l-184.98 60.104c1.324 11.828 2.028 23.842 2.028 36.022zM576 198.408c91.934 18.662 169.544 76.742 214.45 155.826l184.978-60.102c-73.196-155.42-222.24-268.060-399.428-290.156v194.432zM233.55 354.232c44.906-79.084 122.516-137.164 214.45-155.826v-194.43c-177.188 22.096-326.23 134.736-399.426 290.154l184.976 60.102zM644.556 803.328c-40.39 18.408-85.272 28.672-132.556 28.672s-92.166-10.264-132.554-28.67l-114.292 157.31c73.206 40.366 157.336 63.36 246.846 63.36s173.64-22.994 246.848-63.36l-114.292-157.312z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["spinner","loading","loading-wheel","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":32,"code":59731,"name":"spinner"},"setIdx":0,"setId":1,"iconIdx":120},{"icon":{"paths":["M658.744 749.256l-210.744-210.746v-282.51h128v229.49l173.256 173.254zM512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384s-171.922 384-384 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["clock","time","schedule"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":12,"prevSize":32,"code":59728,"name":"clock"},"setIdx":0,"setId":1,"iconIdx":121},{"icon":{"paths":["M128 320v640c0 35.2 28.8 64 64 64h576c35.2 0 64-28.8 64-64v-640h-704zM320 896h-64v-448h64v448zM448 896h-64v-448h64v448zM576 896h-64v-448h64v448zM704 896h-64v-448h64v448z","M848 128h-208v-80c0-26.4-21.6-48-48-48h-224c-26.4 0-48 21.6-48 48v80h-208c-26.4 0-48 21.6-48 48v80h832v-80c0-26.4-21.6-48-48-48zM576 128h-192v-63.198h192v63.198z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bin","trashcan","remove","delete","recycle","dispose"],"grid":16},"attrs":[{},{}],"properties":{"order":1,"id":13,"name":"bin2","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":122},{"icon":{"paths":["M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 960.002c-62.958 0-122.872-13.012-177.23-36.452l233.148-262.29c5.206-5.858 8.082-13.422 8.082-21.26v-96c0-17.674-14.326-32-32-32-112.99 0-232.204-117.462-233.374-118.626-6-6.002-14.14-9.374-22.626-9.374h-128c-17.672 0-32 14.328-32 32v192c0 12.122 6.848 23.202 17.69 28.622l110.31 55.156v187.886c-116.052-80.956-192-215.432-192-367.664 0-68.714 15.49-133.806 43.138-192h116.862c8.488 0 16.626-3.372 22.628-9.372l128-128c6-6.002 9.372-14.14 9.372-22.628v-77.412c40.562-12.074 83.518-18.588 128-18.588 70.406 0 137.004 16.26 196.282 45.2-4.144 3.502-8.176 7.164-12.046 11.036-36.266 36.264-56.236 84.478-56.236 135.764s19.97 99.5 56.236 135.764c36.434 36.432 85.218 56.264 135.634 56.26 3.166 0 6.342-0.080 9.518-0.236 13.814 51.802 38.752 186.656-8.404 372.334-0.444 1.744-0.696 3.488-0.842 5.224-81.324 83.080-194.7 134.656-320.142 134.656z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["earth","globe","language","web","internet","sphere","planet"],"defaultCode":59850,"grid":16},"attrs":[],"properties":{"ligatures":"earth, globe2","name":"earth","id":14,"order":91,"prevSize":32,"code":59850},"setIdx":0,"setId":1,"iconIdx":123},{"icon":{"paths":["M512.002 193.212v-65.212h128v-64c0-35.346-28.654-64-64.002-64h-191.998c-35.346 0-64 28.654-64 64v64h128v65.212c-214.798 16.338-384 195.802-384 414.788 0 229.75 186.25 416 416 416s416-186.25 416-416c0-218.984-169.202-398.448-384-414.788zM706.276 834.274c-60.442 60.44-140.798 93.726-226.274 93.726s-165.834-33.286-226.274-93.726c-60.44-60.44-93.726-140.8-93.726-226.274s33.286-165.834 93.726-226.274c58.040-58.038 134.448-91.018 216.114-93.548l-21.678 314.020c-1.86 26.29 12.464 37.802 31.836 37.802s33.698-11.512 31.836-37.802l-21.676-314.022c81.666 2.532 158.076 35.512 216.116 93.55 60.44 60.44 93.726 140.8 93.726 226.274s-33.286 165.834-93.726 226.274z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["stopwatch","time","speed","meter","chronometer"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":15,"prevSize":32,"code":59715,"name":"elapsed"},"setIdx":0,"setId":1,"iconIdx":124},{"icon":{"paths":["M522.2 438.8v175.6h290.4c-11.8 75.4-87.8 220.8-290.4 220.8-174.8 0-317.4-144.8-317.4-323.2s142.6-323.2 317.4-323.2c99.4 0 166 42.4 204 79l139-133.8c-89.2-83.6-204.8-134-343-134-283 0-512 229-512 512s229 512 512 512c295.4 0 491.6-207.8 491.6-500.2 0-33.6-3.6-59.2-8-84.8l-483.6-0.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["google","brand"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":16,"prevSize":32,"code":59707,"name":"google"},"setIdx":0,"setId":1,"iconIdx":125},{"icon":{"paths":["M592 448h-16v-192c0-105.87-86.13-192-192-192h-128c-105.87 0-192 86.13-192 192v192h-16c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48zM192 256c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192h-256v-192z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["lock","secure","private","encrypted"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":17,"prevSize":32,"code":59700,"name":"lock"},"setIdx":0,"setId":1,"iconIdx":126},{"icon":{"paths":["M0.35 512l-0.35-312.074 384-52.144v364.218zM448 138.482l511.872-74.482v448h-511.872zM959.998 576l-0.126 448-511.872-72.016v-375.984zM384 943.836l-383.688-52.594-0.020-315.242h383.708z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["windows8","brand","os"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":18,"prevSize":32,"code":59712,"name":"microsoft"},"setIdx":0,"setId":1,"iconIdx":127},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":32,"code":59695,"name":"pause"},"setIdx":0,"setId":1,"iconIdx":128},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":20,"prevSize":32,"code":59696,"name":"play"},"setIdx":0,"setId":1,"iconIdx":129},{"icon":{"paths":["M889.68 166.32c-93.608-102.216-228.154-166.32-377.68-166.32-282.77 0-512 229.23-512 512h96c0-229.75 186.25-416 416-416 123.020 0 233.542 53.418 309.696 138.306l-149.696 149.694h352v-352l-134.32 134.32z","M928 512c0 229.75-186.25 416-416 416-123.020 0-233.542-53.418-309.694-138.306l149.694-149.694h-352v352l134.32-134.32c93.608 102.216 228.154 166.32 377.68 166.32 282.77 0 512-229.23 512-512h-96z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["loop","repeat","player","reload","refresh","update","synchronize","arrows"],"grid":16},"attrs":[{},{}],"properties":{"order":49,"id":21,"prevSize":32,"code":59694,"name":"reset"},"setIdx":0,"setId":1,"iconIdx":130},{"icon":{"paths":["M933.79 610.25c-53.726-93.054-21.416-212.304 72.152-266.488l-100.626-174.292c-28.75 16.854-62.176 26.518-97.846 26.518-107.536 0-194.708-87.746-194.708-195.99h-201.258c0.266 33.41-8.074 67.282-25.958 98.252-53.724 93.056-173.156 124.702-266.862 70.758l-100.624 174.292c28.97 16.472 54.050 40.588 71.886 71.478 53.638 92.908 21.512 211.92-71.708 266.224l100.626 174.292c28.65-16.696 61.916-26.254 97.4-26.254 107.196 0 194.144 87.192 194.7 194.958h201.254c-0.086-33.074 8.272-66.57 25.966-97.218 53.636-92.906 172.776-124.594 266.414-71.012l100.626-174.29c-28.78-16.466-53.692-40.498-71.434-71.228zM512 719.332c-114.508 0-207.336-92.824-207.336-207.334 0-114.508 92.826-207.334 207.336-207.334 114.508 0 207.332 92.826 207.332 207.334-0.002 114.51-92.824 207.334-207.332 207.334z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cog","gear","preferences","settings","generate","control","options"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":22,"prevSize":32,"code":59693,"name":"settings2"},"setIdx":0,"setId":1,"iconIdx":131},{"icon":{"paths":["M512 128c-247.424 0-448 200.576-448 448s200.576 448 448 448 448-200.576 448-448-200.576-448-448-448zM512 936c-198.824 0-360-161.178-360-360 0-198.824 161.176-360 360-360 198.822 0 360 161.176 360 360 0 198.822-161.178 360-360 360zM934.784 287.174c16.042-28.052 25.216-60.542 25.216-95.174 0-106.040-85.96-192-192-192-61.818 0-116.802 29.222-151.92 74.596 131.884 27.236 245.206 105.198 318.704 212.578v0zM407.92 74.596c-35.116-45.374-90.102-74.596-151.92-74.596-106.040 0-192 85.96-192 192 0 34.632 9.174 67.122 25.216 95.174 73.5-107.38 186.822-185.342 318.704-212.578z","M512 576v-256h-64v320h256v-64z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["alarm","time","clock"],"grid":16},"attrs":[{},{}],"properties":{"order":2,"id":23,"prevSize":32,"code":59716,"name":"timeout"},"setIdx":0,"setId":1,"iconIdx":132},{"icon":{"paths":["M768 64c105.87 0 192 86.13 192 192v192h-128v-192c0-35.29-28.71-64-64-64h-128c-35.29 0-64 28.71-64 64v192h16c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48h-544c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h400v-192c0-105.87 86.13-192 192-192h128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["unlocked","lock-open"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":24,"prevSize":32,"code":59699,"name":"unlocked"},"setIdx":0,"setId":1,"iconIdx":133},{"icon":{"paths":["M832 416h-320v64h-64v-96h384v-192h-32v96c0 17.664-14.336 32-32 32h-576c-17.696 0-32-14.336-32-32v-128c0-17.696 14.304-32 32-32h576c17.664 0 32 14.304 32 32h64v256h-32zM736 160h-512v32h512v-32zM544 832c0 35.328-28.672 64-64 64s-64-28.672-64-64v-320h128v320zM480 786.656c-17.696 0-32 14.336-32 32 0 17.696 14.304 32 32 32 17.664 0 32-14.304 32-32 0-17.664-14.336-32-32-32z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["paint","tool"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59725,"name":"control-Color"},"setIdx":0,"setId":1,"iconIdx":134},{"icon":{"paths":["M1328 320c-8.832 0-16 7.168-16 16v640c0 8.832-7.168 16-16 16h-1248c-8.832 0-16-7.168-16-16v-640c0-8.832-7.168-16-16-16s-16 7.168-16 16v640c0 26.464 21.536 48 48 48h1248c26.464 0 48-21.536 48-48v-640c0-8.832-7.168-16-16-16zM1296 0h-1248c-26.464 0-48 21.536-48 48v192c0 8.832 7.168 16 16 16h1312c8.832 0 16-7.168 16-16v-192c0-26.464-21.536-48-48-48zM1312 224h-1280v-176c0-8.832 7.168-16 16-16h1248c8.832 0 16 7.168 16 16v176zM560 896c8.832 0 16-7.168 16-16v-512c0-8.832-7.168-16-16-16h-416c-8.832 0-16 7.168-16 16v512c0 8.832 7.168 16 16 16h416zM160 384h384v480h-384v-480zM720 480h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM720 640h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM720 800h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM96 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM224 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM352 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32z"],"width":1344,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59701,"name":"browser"},"setIdx":0,"setId":1,"iconIdx":135},{"icon":{"paths":["M927.936 272.992l-68.288-68.288c-12.608-12.576-32.96-12.576-45.536 0l-409.44 409.44-194.752-196.16c-12.576-12.576-32.928-12.576-45.536 0l-68.288 68.288c-12.576 12.608-12.576 32.96 0 45.536l285.568 287.488c12.576 12.576 32.96 12.576 45.536 0l500.736-500.768c12.576-12.544 12.576-32.96 0-45.536z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["checkmark","tick","approve","submit"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":0,"setId":1,"iconIdx":136},{"icon":{"paths":["M1020.192 401.824c-8.864-25.568-31.616-44.288-59.008-48.352l-266.432-39.616-115.808-240.448c-12.192-25.248-38.272-41.408-66.944-41.408s-54.752 16.16-66.944 41.408l-115.808 240.448-266.464 39.616c-27.36 4.064-50.112 22.784-58.944 48.352-8.8 25.632-2.144 53.856 17.184 73.12l195.264 194.944-45.28 270.432c-4.608 27.232 7.2 54.56 30.336 70.496 12.704 8.736 27.648 13.184 42.592 13.184 12.288 0 24.608-3.008 35.776-8.992l232.288-125.056 232.32 125.056c11.168 5.984 23.488 8.992 35.744 8.992 14.944 0 29.888-4.448 42.624-13.184 23.136-15.936 34.88-43.264 30.304-70.496l-45.312-270.432 195.328-194.944c19.296-19.296 25.92-47.52 17.184-73.12zM754.816 619.616c-16.384 16.32-23.808 39.328-20.064 61.888l45.312 270.432-232.32-124.992c-11.136-6.016-23.424-8.992-35.776-8.992-12.288 0-24.608 3.008-35.744 8.992l-232.32 124.992 45.312-270.432c3.776-22.56-3.648-45.568-20.032-61.888l-195.264-194.944 266.432-39.68c24.352-3.616 45.312-18.848 55.776-40.576l115.872-240.384 115.84 240.416c10.496 21.728 31.424 36.928 55.744 40.576l266.496 39.68-195.264 194.912z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star","favorite"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":3,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":0,"setId":1,"iconIdx":137},{"icon":{"paths":["M409.6 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM409.6 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["grid"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":0,"setId":1,"iconIdx":138},{"icon":{"paths":["M737.28 460.8h-296.96c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h296.96c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM839.68 716.8h-399.36c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h399.36c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM440.32 307.2h399.36c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2h-399.36c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2zM276.48 460.8h-92.16c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h92.16c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM276.48 716.8h-92.16c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h92.16c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM276.48 204.8h-92.16c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h92.16c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["list"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":1,"name":"list","prevSize":20,"code":59726},"setIdx":0,"setId":1,"iconIdx":139},{"icon":{"paths":["M636.518 0c68.608 0 102.912 46.694 102.912 100.198 0 66.816-59.597 128.614-137.165 128.614-64.973 0-102.861-38.4-101.069-101.888 0-53.402 45.107-126.925 135.322-126.925zM425.421 1024c-54.17 0-93.85-33.382-55.962-180.429l62.157-260.71c10.803-41.677 12.595-58.419 0-58.419-16.23 0-86.477 28.774-128.102 57.19l-27.034-45.056c131.686-111.923 283.187-177.51 348.211-177.51 54.118 0 63.13 65.178 36.096 165.376l-71.219 274.022c-12.595 48.384-7.219 65.075 5.427 65.075 16.23 0 69.478-20.070 121.805-61.798l30.72 41.677c-128.102 130.406-268.032 180.582-322.099 180.582z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["info"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":20,"code":59708,"name":"info"},"setIdx":0,"setId":1,"iconIdx":140}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showCodes":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"name":"icomoon","classSelector":".icon"},"historySize":50,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M251.429 100.571c-87.881 0-160 72.119-160 160v525.714c0 87.881 72.119 160 160 160h525.714c87.881 0 160-72.119 160-160v-525.714c0-87.881-72.119-160-160-160zM251.429 146.286h525.714c62.976 0 114.286 51.31 114.286 114.286v525.714c0 62.976-51.31 114.286-114.286 114.286h-525.714c-62.976 0-114.286-51.31-114.286-114.286v-525.714c0-62.976 51.31-114.286 114.286-114.286z","M434.286 288c-87.881 0-160 72.119-160 160v233.143c0 87.881 72.119 160 160 160h233.143c87.881 0 160-72.119 160-160v-233.143c0-87.881-72.119-160-160-160zM434.286 333.714h233.143c62.976 0 114.286 51.31 114.286 114.286v233.143c0 62.976-51.31 114.286-114.286 114.286h-233.143c-62.976 0-114.286-51.31-114.286-114.286v-233.143c0-62.976 51.31-114.286 114.286-114.286z","M406.082 465.511h-0.329c-12.617 0-22.857 10.24-22.857 22.857s10.24 22.857 22.857 22.857h306.944c12.617 0 22.857-10.24 22.857-22.857s-35.474-22.857-22.857-22.857h-0.329z","M406.082 602.654h-0.329c-12.617 0-22.857 10.24-22.857 22.857s10.24 22.857 22.857 22.857h224.658c12.617 0 22.857-10.24 22.857-22.857s-10.24-22.857-22.857-22.857h-0.329z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["component"]},"attrs":[{},{},{},{}],"properties":{"order":139,"id":48,"name":"component","prevSize":24,"code":59782},"setIdx":0,"setId":1,"iconIdx":0},{"icon":{"paths":["M456.158 36.282c-12.145-0.032-24.18 1.32-35.941 3.974-23.536 5.313-45.906 15.872-65.238 31.342-77.826 61.631-80.817 179.217-6.302 244.772 0.028 0.028 0.084 0.086 0.113 0.114 0.020 0.018 0.038 0.039 0.058 0.057 0.037 0.039 0.074 0.076 0.112 0.112l0.001 0.001c4.727 4.044 7.287 9.964 7.097 16.182-0.003 0.018 0.003 0.038 0 0.057-0.008 0.085-0.012 0.184-0.012 0.284s0.004 0.199 0.013 0.296l-0.001-0.013c0 10.503-8.234 18.737-18.737 18.737h-290.707c-5.436-0.020-10.354 4.898-10.334 10.334v192.479c0.079 40.118 25.509 70.246 57.289 81.875 31.779 11.628 70.726 5.088 96.694-25.494 48.914-57.384 140.83-35.582 158.809 37.644 6.312 27.401 0.010 56.217-17.261 78.411-35.813 45.415-103.666 46.801-141.265 2.839-0.153-0.167-0.32-0.317-0.501-0.448l-0.010-0.007c-0.073-0.080-0.147-0.154-0.224-0.224l-0.003-0.002c-25.873-30.135-64.41-36.684-96.012-25.21-31.887 11.577-57.465 41.733-57.517 81.988v191.003c-0.020 5.436 4.898 10.354 10.334 10.334h745.955c5.436 0.020 10.354-4.898 10.334-10.334l-0.852-616.898c0.020-5.436-4.898-10.354-10.334-10.334h-222.401c-10.503 0-18.737-8.234-18.737-18.737-0.019-5.72 2.466-11.020 6.87-14.592 0.080-0.073 0.154-0.147 0.224-0.224l0.002-0.003 0.227-0.227c97.336-84.032 59.622-244.251-65.125-275.83-0.169-0.034-0.365-0.054-0.566-0.057l-0.002-0c-0.018-0.004-0.038 0.004-0.058 0h-0.113c-11.884-2.753-23.91-4.17-35.884-4.202zM454.682 105.041c6.891 0.035 13.821 0.856 20.667 2.441 73.201 17.648 95.396 109.369 38.439 158.582-30.669 26.067-37.154 65.105-25.38 96.921 11.773 31.813 42.084 57.204 82.329 57.006h164.090v499.65h-629.673l-0.795-133.884c0.026-10.44 8.193-18.619 18.623-18.68 5.89 0.174 11.341 2.823 15.103 7.324 0.055 0.060 0.111 0.116 0.169 0.17l0.002 0.002c0.028 0.028 0.086 0.087 0.114 0.113 65.15 75.665 183.646 73.404 245.737-4.769l0.058-0.058c0.076-0.085 0.151-0.178 0.22-0.275l0.007-0.010c30.825-38.562 42.246-89.164 31.058-137.234-0.010-0.168-0.030-0.324-0.062-0.475l0.004 0.021c-30.581-126.005-192.369-164.654-276.681-66.145-0.019 0.019-0.037 0.038-0.055 0.057l-0.001 0.001c-0.175 0.215-0.297 0.397-0.454 0.624-5.948 8.251-13.969 9.414-21.519 6.699-7.485-2.692-12.925-8.644-12.378-18.623v-0.172c0.003-0.041-0.003-0.073 0-0.113 0.017-0.131 0.045-0.267 0.057-0.397 0.002-0.043 0.003-0.092 0.003-0.142s-0.001-0.1-0.003-0.149l0 0.007v-133.259h233.53c40.255-0.052 70.451-25.629 82.045-57.517 11.514-31.669 4.916-70.308-25.38-96.183 0-0.008 0-0.018 0-0.028s-0-0.020-0-0.030l0 0.002c-0.064-0.053-0.108-0.117-0.172-0.17-0.106-0.123-0.218-0.234-0.337-0.337l-0.004-0.003c-43.965-37.601-42.63-105.454 2.782-141.265 11.117-8.651 23.938-14.535 37.36-17.488 6.716-1.478 13.596-2.249 20.497-2.214z"],"attrs":[{}],"width":839,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["noun_extension_1559208"]},"attrs":[{}],"properties":{"order":138,"id":46,"name":"plugin","prevSize":24,"code":59781},"setIdx":0,"setId":1,"iconIdx":2},{"icon":{"paths":["M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143zM559.429 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"attrs":[{}],"width":567,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-double-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59773,"name":"angle-double-right"},"setIdx":0,"setId":1,"iconIdx":3},{"icon":{"paths":["M358.286 786.286c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143zM577.714 786.286c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143z"],"attrs":[{}],"width":603,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-double-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":24,"code":59774,"name":"angle-double-left"},"setIdx":0,"setId":1,"iconIdx":4},{"icon":{"paths":["M801.714 168.571c5.714 13.714 2.857 29.714-8 40l-281.714 281.714v424c0 14.857-9.143 28-22.286 33.714-4.571 1.714-9.714 2.857-14.286 2.857-9.714 0-18.857-3.429-25.714-10.857l-146.286-146.286c-6.857-6.857-10.857-16-10.857-25.714v-277.714l-281.714-281.714c-10.857-10.286-13.714-26.286-8-40 5.714-13.143 18.857-22.286 33.714-22.286h731.429c14.857 0 28 9.143 33.714 22.286z"],"attrs":[{}],"width":805,"isMulticolor":false,"isMulticolor2":false,"tags":["filter"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59768,"name":"filter-filled"},"setIdx":0,"setId":1,"iconIdx":5},{"icon":{"paths":["M950.857 932.571v-621.714c0-9.714-8.571-18.286-18.286-18.286h-621.714c-9.714 0-18.286 8.571-18.286 18.286v621.714c0 9.714 8.571 18.286 18.286 18.286h621.714c9.714 0 18.286-8.571 18.286-18.286zM1024 310.857v621.714c0 50.286-41.143 91.429-91.429 91.429h-621.714c-50.286 0-91.429-41.143-91.429-91.429v-621.714c0-50.286 41.143-91.429 91.429-91.429h621.714c50.286 0 91.429 41.143 91.429 91.429zM804.571 91.429v91.429h-73.143v-91.429c0-9.714-8.571-18.286-18.286-18.286h-621.714c-9.714 0-18.286 8.571-18.286 18.286v621.714c0 9.714 8.571 18.286 18.286 18.286h91.429v73.143h-91.429c-50.286 0-91.429-41.143-91.429-91.429v-621.714c0-50.286 41.143-91.429 91.429-91.429h621.714c50.286 0 91.429 41.143 91.429 91.429z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["clone"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59754,"name":"clone"},"setIdx":0,"setId":1,"iconIdx":6},{"icon":{"paths":["M498.787 330.323v-49.548h112.31v-66.065c0-49.548-39.639-89.187-89.187-89.187s-89.187 39.639-89.187 89.187v541.729l89.187 161.858 89.187-161.858v-426.116z","M360.052 716.8h-66.065c-59.458 0-105.703-46.245-105.703-105.703v-254.348c0-59.458 46.245-105.703 105.703-105.703h66.065v-42.942h-66.065c-82.581 0-148.645 66.065-148.645 148.645v254.348c0 82.581 66.065 148.645 148.645 148.645h66.065z","M852.232 260.955c-26.426-33.032-66.065-52.852-109.006-52.852h-59.458v42.942h39.639c42.942 0 82.581 19.819 109.006 52.852l145.342 181.677-142.039 178.374c-26.426 33.032-69.368 52.852-112.31 52.852h-36.335v42.942h56.155c42.942 0 85.884-19.819 112.31-52.852l178.374-221.316z"],"width":1140,"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Tags"],"grid":14},"attrs":[{},{},{}],"properties":{"order":119,"id":1,"name":"control-Tags","prevSize":24,"code":59747},"setIdx":0,"setId":1,"iconIdx":7},{"icon":{"paths":["M384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM998.4 844.8h-614.4c-38.406 15.539-22.811 37.543 0 51.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z","M0 0v307.2h307.2v-307.2zM47.4 47.4h212.4v212.4h-212.4z","M0 716.8v307.2h307.2v-307.2zM47.4 764.2h212.4v212.4h-212.4z","M0 358.4v307.2h307.2v-307.2zM47.4 405.8h212.4v212.4h-212.4z","M89.6 89.6h128v128h-128v-128z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Checkboxes"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":2,"name":"control-Checkboxes, control-List","prevSize":24,"code":59746},"setIdx":0,"setId":1,"iconIdx":8},{"icon":{"paths":["M159.073 665.6l-159.073-134.055 159.073-133.819 36.818 37.29-117.062 96.057 117.062 97.237z","M493.247 536.029q0 33.042-9.441 57.115-9.205 24.073-25.961 40.122-16.521 15.813-39.178 23.601-22.657 7.552-49.327 7.552-26.197 0-48.855-4.012-22.421-3.776-42.954-10.385v-323.338h57.587v78.356l-2.36 47.203q12.981-16.757 30.21-26.905 17.465-10.149 41.774-10.149 21.241 0 37.762 8.496t27.614 24.309q11.329 15.577 17.229 37.998 5.9 22.185 5.9 50.035zM432.828 538.389q0-19.825-2.832-33.75t-8.26-22.893q-5.192-8.969-12.981-12.981-7.552-4.248-17.465-4.248-14.633 0-28.086 11.801-13.217 11.801-28.086 32.098v104.79q6.844 2.596 16.757 4.248 10.149 1.652 20.533 1.652 13.689 0 24.781-5.664 11.329-5.664 19.117-16.049 8.024-10.385 12.273-25.253 4.248-15.105 4.248-33.75z","M700.682 513.608q0.472-13.453-1.416-22.893-1.652-9.441-5.664-15.577-3.776-6.136-9.441-8.968t-12.981-2.832q-12.745 0-26.433 10.621-13.453 10.385-29.738 34.458v151.756h-59.003v-239.789h52.159l2.124 34.93q5.9-9.205 13.217-16.521 7.552-7.316 16.521-12.509 9.205-5.428 20.297-8.26t24.309-2.832q18.173 0 32.098 6.372 14.161 6.136 23.601 18.409 9.677 12.273 14.161 30.918 4.72 18.409 4.012 42.718z","M864.927 397.725l159.073 133.819-159.073 134.055-36.582-37.29 116.826-96.293-116.826-97.001z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Html"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":116,"id":3,"name":"control-Html","prevSize":24,"code":59744},"setIdx":0,"setId":1,"iconIdx":9},{"icon":{"paths":["M251.429 100.58c-87.896 0-160 72.104-160 160v525.714c0 87.896 72.104 160 160 160h525.714c87.896 0 160-72.104 160-160v-525.714c0-87.896-72.104-160-160-160zM251.429 146.295h525.714c62.961 0 114.286 51.325 114.286 114.286v525.714c0 62.961-51.325 114.286-114.286 114.286h-525.714c-62.961 0-114.286-51.325-114.286-114.286v-525.714c0-62.961 51.325-114.286 114.286-114.286z","M251.429 306.295c-0.096-0.001-0.21-0.002-0.323-0.002-12.625 0-22.859 10.235-22.859 22.859s10.235 22.859 22.859 22.859c0.114 0 0.227-0.001 0.34-0.002l-0.017 0h525.714c0.096 0.001 0.21 0.002 0.323 0.002 12.625 0 22.859-10.235 22.859-22.859s-10.235-22.859-22.859-22.859c-0.114 0-0.227 0.001-0.34 0.002l0.017-0z","M251.429 443.438c-0.096-0.001-0.21-0.002-0.323-0.002-12.625 0-22.859 10.235-22.859 22.859s10.235 22.859 22.859 22.859c0.114 0 0.227-0.001 0.34-0.002l-0.017 0h297.143c0.096 0.001 0.21 0.002 0.323 0.002 12.625 0 22.859-10.235 22.859-22.859s-10.235-22.859-22.859-22.859c-0.114 0-0.227 0.001-0.34 0.002l0.017-0z","M251.429 580.58c-0.096-0.001-0.21-0.002-0.323-0.002-12.625 0-22.859 10.235-22.859 22.859s10.235 22.859 22.859 22.859c0.114 0 0.227-0.001 0.34-0.002l-0.017 0h297.143c0.096 0.001 0.21 0.002 0.323 0.002 12.625 0 22.859-10.235 22.859-22.859s-10.235-22.859-22.859-22.859c-0.114 0-0.227 0.001-0.34 0.002l0.017-0z"],"width":1029,"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["single-content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":112,"id":4,"name":"single-content, search-Content, type-Component","prevSize":24,"code":59736},"setIdx":0,"setId":1,"iconIdx":10},{"icon":{"paths":["M777.143 946.286h-525.714c-89.143 0-160-70.857-160-160v-297.143c0-89.143 70.857-160 160-160h525.714c89.143 0 160 70.857 160 160v297.143c0 89.143-70.857 160-160 160zM251.429 374.857c-64 0-114.286 50.286-114.286 114.286v297.143c0 64 50.286 114.286 114.286 114.286h525.714c64 0 114.286-50.286 114.286-114.286v-297.143c0-64-50.286-114.286-114.286-114.286h-525.714z","M731.429 580.571h-457.143c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h457.143c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M502.857 740.571h-228.571c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h228.571c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M777.143 260.571h-525.714c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h525.714c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M685.714 146.286h-342.857c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h342.857c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z"],"width":1029,"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["multiple-content"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":5,"name":"multiple-content, type-Components","prevSize":24,"code":59735},"setIdx":0,"setId":1,"iconIdx":11},{"icon":{"paths":["M832 268.8h-657.92c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h657.92c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 453.12h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 642.56h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 832h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-Array"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":108,"id":6,"name":"type-Array","prevSize":24,"code":59734},"setIdx":0,"setId":1,"iconIdx":12},{"icon":{"paths":["M292.571 713.143v128c0 20-16.571 36.571-36.571 36.571h-146.286c-20 0-36.571-16.571-36.571-36.571v-128c0-20 16.571-36.571 36.571-36.571h146.286c20 0 36.571 16.571 36.571 36.571zM309.714 109.714l-16 438.857c-0.571 20-17.714 36.571-37.714 36.571h-146.286c-20 0-37.143-16.571-37.714-36.571l-16-438.857c-0.571-20 15.429-36.571 35.429-36.571h182.857c20 0 36 16.571 35.429 36.571z"],"width":366,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":24,"code":59733,"name":"exclamation"},"setIdx":0,"setId":1,"iconIdx":13},{"icon":{"paths":["M512 26.38l-424.96 242.8v485.64l424.96 242.8 424.96-242.8v-485.64l-424.96-242.8zM512 235.52l245.76 138.24v276.48l-245.76 138.24-245.76-138.24v-276.48l245.76-138.24z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["orleans"],"grid":14},"attrs":[{}],"properties":{"order":99,"id":8,"name":"orleans","prevSize":24,"code":59723},"setIdx":0,"setId":1,"iconIdx":14},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v204.8h51.2v-204.8h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-307.2v51.2h307.2c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4z","M153.6 640v281.6h358.4v-281.6zM179.2 640v-76.8c0-84.48 69.12-153.6 153.6-153.6s153.6 69.12 153.6 153.6v76.8h-51.2v-76.8c0-56.32-46.080-102.4-102.4-102.4s-102.4 46.080-102.4 102.4v76.8z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-lock"],"grid":14},"attrs":[{},{}],"properties":{"order":97,"id":9,"name":"document-lock","prevSize":24,"code":59721},"setIdx":0,"setId":1,"iconIdx":15},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v153.6h51.2v-153.6h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7z","M102.4 357.532h460.8v52.068h-460.8v-52.068z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-unpublish"],"grid":14},"attrs":[{},{}],"properties":{"order":96,"id":10,"name":"document-unpublish","prevSize":24,"code":59711},"setIdx":0,"setId":1,"iconIdx":16},{"icon":{"paths":["M614.286 420.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8-5.714 13.143-5.714 4.571 0 9.714 2.286 13.143 5.714l224.571 224.571 224.571-224.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":24,"code":59648,"name":"angle-down"},"setIdx":0,"setId":1,"iconIdx":17},{"icon":{"paths":["M358.286 310.857c0 4.571-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8 5.714 13.143z"],"width":384,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":12,"prevSize":24,"code":59649,"name":"angle-left"},"setIdx":0,"setId":1,"iconIdx":18},{"icon":{"paths":["M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8-5.714-13.143 0-4.571 2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":347,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":13,"prevSize":24,"code":59697,"name":"angle-right"},"setIdx":0,"setId":1,"iconIdx":19},{"icon":{"paths":["M614.286 676.571c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8 5.714-13.143 5.714-4.571 0-9.714-2.286-13.143-5.714l-224.571-224.571-224.571 224.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":14,"prevSize":24,"code":59651,"name":"angle-up"},"setIdx":0,"setId":1,"iconIdx":20},{"icon":{"paths":["M592 393.6h-156.8c-57.6 0-105.6-48-105.6-105.6v-182.4c0-57.6 48-105.6 105.6-105.6h156.8c57.6 0 105.6 48 105.6 105.6v182.4c-3.2 57.6-48 105.6-105.6 105.6zM432 64c-22.4 0-41.6 19.2-41.6 41.6v182.4c0 22.4 19.2 41.6 41.6 41.6h156.8c22.4 0 41.6-19.2 41.6-41.6v-182.4c0-22.4-19.2-41.6-41.6-41.6h-156.8z","M195.2 1024c-105.6 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c3.2 105.6-86.4 195.2-195.2 195.2zM195.2 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 134.4 131.2 134.4 73.6 0 131.2-60.8 131.2-131.2 3.2-73.6-57.6-134.4-131.2-134.4z","M828.8 1024c-108.8 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c0 105.6-89.6 195.2-195.2 195.2zM828.8 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 131.2 131.2 131.2 73.6 0 131.2-60.8 131.2-131.2s-60.8-131.2-131.2-131.2z","M332.8 640c-6.4 0-12.8 0-16-3.2-16-9.6-19.2-28.8-9.6-44.8l83.2-137.6c9.6-16 28.8-19.2 44.8-9.6s19.2 28.8 9.6 44.8l-83.2 137.6c-6.4 6.4-16 12.8-28.8 12.8z","M691.2 640c-9.6 0-22.4-6.4-28.8-16l-83.2-137.6c-9.6-16-3.2-35.2 9.6-44.8s35.2-3.2 44.8 9.6l83.2 137.6c9.6 16 3.2 35.2-9.6 44.8-6.4 6.4-12.8 6.4-16 6.4z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["api"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":15,"name":"api","prevSize":24,"code":59717},"setIdx":0,"setId":1,"iconIdx":21},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M771.2 860.8h-438.4c-12.8 0-22.4-6.4-28.8-19.2s-3.2-25.6 3.2-35.2l300.8-355.2c6.4-6.4 16-12.8 25.6-12.8s19.2 6.4 25.6 12.8l192 275.2c3.2 3.2 3.2 6.4 3.2 9.6 16 44.8 3.2 73.6-6.4 89.6-22.4 32-70.4 35.2-76.8 35.2zM403.2 796.8h371.2c6.4 0 22.4-3.2 25.6-9.6 3.2-3.2 3.2-12.8 0-25.6l-166.4-236.8-230.4 272z","M332.8 502.4c-76.8 0-140.8-64-140.8-140.8s64-140.8 140.8-140.8 140.8 64 140.8 140.8-60.8 140.8-140.8 140.8zM332.8 284.8c-41.6 0-76.8 32-76.8 76.8s35.2 76.8 76.8 76.8 76.8-35.2 76.8-76.8-32-76.8-76.8-76.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["assets"],"grid":14},"attrs":[{},{},{}],"properties":{"order":95,"id":16,"name":"assets, search-Asset","prevSize":24,"code":59720},"setIdx":0,"setId":1,"iconIdx":22},{"icon":{"paths":["M932.571 548.571c0 20-16.571 36.571-36.571 36.571h-128c0 71.429-15.429 125.143-38.286 165.714l118.857 119.429c14.286 14.286 14.286 37.143 0 51.429-6.857 7.429-16.571 10.857-25.714 10.857s-18.857-3.429-25.714-10.857l-113.143-112.571s-74.857 68.571-172 68.571v-512h-73.143v512c-103.429 0-178.857-75.429-178.857-75.429l-104.571 118.286c-7.429 8-17.143 12-27.429 12-8.571 0-17.143-2.857-24.571-9.143-14.857-13.714-16-36.571-2.857-52l115.429-129.714c-20-39.429-33.143-90.286-33.143-156.571h-128c-20 0-36.571-16.571-36.571-36.571s16.571-36.571 36.571-36.571h128v-168l-98.857-98.857c-14.286-14.286-14.286-37.143 0-51.429s37.143-14.286 51.429 0l98.857 98.857h482.286l98.857-98.857c14.286-14.286 37.143-14.286 51.429 0s14.286 37.143 0 51.429l-98.857 98.857v168h128c20 0 36.571 16.571 36.571 36.571zM658.286 219.429h-365.714c0-101.143 81.714-182.857 182.857-182.857s182.857 81.714 182.857 182.857z"],"width":951,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":17,"prevSize":24,"code":59709,"name":"bug"},"setIdx":0,"setId":1,"iconIdx":23},{"icon":{"paths":["M585.143 402.286c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857s-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714 0-20 16.571-36.571 36.571-36.571h512c20 0 36.571 16.571 36.571 36.571z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":18,"prevSize":24,"code":59692,"name":"caret-down"},"setIdx":0,"setId":1,"iconIdx":24},{"icon":{"paths":["M365.714 256v512c0 20-16.571 36.571-36.571 36.571-9.714 0-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714s4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857 20 0 36.571 16.571 36.571 36.571z"],"width":402,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":24,"code":59690,"name":"caret-left"},"setIdx":0,"setId":1,"iconIdx":25},{"icon":{"paths":["M329.143 512c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857-20 0-36.571-16.571-36.571-36.571v-512c0-20 16.571-36.571 36.571-36.571 9.714 0 18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":329,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":20,"prevSize":24,"code":59689,"name":"caret-right"},"setIdx":0,"setId":1,"iconIdx":26},{"icon":{"paths":["M585.143 694.857c0 20-16.571 36.571-36.571 36.571h-512c-20 0-36.571-16.571-36.571-36.571 0-9.714 4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857s18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":21,"prevSize":24,"code":59691,"name":"caret-up"},"setIdx":0,"setId":1,"iconIdx":27},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M480 448h-211.2c-57.6 0-105.6-48-105.6-105.6v-73.6c0-57.6 48-105.6 105.6-105.6h211.2c57.6 0 105.6 48 105.6 105.6v73.6c0 57.6-48 105.6-105.6 105.6zM268.8 227.2c-22.4 0-41.6 19.2-41.6 41.6v73.6c0 22.4 19.2 41.6 41.6 41.6h211.2c22.4 0 41.6-19.2 41.6-41.6v-73.6c0-22.4-19.2-41.6-41.6-41.6h-211.2z","M828.8 611.2h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M553.6 777.6h-358.4c-19.2 0-32-12.8-32-32s12.8-32 32-32h355.2c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":93,"id":22,"name":"contents, trigger-ContentChanged","prevSize":24,"code":59718},"setIdx":0,"setId":1,"iconIdx":28},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date"],"grid":14},"attrs":[{}],"properties":{"order":71,"id":23,"name":"control-Date","prevSize":24,"code":59702},"setIdx":0,"setId":1,"iconIdx":29},{"icon":{"paths":["M486.4 409.6h51.2c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM230.4 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM230.4 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM51.2 742.4v-435.2h665.6v102.4h51.2v-281.6c0-42.342-34.458-76.8-76.8-76.8h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-256v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v614.4c0 42.342 34.458 76.8 76.8 76.8h332.8v-51.2h-332.8c-14.080 0-25.6-11.469-25.6-25.6zM51.2 128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h256v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128h-665.6v-128zM384 409.6c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM742.4 460.8c-155.546 0-281.6 126.054-281.6 281.6s126.054 281.6 281.6 281.6 281.6-126.054 281.6-281.6-126.054-281.6-281.6-281.6zM742.4 972.8c-127.232 0-230.4-103.168-230.4-230.4s103.168-230.4 230.4-230.4 230.4 103.168 230.4 230.4-103.168 230.4-230.4 230.4zM384 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM384 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM844.8 716.8c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-102.4c-14.131 0-25.6-11.469-25.6-25.6v-102.4c0-14.131 11.469-25.6 25.6-25.6s25.6 11.469 25.6 25.6v76.8h76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date-time"],"grid":14},"attrs":[{}],"properties":{"order":70,"id":24,"name":"control-DateTime","prevSize":24,"code":59703},"setIdx":0,"setId":1,"iconIdx":30},{"icon":{"paths":["M793.6 609.416h-61.838v-28.108h-0.783q-21.135 33.092-62.034 33.092-37.573 0-60.469-26.912-22.896-27.112-22.896-75.554 0-50.635 25.244-81.136t66.144-30.501q38.747 0 54.011 28.308h0.783v-121.405h61.838v302.216zM732.936 510.139v-15.35q0-19.935-11.35-33.092t-29.549-13.157q-20.548 0-32.093 16.546-11.546 16.347-11.546 45.053 0 26.912 11.154 41.465t30.919 14.553q18.786 0 30.528-15.35 11.937-15.35 11.937-40.668zM548.594 609.416h-61.643v-116.421q0-44.455-32.093-44.455-15.264 0-24.853 13.357t-9.589 33.292v114.228h-61.839v-117.617q0-43.259-31.506-43.259-15.851 0-25.44 12.758-9.393 12.758-9.393 34.687v113.431h-61.838v-204.135h61.838v31.896h0.783q9.589-16.347 26.81-26.514 17.417-10.366 37.964-10.366 42.465 0 58.12 38.076 22.896-38.076 67.318-38.076 65.361 0 65.361 82.133v126.987zM0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8zM819.2 0v204.8h204.8v-204.8zM51.2 51.2h102.4v102.4h-102.4zM870.4 51.2h102.4v102.4h-102.4zM281.6 76.8v51.2h102.4v-51.2zM486.4 76.8v51.2h102.4v-51.2zM691.2 76.8v51.2h102.4v-51.2zM896 281.6v102.4h51.2v-102.4zM76.8 384v102.4h51.2v-102.4zM896 486.4v102.4h51.2v-102.4zM76.8 588.8v102.4h51.2v-102.4zM896 691.2v102.4h51.2v-102.4zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8zM51.2 870.4h102.4v102.4h-102.4zM870.4 870.4h102.4v102.4h-102.4zM384 896v51.2h102.4v-51.2zM588.8 896v51.2h102.4v-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Markdown"],"grid":14},"attrs":[{}],"properties":{"order":72,"id":25,"name":"control-Markdown","prevSize":24,"code":59704},"setIdx":0,"setId":1,"iconIdx":31},{"icon":{"paths":["M292.571 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857z"],"width":1024,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["th"],"defaultCode":61450,"grid":14},"attrs":[],"properties":{"name":"grid","id":26,"order":83,"prevSize":24,"code":61450},"setIdx":0,"setId":1,"iconIdx":32},{"icon":{"paths":["M877.714 768v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 475.429v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 182.857v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571z"],"width":877.7142857142857,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["bars","navicon","reorder"],"defaultCode":61641,"grid":14},"attrs":[],"properties":{"name":"list1","id":27,"order":89,"prevSize":24,"code":61641},"setIdx":0,"setId":1,"iconIdx":33},{"icon":{"paths":["M512 64c-131.696 0-239.125 107.4-239.125 239 0 65.8 24.831 146.717 65.375 215.25 19.653 33.221 43.902 63.853 71.75 87.125-59.423 7.524-122.009 9.415-172.125 32-79.809 35.967-144.343 94.74-172.375 178.625-1.5 9.499 0 0-1.5 9v0.499c0 73.995 60.563 134.501 134.375 134.501h627.125c73.888 0 134.5-60.506 134.5-134.5l-1.5-9.375c-27.845-84.263-92.273-143.119-172.125-179-50.17-22.544-112.844-24.421-172.375-31.875 27.792-23.26 52.002-53.831 71.625-87 40.544-68.533 65.375-149.45 65.375-215.25 0-131.6-107.304-239-239-239zM512 124c99.241 0 179 79.875 179 179 0 49.562-21.877 125.381-57 184.75s-81.435 98.75-122 98.75c-40.565 0-86.877-39.381-122-98.75s-57.125-135.188-57.125-184.75c0-99.125 79.884-179 179.125-179zM512 646.5c92.551 0 180.829 14.406 249.75 45.375 66.784 30.009 113.649 74.724 136.5 137.75-2.447 39.259-32.9 70.375-72.75 70.375h-627.125c-39.678 0-70.116-31.051-72.625-70.25 22.978-62.705 69.953-107.523 136.75-137.625 68.937-31.067 157.205-45.625 249.5-45.625z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user-o"],"grid":14},"attrs":[{}],"properties":{"order":64,"id":28,"name":"user-o","prevSize":24,"code":59698},"setIdx":0,"setId":1,"iconIdx":34},{"icon":{"paths":["M217.6 992c-3.2 0-3.2 0-6.4 0h-3.2c-144-25.6-208-144-208-249.6 0-99.2 57.6-208 185.6-240v-147.2c0-19.2 12.8-32 32-32s32 12.8 32 32v172.8c0 16-12.8 28.8-25.6 32-108.8 16-160 102.4-160 182.4s48 166.4 153.6 185.6h6.4c16 3.2 28.8 19.2 25.6 38.4-3.2 16-16 25.6-32 25.6z","M774.4 1001.6c0 0 0 0 0 0-102.4 0-211.2-60.8-243.2-185.6h-176c-19.2 0-32-12.8-32-32s12.8-32 32-32h201.6c16 0 28.8 12.8 32 25.6 16 108.8 102.4 156.8 182.4 160 80 0 166.4-48 185.6-153.6v-3.2c3.2-16 19.2-28.8 38.4-25.6 16 3.2 28.8 19.2 25.6 38.4v3.2c-22.4 140.8-140.8 204.8-246.4 204.8z","M787.2 678.4c-19.2 0-32-12.8-32-32v-176c0-16 12.8-28.8 25.6-32 108.8-16 156.8-102.4 160-182.4 0-80-48-166.4-153.6-185.6h-3.2c-19.2-6.4-32-22.4-28.8-38.4s19.2-28.8 38.4-25.6h3.2c144 25.6 208 144 208 249.6 0 99.2-60.8 208-185.6 240v150.4c0 16-16 32-32 32z","M41.6 246.4c-3.2 0-3.2 0-6.4 0-16-3.2-28.8-19.2-25.6-35.2v-3.2c25.6-144 140.8-208 246.4-208 0 0 3.2 0 3.2 0 99.2 0 208 60.8 240 185.6h147.2c19.2 0 32 12.8 32 32s-12.8 32-32 32h-172.8c-16 0-28.8-12.8-32-25.6-16-108.8-102.4-156.8-182.4-160-80 0-166.4 48-185.6 153.6v3.2c-3.2 16-16 25.6-32 25.6z","M256 387.2c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-25.6 22.4-57.6 35.2-92.8 35.2zM256 192c-16 0-32 6.4-44.8 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-32-19.2-44.8-28.8-19.2-48-19.2z","M771.2 873.6c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-25.6 57.6-38.4 92.8-38.4s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-28.8 25.6-60.8 38.4-92.8 38.4zM771.2 678.4c-19.2 0-35.2 6.4-48 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-35.2-19.2-48-28.8-16-44.8-16z","M745.6 387.2c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 60.8-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM745.6 192c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z","M259.2 873.6c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM259.2 678.4c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z"],"attrs":[{},{},{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["webhooks"],"grid":14},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":29,"name":"rules, search-Rule","prevSize":24,"code":59719},"setIdx":0,"setId":1,"iconIdx":35},{"icon":{"paths":["M470 384l60 60-154 154h392v-428h86v512h-478l154 154-60 60-256-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["subdirectory_arrow_left"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59780,"name":"enter"},"setIdx":0,"setId":1,"iconIdx":36},{"icon":{"paths":["M298 384h214v42h-214v-42zM406 598q80 0 136-56t56-136-56-136-136-56-136 56-56 136 56 136 136 56zM662 598l212 212-64 64-212-212v-34l-12-12q-76 66-180 66-116 0-197-80t-81-196 81-197 197-81 196 81 80 197q0 42-20 95t-46 85l12 12h34z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["zoom_out"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":4,"prevSize":24,"code":59778,"name":"zoom_out"},"setIdx":0,"setId":1,"iconIdx":37},{"icon":{"paths":["M512 426h-86v86h-42v-86h-86v-42h86v-86h42v86h86v42zM406 598q80 0 136-56t56-136-56-136-136-56-136 56-56 136 56 136 136 56zM662 598l212 212-64 64-212-212v-34l-12-12q-76 66-180 66-116 0-197-80t-81-196 81-197 197-81 196 81 80 197q0 42-20 95t-46 85l12 12h34z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["zoom_in"],"grid":24},"attrs":[{}],"properties":{"order":2,"id":3,"prevSize":24,"code":59779,"name":"zoom_in"},"setIdx":0,"setId":1,"iconIdx":38},{"icon":{"paths":["M810 896v-86h86q0 34-26 60t-60 26zM810 554v-84h86v84h-86zM640 214v-86h86v86h-86zM810 726v-86h86v86h-86zM470 982v-940h84v940h-84zM810 128q34 0 60 26t26 60h-86v-86zM128 214q0-34 26-60t60-26h170v86h-170v596h170v86h-170q-34 0-60-26t-26-60v-596zM810 384v-86h86v86h-86zM640 896v-86h86v86h-86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["flip"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":2,"name":"flip","prevSize":24,"code":59775},"setIdx":0,"setId":1,"iconIdx":39},{"icon":{"paths":["M720 660q34-46 44-106h86q-12 92-68 166zM554 764q60-10 106-44l62 62q-72 56-168 68v-86zM850 470h-86q-10-60-44-106l62-60q58 72 68 166zM664 236l-194 190v-166q-92 16-153 87t-61 165 61 165 153 87v86q-126-16-213-112t-87-226 87-226 213-112v-132z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["rotate_right"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"name":"rotate_right","prevSize":24,"code":59776},"setIdx":0,"setId":1,"iconIdx":40},{"icon":{"paths":["M554 174q126 16 213 112t87 226-87 226-213 112v-86q92-16 153-87t61-165-61-165-153-87v166l-194-190 194-194v132zM302 782l62-62q46 34 106 44v86q-96-12-168-68zM260 554q10 58 42 106l-60 60q-56-74-68-166h86zM304 364q-36 52-44 106h-86q12-90 70-166z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["rotate_left"],"grid":24},"attrs":[{}],"properties":{"order":2,"id":0,"name":"rotate_left","prevSize":24,"code":59777},"setIdx":0,"setId":1,"iconIdx":41},{"icon":{"paths":["M810 598v-86h-128v-128h-84v128h-128v86h128v128h84v-128h128zM854 256q36 0 60 25t24 61v426q0 36-24 61t-60 25h-684q-36 0-60-25t-24-61v-512q0-36 24-61t60-25h256l86 86h342z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["create_new_folder"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59771,"name":"create_new_folder"},"setIdx":0,"setId":1,"iconIdx":42},{"icon":{"paths":["M426 170l86 86h342q34 0 59 26t25 60v426q0 34-25 60t-59 26h-684q-34 0-59-26t-25-60v-512q0-34 25-60t59-26h256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["folder"],"grid":24},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":24,"code":59772,"name":"folder"},"setIdx":0,"setId":1,"iconIdx":43},{"icon":{"paths":["M512 256q70 0 120 50t50 120q0 54-64 111t-64 103h-84q0-46 20-79t44-48 44-37 20-50q0-34-26-59t-60-25-60 25-26 59h-84q0-70 50-120t120-50zM512 854q140 0 241-101t101-241-101-241-241-101-241 101-101 241 101 241 241 101zM512 86q176 0 301 125t125 301-125 301-301 125-301-125-125-301 125-301 301-125zM470 768v-86h84v86h-84z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["help_outline"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59770,"name":"help2"},"setIdx":0,"setId":1,"iconIdx":44},{"icon":{"paths":["M236.416 92.117c-6.528-4.267-14.507-6.784-23.083-6.784-23.552 0-42.667 19.115-42.667 42.667v768c-0.043 7.765 2.133 15.872 6.784 23.083 12.757 19.84 39.125 25.557 58.965 12.8l597.333-384c4.864-3.072 9.344-7.424 12.8-12.8 12.757-19.84 6.997-46.208-12.8-58.965zM256 206.165l475.776 305.835-475.776 305.835z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59769,"name":"trigger-Manual, play-line"},"setIdx":0,"setId":1,"iconIdx":45},{"icon":{"paths":["M128 170.667v298.667c0 58.88 23.936 112.299 62.464 150.869s91.989 62.464 150.869 62.464h409.003l-140.501 140.501c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0l213.333-213.333c3.925-3.925 7.083-8.619 9.259-13.824s3.243-10.795 3.243-16.341c0-10.923-4.181-21.845-12.501-30.165l-213.333-213.333c-16.683-16.683-43.691-16.683-60.331 0s-16.683 43.691 0 60.331l140.501 140.501h-409.003c-35.371 0-67.285-14.293-90.496-37.504s-37.504-55.125-37.504-90.496v-298.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["corner-down-right"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59767,"name":"corner-down-right"},"setIdx":0,"setId":1,"iconIdx":46},{"icon":{"paths":["M470 384v-86h84v86h-84zM512 854c188 0 342-154 342-342s-154-342-342-342-342 154-342 342 154 342 342 342zM512 86c236 0 426 190 426 426s-190 426-426 426-426-190-426-426 190-426 426-426zM470 726v-256h84v256h-84z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["info_outline"],"grid":24},"attrs":[{}],"properties":{"order":128,"id":0,"prevSize":24,"code":59764,"name":"info-outline"},"setIdx":0,"setId":1,"iconIdx":47},{"icon":{"paths":["M214 768h596v86h-596v-86zM384 682v-256h-170l298-298 298 298h-170v256h-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["file_upload"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59762,"name":"upload-2"},"setIdx":0,"setId":1,"iconIdx":48},{"icon":{"paths":["M678 726h138l-70-186zM790 426l192 512h-86l-48-128h-202l-48 128h-86l192-512h86zM550 642l-34 88-132-132-214 212-60-60 218-214c-54-60-96-124-128-194h86c26 50 58 98 98 142 62-68 108-146 136-228h-478v-86h300v-84h84v84h300v86h-126c-32 100-84 196-158 278l-2 2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["translate"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59759,"name":"translate"},"setIdx":0,"setId":1,"iconIdx":49},{"icon":{"paths":["M854 470v84h-520l238 240-60 60-342-342 342-342 60 60-238 240h520z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["arrow_back"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59758,"name":"arrow_back"},"setIdx":0,"setId":1,"iconIdx":50},{"icon":{"paths":["M768 512c-25.6 0-42.667 17.067-42.667 42.667v256c0 25.6-17.067 42.667-42.667 42.667h-469.333c-25.6 0-42.667-17.067-42.667-42.667v-469.333c0-25.6 17.067-42.667 42.667-42.667h256c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-256c-72.533 0-128 55.467-128 128v469.333c0 72.533 55.467 128 128 128h469.333c72.533 0 128-55.467 128-128v-256c0-25.6-17.067-42.667-42.667-42.667z","M934.4 110.933c-4.267-8.533-12.8-17.067-21.333-21.333-4.267-4.267-12.8-4.267-17.067-4.267h-256c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h153.6l-396.8 396.8c-17.067 17.067-17.067 42.667 0 59.733 8.533 8.533 17.067 12.8 29.867 12.8s21.333-4.267 29.867-12.8l396.8-396.8v153.6c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-256c0-4.267 0-12.8-4.267-17.067z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["external-link"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":2,"prevSize":24,"code":59757,"name":"external-link"},"setIdx":0,"setId":1,"iconIdx":51},{"icon":{"paths":["M810.667 85.333h-597.333c-72.533 0-128 55.467-128 128v597.333c0 72.533 55.467 128 128 128h597.333c72.533 0 128-55.467 128-128v-597.333c0-72.533-55.467-128-128-128zM853.333 810.667c0 25.6-17.067 42.667-42.667 42.667h-597.333c-25.6 0-42.667-17.067-42.667-42.667v-597.333c0-25.6 17.067-42.667 42.667-42.667h597.333c25.6 0 42.667 17.067 42.667 42.667v597.333z","M682.667 469.333h-341.333c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h341.333c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["minus-square"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":3,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":0,"setId":1,"iconIdx":52},{"icon":{"paths":["M810.667 85.333h-597.333c-72.533 0-128 55.467-128 128v597.333c0 72.533 55.467 128 128 128h597.333c72.533 0 128-55.467 128-128v-597.333c0-72.533-55.467-128-128-128zM853.333 810.667c0 25.6-17.067 42.667-42.667 42.667h-597.333c-25.6 0-42.667-17.067-42.667-42.667v-597.333c0-25.6 17.067-42.667 42.667-42.667h597.333c25.6 0 42.667 17.067 42.667 42.667v597.333z","M682.667 469.333h-128v-128c0-25.6-17.067-42.667-42.667-42.667s-42.667 17.067-42.667 42.667v128h-128c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h128v128c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-128h128c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["plus-square"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":4,"name":"plus-square","prevSize":24,"code":59752},"setIdx":0,"setId":1,"iconIdx":53},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":5,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":0,"setId":1,"iconIdx":54},{"icon":{"paths":["M854 682v-512h-684v598l86-86h598zM854 86c46 0 84 38 84 84v512c0 46-38 86-84 86h-598l-170 170v-768c0-46 38-84 84-84h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["chat_bubble_outline"],"grid":24},"attrs":[{}],"properties":{"order":133,"id":6,"name":"comments","prevSize":24,"code":59743},"setIdx":0,"setId":1,"iconIdx":55},{"icon":{"paths":["M512 128c212 0 384 172 384 384s-172 384-384 384c-88 0-170-30-234-80l60-60c50 34 110 54 174 54 166 0 298-132 298-298s-132-298-298-298-298 132-298 298h128l-172 170-170-170h128c0-212 172-384 384-384zM598 512c0 46-40 86-86 86s-86-40-86-86 40-86 86-86 86 40 86 86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings_backup_restore"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":24,"code":59739,"name":"backup"},"setIdx":0,"setId":1,"iconIdx":56},{"icon":{"paths":["M726 512c0 24-20 42-44 42h-426l-170 172v-598c0-24 18-42 42-42h554c24 0 44 18 44 42v384zM896 256c24 0 42 18 42 42v640l-170-170h-470c-24 0-42-18-42-42v-86h554v-384h86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["question_answer"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":8,"prevSize":24,"code":59738,"name":"support"},"setIdx":0,"setId":1,"iconIdx":57},{"icon":{"paths":["M918 384v128h-128v298h-128v-298h-128v-128h384zM106 170h556v128h-214v512h-128v-512h-214v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["text_fields"],"grid":24},"attrs":[{}],"properties":{"order":75,"id":9,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":0,"setId":1,"iconIdx":58},{"icon":{"paths":["M640 85.333q78 0 149.167 30.5t122.5 81.833 81.833 122.5 30.5 149.167q0 85-35 160.667t-96.667 129.167-140 77.5l21-20.667q18-18.333 28-42.667 9.333-22.667 9.333-49.333 0-6.667-0.333-9.333 59.333-41.333 93.833-105.833t34.5-139.5q0-60.667-23.667-116t-63.667-95.333-95.333-63.667-116-23.667q-55.333 0-106.5 19.833t-90 53.833-65 81.333-33.833 101h-88.667q-70.667 0-120.667 50t-50 120.667q0 38.667 15.167 71.667t39.833 54.167 54.833 33 60.833 11.833h50q11.667 29.333 30 48l37.667 37.333h-117.667q-69.667 0-128.5-34.333t-93.167-93.167-34.333-128.5 34.333-128.5 93.167-93.167 128.5-34.333h22q26.333-74.333 79.333-132.167t126.833-90.833 155.833-33zM554.667 426.667q17.667 0 30.167 12.5t12.5 30.167v281l55-55.333q12.333-12.333 30.333-12.333 18.333 0 30.5 12.167t12.167 30.5q0 18-12.333 30.333l-128 128q-12.333 12.333-30.333 12.333t-30.333-12.333l-128-128q-12.333-13-12.333-30.333 0-17.667 12.5-30.167t30.167-12.5q18 0 30.333 12.333l55 55.333v-281q0-17.667 12.5-30.167t30.167-12.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cloud-download"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":24,"code":59710,"name":"download"},"setIdx":0,"setId":1,"iconIdx":59},{"icon":{"paths":["M512 682.667h-341.333c-5.845 0-11.349-1.152-16.299-3.2-5.205-2.133-9.899-5.333-13.867-9.301s-7.125-8.661-9.301-13.867c-2.048-4.949-3.2-10.453-3.2-16.299v-426.667c0-5.845 1.152-11.349 3.2-16.299 2.133-5.205 5.333-9.899 9.301-13.867s8.661-7.125 13.867-9.301c4.949-2.048 10.453-3.2 16.299-3.2h682.667c5.845 0 11.349 1.152 16.299 3.2 5.205 2.133 9.899 5.333 13.867 9.301s7.125 8.661 9.301 13.867c2.048 4.949 3.2 10.453 3.2 16.299v426.667c0 5.845-1.152 11.349-3.2 16.299-2.133 5.205-5.333 9.899-9.301 13.867s-8.661 7.125-13.867 9.301c-4.949 2.048-10.453 3.2-16.299 3.2zM469.333 768v85.333h-128c-23.552 0-42.667 19.115-42.667 42.667s19.115 42.667 42.667 42.667h341.333c23.552 0 42.667-19.115 42.667-42.667s-19.115-42.667-42.667-42.667h-128v-85.333h298.667c17.28 0 33.835-3.456 48.981-9.728 15.701-6.485 29.781-16 41.557-27.776s21.291-25.856 27.776-41.557c6.229-15.104 9.685-31.659 9.685-48.939v-426.667c0-17.28-3.456-33.835-9.728-48.981-6.485-15.701-16-29.781-27.776-41.557s-25.856-21.291-41.557-27.776c-15.104-6.229-31.659-9.685-48.939-9.685h-682.667c-17.28 0-33.835 3.456-48.981 9.728-15.659 6.485-29.739 16-41.515 27.776s-21.291 25.856-27.776 41.515c-6.272 15.147-9.728 31.701-9.728 48.981v426.667c0 17.28 3.456 33.835 9.728 48.981 6.485 15.701 16 29.781 27.776 41.557s25.856 21.291 41.557 27.776c15.104 6.229 31.659 9.685 48.939 9.685z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["monitor"],"grid":0},"attrs":[{}],"properties":{"order":132,"id":0,"prevSize":24,"code":59765,"name":"type-UI"},"setIdx":0,"setId":1,"iconIdx":60},{"icon":{"paths":["M66.337 575.491l276.668-171.531v-57.177l-331.627 207.614v42.189l331.627 207.614-0-57.177z","M957.663 575.49l-276.668-171.531v-57.177l331.627 207.614v42.189l-331.627 207.614 0-57.177z","M583.295 214.183l-200.825 621.623 53.007 17.527 200.837-621.623z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["prerender"],"grid":0},"attrs":[{},{},{}],"properties":{"order":114,"id":0,"name":"prerender","prevSize":24,"code":59724},"setIdx":0,"setId":1,"iconIdx":61},{"icon":{"paths":["M1024 512c0 282.77-229.23 512-512 512s-512-229.23-512-512c0-282.77 229.23-512 512-512s512 229.23 512 512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["circle"],"grid":0},"attrs":[{}],"properties":{"order":106,"id":1,"name":"circle","prevSize":24,"code":59729},"setIdx":0,"setId":1,"iconIdx":62},{"icon":{"paths":["M512 0c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h128v870.4h-128c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h307.2c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-128v-870.4h128c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.16 0-51.2 23.040-51.2 51.2v460.8c0 28.16 23.040 51.2 51.2 51.2h537.6v-51.2h-512c-15.36 0-25.6-10.24-25.6-25.6v-409.6c0-15.36 10.24-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c15.36 0 25.6 10.24 25.6 25.6v409.6c0 15.36-10.24 25.6-25.6 25.6h-204.8v51.2h230.4c28.16 0 51.2-23.040 51.2-51.2v-460.8c0-28.16-23.040-51.2-51.2-51.2h-230.4z","M386.56 606.72c0 12.8-7.68 23.040-20.48 25.6-28.16 10.24-58.88 15.36-92.16 15.36-35.84 0-66.56-10.24-84.48-25.6s-25.6-38.4-25.6-66.56 10.24-51.2 25.6-66.56c17.92-17.92 46.080-23.040 84.48-23.040h69.12v-38.4c0-35.84-25.6-53.76-64-53.76-23.040 0-46.080 7.68-69.12 20.48-2.56 2.56-5.12 2.56-10.24 2.56-10.24 0-20.48-7.68-20.48-20.48 0-7.68 2.56-12.8 10.24-17.92 30.72-20.48 61.44-25.6 92.16-25.6 56.32 0 104.96 30.72 104.96 92.16v181.76zM345.6 501.76h-69.12c-61.44 0-69.12 28.16-69.12 53.76s7.68 56.32 69.12 56.32c23.040 0 46.080-2.56 69.12-10.24v-99.84z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Slug"],"grid":0},"attrs":[{},{}],"properties":{"order":103,"id":2,"name":"control-Slug","prevSize":24,"code":59727},"setIdx":0,"setId":1,"iconIdx":63},{"icon":{"paths":["M295.954 822.751h-94.705c-47.353 0-88.786-41.434-88.786-88.786v-491.283c0-47.353 41.434-88.786 88.786-88.786h94.705v-59.191h-94.705c-82.867 0-147.977 65.11-147.977 147.977v491.283c0 82.867 65.11 147.977 147.977 147.977h94.705v-59.191z","M970.728 473.526c-82.867-171.653-201.249-378.821-272.277-378.821h-112.462v59.191h112.462c35.514 11.838 136.139 177.572 213.087 337.387-76.948 153.896-177.572 325.549-213.087 337.387h-112.462v59.191h112.462c71.029 0 183.491-207.168 272.277-384.74l5.919-11.838-5.919-17.757z","M266.358 337.341v260.462h59.191v-260.462z","M479.422 337.341v260.462h59.191v-260.462z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["Tags"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":98,"id":3,"name":"type-Tags","prevSize":24,"code":59722},"setIdx":0,"setId":1,"iconIdx":64},{"icon":{"paths":["M512 102.4c-200.4 0-366.954 144.072-402.4 334.2-0.031 0.165-0.069 0.335-0.1 0.5-2.974 16.061-4.76 32.441-5.8 49.1-0.017 0.271-0.084 0.529-0.1 0.8 0.019 0.004 0.080-0.004 0.1 0-0.503 8.31-1.3 16.564-1.3 25 0 226.202 183.398 409.6 409.6 409.6 208.165 0 379.707-155.44 405.8-356.5 0.004-0.033-0.004-0.067 0-0.1 1.94-14.978 3.124-30.16 3.4-45.6 0.044-2.487 0.4-4.903 0.4-7.4 0-226.202-183.398-409.6-409.6-409.6zM512 153.6c185.461 0 337.902 140.924 356.4 321.5-35.181-21.812-84.232-39.9-151.6-39.9-85.35 0-140.891 41.606-194.6 81.9-49.152 36.864-95.55 71.7-163.8 71.7-86.067 0-135.862-54.67-175.9-98.6-9.001-9.901-17.11-17.483-25.4-25.3 23.131-175.603 172.981-311.3 354.9-311.3zM716.8 486.4c77.828 0 125.173 28.221 152.2 52.8-13.96 185.173-168.254 331.2-357 331.2-190.097 0-345.175-148.14-357.2-335.2 41.826 45.372 102.577 104.8 203.6 104.8 85.35 0 140.891-41.606 194.6-81.9 49.152-36.915 95.55-71.7 163.8-71.7z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["activity"],"grid":0},"attrs":[{}],"properties":{"order":12,"id":4,"name":"activity, history, time","prevSize":24,"code":59652},"setIdx":0,"setId":1,"iconIdx":65},{"icon":{"paths":["M512 0c-35.392 0-64 28.608-64 64v384h-384c-35.392 0-64 28.608-64 64s28.608 64 64 64h384v384c0 35.392 28.608 64 64 64s64-28.608 64-64v-384h384c35.392 0 64-28.608 64-64s-28.608-64-64-64h-384v-384c0-35.392-28.608-64-64-64z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["add"],"grid":0},"attrs":[{}],"properties":{"order":13,"id":5,"name":"add, plus","prevSize":24,"code":59653},"setIdx":0,"setId":1,"iconIdx":66},{"icon":{"paths":["M512 102.4c-226.202 0-409.6 183.398-409.6 409.6s183.398 409.6 409.6 409.6c226.202 0 409.6-183.398 409.6-409.6s-183.398-409.6-409.6-409.6zM512 153.6c197.632 0 358.4 160.819 358.4 358.4s-160.768 358.4-358.4 358.4c-197.632 0-358.4-160.819-358.4-358.4s160.768-358.4 358.4-358.4zM691.9 333c-12.893 0.002-25.782 4.882-35.5 14.6l-222.2 221.9-67.7-67.5c-19.19-19.294-51.085-19.215-70.3 0-19.15 19.15-19.15 51.050 0 70.2 0.198 0.2 26.198 26.681 52 53 12.95 13.209 25.761 26.372 35.2 36 4.719 4.814 8.607 8.755 11.2 11.4 1.296 1.322 2.293 2.281 2.9 2.9 0.279 0.282 0.488 0.486 0.6 0.6 0.001 0.001 7.591-7.429 14.6-14.3l-14.5 14.4 0.2 0.2v0.1c19.43 19.327 51.57 19.327 71 0v-0.1l258.1-257.6c19.546-19.447 19.521-51.885-0.1-71.3-9.731-9.679-22.607-14.502-35.5-14.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle"],"grid":0},"attrs":[{}],"properties":{"order":14,"id":6,"name":"check-circle","prevSize":24,"code":59654},"setIdx":0,"setId":1,"iconIdx":67},{"icon":{"paths":["M512 1024c-282.778 0-512-229.222-512-512s229.222-512 512-512 512 229.222 512 512-229.222 512-512 512zM855.808 270.592c-19.2-19.2-50.278-19.2-69.478 0l-376.73 376.73-171.878-171.93c-19.2-19.2-50.278-19.2-69.478 0s-19.2 50.278 0 69.478c0 0 201.523 205.261 204.8 208.486 9.984 10.138 23.347 14.643 36.557 14.080 13.21 0.563 26.573-3.942 36.608-14.029 3.277-3.226 409.6-413.286 409.6-413.286 19.2-19.2 19.2-50.33 0-69.53z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle-filled"],"grid":0},"attrs":[{}],"properties":{"order":27,"id":7,"name":"check-circle-filled","prevSize":24,"code":59655},"setIdx":0,"setId":1,"iconIdx":68},{"icon":{"paths":["M601.024 512l276.736 276.736c24.512 24.576 24.512 64.384 0 89.024-24.64 24.576-64.384 24.576-89.024 0l-276.736-276.736-276.736 276.736c-24.512 24.576-64.384 24.576-89.024 0-24.512-24.64-24.512-64.448 0-89.024l276.736-276.736-276.736-276.736c-24.512-24.576-24.512-64.384 0-89.024 24.64-24.576 64.512-24.576 89.024 0l276.736 276.736 276.736-276.736c24.64-24.576 64.384-24.576 89.024 0 24.512 24.64 24.512 64.448 0 89.024l-276.736 276.736z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["close"],"grid":0},"attrs":[{}],"properties":{"order":28,"id":8,"name":"close","prevSize":24,"code":59656},"setIdx":0,"setId":1,"iconIdx":69},{"icon":{"paths":["M409.6 435.2h-153.6v51.2h153.6v-51.2zM409.6 332.8h-153.6v51.2h153.6v-51.2zM256 691.2h409.6v-51.2h-409.6v51.2zM409.6 230.4h-153.6v51.2h153.6v-51.2zM870.4 179.2h-51.2v-51.2c0-28.262-22.938-51.2-51.2-51.2h-614.4c-28.262 0-51.2 22.938-51.2 51.2v665.6c0 28.262 22.938 51.2 51.2 51.2h51.2v51.2c0 28.262 22.938 51.2 51.2 51.2h614.4c28.262 0 51.2-22.938 51.2-51.2v-665.6c0-28.262-22.938-51.2-51.2-51.2zM179.2 793.6c-14.157 0-25.6-11.443-25.6-25.6v-614.4c0-14.131 11.443-25.6 25.6-25.6h563.2c14.157 0 25.6 11.469 25.6 25.6v614.4c0 14.157-11.443 25.6-25.6 25.6h-563.2zM870.4 870.4c0 14.157-11.443 25.6-25.6 25.6h-563.2c-14.157 0-25.6-11.443-25.6-25.6v-25.6h512c28.262 0 51.2-22.938 51.2-51.2v-563.2h25.6c14.157 0 25.6 11.469 25.6 25.6v614.4zM614.4 230.4h-102.4c-28.262 0-51.2 22.938-51.2 51.2v153.6c0 28.262 22.938 51.2 51.2 51.2h102.4c28.262 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.938-51.2-51.2-51.2zM614.4 435.2h-102.4v-153.6h102.4v153.6zM256 588.8h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":0},"attrs":[{}],"properties":{"order":37,"id":9,"name":"type-References","prevSize":24,"code":59657},"setIdx":0,"setId":1,"iconIdx":70},{"icon":{"paths":["M793.6 844.8c0 14.157-11.443 25.6-25.6 25.6h-665.6c-14.131 0-25.6-11.443-25.6-25.6v-665.6c0-14.157 11.469-25.6 25.6-25.6h665.6c14.157 0 25.6 11.443 25.6 25.6v102.4h51.2v-128c0-28.262-22.938-51.2-51.2-51.2h-716.8c-28.262 0-51.2 22.938-51.2 51.2v716.8c0 28.262 22.938 51.2 51.2 51.2h716.8c28.262 0 51.2-22.938 51.2-51.2v-281.6h-51.2v256zM991.078 237.747c-9.958-9.958-26.035-9.958-35.968 0l-391.91 391.91-238.31-238.31c-9.958-9.958-26.061-9.958-35.942 0-9.958 9.907-9.958 26.010 0 35.942l254.874 254.874c0.461 0.538 0.614 1.203 1.126 1.69 5.043 5.018 11.674 7.475 18.278 7.373 6.605 0.102 13.235-2.355 18.278-7.373 0.512-0.512 0.666-1.178 1.126-1.69l408.448-408.474c9.933-9.933 9.933-26.035 0-35.942z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-checkbox"],"grid":0},"attrs":[{}],"properties":{"order":38,"id":10,"name":"control-Checkbox","prevSize":24,"code":59658},"setIdx":0,"setId":1,"iconIdx":71},{"icon":{"paths":["M51.2 0c-28.262 0-51.2 22.938-51.2 51.2v281.6c0 28.262 22.938 51.2 51.2 51.2h921.6c28.262 0 51.2-22.938 51.2-51.2v-281.6c0-28.262-22.938-51.2-51.2-51.2h-921.6zM76.8 51.2h512v281.6h-512c-14.157 0-25.6-11.443-25.6-25.6v-230.4c0-14.157 11.443-25.6 25.6-25.6zM640 51.2h307.2c14.157 0 25.6 11.443 25.6 25.6v230.4c0 14.157-11.443 25.6-25.6 25.6h-307.2v-281.6zM716.8 153.6c-0.41 0.358 89.139 102.938 89.6 102.4 0.512 0 89.6-95.36 89.6-102.4 0 0.384-172.16 0-179.2 0zM128 435.2c-42.394 0-76.8 34.406-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.406 76.8-76.8s-34.406-76.8-76.8-76.8zM128 486.4c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 486.4c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 640c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 691.2c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 691.2c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 844.8c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 896c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 896c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-dropdown"],"grid":0},"attrs":[{}],"properties":{"order":39,"id":11,"name":"control-Dropdown","prevSize":24,"code":59659},"setIdx":0,"setId":1,"iconIdx":72},{"icon":{"paths":["M512 0c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h128v870.4h-128c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h307.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-128v-870.4h128c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.262 0-51.2 22.938-51.2 51.2v460.8c0 28.262 22.938 51.2 51.2 51.2h537.6v-51.2h-512c-14.131 0-25.6-11.443-25.6-25.6v-409.6c0-14.157 11.469-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c14.157 0 25.6 11.443 25.6 25.6v409.6c0 14.157-11.443 25.6-25.6 25.6h-204.8v51.2h230.4c28.262 0 51.2-22.938 51.2-51.2v-460.8c0-28.262-22.938-51.2-51.2-51.2h-230.4zM285.9 307c-0.589 0.051-1.161 0.048-1.75 0.15-8.243 0.051-16.396 4.474-20.85 13.050l-132.55 306.25c-6.656 12.749-2.866 28.981 8.5 36.2 11.341 7.219 25.97 2.749 32.6-10l27.65-63.85h170.5c0.512 0 0.914-0.224 1.4-0.25l27.45 64.050c6.63 12.749 21.136 17.269 32.4 10.050s15.005-23.451 8.4-36.2l-131.3-306.25c-4.454-8.576-12.432-12.973-20.65-13.050-0.614-0.102-1.211-0.099-1.8-0.15zM285.9 389.15l63.65 148.45h-127.9l64.25-148.45z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-input"],"grid":0},"attrs":[{}],"properties":{"order":41,"id":12,"name":"control-Input","prevSize":24,"code":59660},"setIdx":0,"setId":1,"iconIdx":73},{"icon":{"paths":["M153.6 716.8c-84.787 0-153.6 68.813-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.813 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 972.8c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM153.6 0c-84.787 0-153.6 68.787-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.787 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 256c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 358.4c-84.787 0-153.6 68.787-153.6 153.6 0 84.787 68.813 153.6 153.6 153.6s153.6-68.813 153.6-153.6c0-84.813-68.813-153.6-153.6-153.6zM153.6 614.4c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 102.4c-28.262 0-51.2 22.938-51.2 51.2s22.938 51.2 51.2 51.2c28.262 0 51.2-22.938 51.2-51.2s-22.938-51.2-51.2-51.2zM998.4 844.8h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-radio"],"grid":0},"attrs":[{}],"properties":{"order":42,"id":13,"name":"control-Radio","prevSize":24,"code":59661},"setIdx":0,"setId":1,"iconIdx":74},{"icon":{"paths":["M0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8h-204.8zM819.2 0v204.8h204.8v-204.8h-204.8zM51.2 51.2h102.4v102.4h-102.4v-102.4zM870.4 51.2h102.4v102.4h-102.4v-102.4zM281.6 76.8v51.2h102.4v-51.2h-102.4zM486.4 76.8v51.2h102.4v-51.2h-102.4zM691.2 76.8v51.2h102.4v-51.2h-102.4zM333.25 204.8c-7.091-0.307-14.348 2.097-19.75 7.55l-74.75 74.75c-10.317 10.291-10.317 27.083 0 37.4s27.059 10.317 37.35 0l68.45-68.5h141.85v486.4h-50.7c-7.117-0.307-14.348 2.097-19.75 7.55l-23.6 23.55c-10.317 10.317-10.317 27.083 0 37.4 10.291 10.317 27.109 10.317 37.4 0l17.25-17.3h129.75l18.050 18c10.394 10.368 27.181 10.368 37.6 0 10.368-10.394 10.368-27.181 0-37.6l-24-24c-5.478-5.478-12.682-7.907-19.85-7.6h-50.95v-486.4h141.55l69.25 69.2c10.394 10.368 27.155 10.368 37.6 0 10.368-10.368 10.368-27.181 0-37.6l-75.2-75.2c-5.478-5.478-12.706-7.907-19.9-7.6h-357.65zM896 281.6v102.4h51.2v-102.4h-51.2zM76.8 384v102.4h51.2v-102.4h-51.2zM896 486.4v102.4h51.2v-102.4h-51.2zM76.8 588.8v102.4h51.2v-102.4h-51.2zM896 691.2v102.4h51.2v-102.4h-51.2zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6h-51.2zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8h-204.8zM51.2 870.4h102.4v102.4h-102.4v-102.4zM870.4 870.4h102.4v102.4h-102.4v-102.4zM384 896v51.2h102.4v-51.2h-102.4zM588.8 896v51.2h102.4v-51.2h-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-textarea"],"grid":0},"attrs":[{}],"properties":{"order":17,"id":14,"name":"control-TextArea","prevSize":24,"code":59662},"setIdx":0,"setId":1,"iconIdx":75},{"icon":{"paths":["M332.8 25.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 76.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM332.8 128c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM332.8 179.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8zM332.8 537.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 588.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM691.2 640c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM691.2 691.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-toggle"],"grid":0},"attrs":[{}],"properties":{"order":16,"id":15,"name":"control-Toggle","prevSize":24,"code":59663},"setIdx":0,"setId":1,"iconIdx":76},{"icon":{"paths":["M204.8 51.2c-56.525 0-102.4 45.875-102.4 102.4v512c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4h-409.6zM204.8 102.4h409.6c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2v-512c0-28.314 22.938-51.2 51.2-51.2zM768 204.8v51.2c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2h-51.2c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["copy"],"grid":0},"attrs":[{}],"properties":{"order":90,"id":16,"name":"copy","prevSize":24,"code":59664},"setIdx":0,"setId":1,"iconIdx":77},{"icon":{"paths":["M828.8 1024h-633.6c-105.6 0-195.2-89.6-195.2-195.2v-320c0-281.6 227.2-508.8 505.6-508.8 288 0 518.4 230.4 518.4 518.4v310.4c0 105.6-89.6 195.2-195.2 195.2zM505.6 64c-243.2 0-441.6 198.4-441.6 441.6v320c0 73.6 60.8 134.4 131.2 134.4h630.4c73.6 0 131.2-60.8 131.2-131.2v-310.4c3.2-249.6-201.6-454.4-451.2-454.4z","M512 668.8c-3.2 0-6.4 0-6.4 0-32-3.2-64-19.2-80-48l-192-278.4c-9.6-9.6-9.6-25.6-0-38.4 9.6-9.6 25.6-12.8 38.4-6.4l294.4 172.8c28.8 16 48 44.8 51.2 76.8s-6.4 64-28.8 89.6c-19.2 22.4-48 32-76.8 32zM364.8 428.8l108.8 160c6.4 9.6 19.2 19.2 32 19.2s25.6-3.2 35.2-12.8c9.6-9.6 12.8-22.4 9.6-35.2s-9.6-22.4-19.2-32l-166.4-99.2z","M678.4 364.8c-6.4 0-12.8-3.2-19.2-6.4-16-9.6-19.2-28.8-9.6-44.8l54.4-83.2c9.6-16 28.8-19.2 44.8-9.6 19.2 12.8 22.4 35.2 12.8 48l-54.4 83.2c-6.4 9.6-16 12.8-28.8 12.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["dashboard"],"grid":0},"attrs":[{},{},{}],"properties":{"order":26,"id":17,"name":"dashboard, search-Dashboard","prevSize":24,"code":59665},"setIdx":0,"setId":1,"iconIdx":78},{"icon":{"paths":["M597.35 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.418 25.6 25.6 25.6zM776.55 204.8h-153.6v-51.2c0-28.314-22.886-51.2-51.2-51.2h-102.4c-28.262 0-51.2 22.886-51.2 51.2v51.2h-153.6c-28.262 0-51.2 22.886-51.2 51.2v102.4c0 28.314 22.938 51.2 51.2 51.2v460.8c0 28.314 22.938 51.2 51.2 51.2h409.6c28.314 0 51.2-22.886 51.2-51.2v-460.8c28.314 0 51.2-22.886 51.2-51.2v-102.4c0-28.314-22.938-51.2-51.2-51.2zM469.35 153.6h102.4v51.2h-102.4v-51.2zM725.35 870.4h-409.6v-460.8h409.6v460.8zM776.55 358.4h-512v-102.4h512v102.4zM443.75 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete"],"grid":0},"attrs":[{}],"properties":{"order":29,"id":18,"name":"delete, bin","prevSize":24,"code":59666},"setIdx":0,"setId":1,"iconIdx":79},{"icon":{"paths":["M832 128h-192v-64c0-35.392-28.608-64-64-64h-128c-35.328 0-64 28.608-64 64v64h-192c-35.328 0-64 28.608-64 64v128c0 35.392 28.672 64 64 64v512c0 35.392 28.672 64 64 64h512c35.392 0 64-28.608 64-64v-512c35.392 0 64-28.608 64-64v-128c0-35.392-28.608-64-64-64zM448 64h128v64h-128v-64zM448 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM640 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM832 320h-640v-128h640v128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete-filled"],"grid":0},"attrs":[{}],"properties":{"order":36,"id":19,"name":"delete-filled","prevSize":24,"code":59667},"setIdx":0,"setId":1,"iconIdx":80},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c98.816 0 179.2 80.384 179.2 179.2s-80.384 179.2-179.2 179.2c-98.816 0-179.2-80.384-179.2-179.2s80.384-179.2 179.2-179.2zM227.2 665.6c-12.39 0-22.4 10.061-22.4 22.4v6.4c0 12.39 10.010 22.4 22.4 22.4h211.2c12.39 0 22.4-10.010 22.4-22.4v-6.4c0-12.39-10.061-22.4-22.4-22.4h-211.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-delete"],"grid":0},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":24,"code":59668},"setIdx":0,"setId":1,"iconIdx":81},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c39.934 0 76.475 13.533 106.3 35.7l-250.4 249c-21.807-29.683-35.1-65.924-35.1-105.5 0-98.816 80.384-179.2 179.2-179.2zM477 585.7c21.785 29.674 35 65.947 35 105.5 0 98.816-80.384 179.2-179.2 179.2-39.906 0-76.386-13.561-106.2-35.7l250.4-249z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-disable"],"grid":0},"attrs":[{}],"properties":{"order":40,"id":21,"name":"document-disable","prevSize":24,"code":59669},"setIdx":0,"setId":1,"iconIdx":82},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2l-230.4-256zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7l161.5-179.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-publish"],"grid":0},"attrs":[{}],"properties":{"order":44,"id":22,"name":"document-publish","prevSize":24,"code":59670},"setIdx":0,"setId":1,"iconIdx":83},{"icon":{"paths":["M665.6 51.2v102.4h102.4v-102.4h-102.4zM460.8 153.6h102.4v-102.4h-102.4v102.4zM460.8 358.4h102.4v-102.4h-102.4v102.4zM665.6 358.4h102.4v-102.4h-102.4v102.4zM665.6 563.2h102.4v-102.4h-102.4v102.4zM460.8 563.2h102.4v-102.4h-102.4v102.4zM460.8 768h102.4v-102.4h-102.4v102.4zM665.6 768h102.4v-102.4h-102.4v102.4zM665.6 972.8h102.4v-102.4h-102.4v102.4zM460.8 972.8h102.4v-102.4h-102.4v102.4zM256 153.6h102.4v-102.4h-102.4v102.4zM256 358.4h102.4v-102.4h-102.4v102.4zM256 563.2h102.4v-102.4h-102.4v102.4zM256 768h102.4v-102.4h-102.4v102.4zM256 972.8h102.4v-102.4h-102.4v102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag"],"grid":0},"attrs":[{}],"properties":{"order":43,"id":23,"name":"drag","prevSize":24,"code":59671},"setIdx":0,"setId":1,"iconIdx":84},{"icon":{"paths":["M921.6 281.958c0-70.707-171.878-128.154-384-128.154s-384 57.19-384 127.898c0 10.035 3.789 19.712 10.342 29.030 0-0.051 296.858 406.067 296.858 406.067v256l153.6-51.2v-204.8c0 0 298.752-408.166 299.725-409.702 0 0 7.475-16.64 7.475-25.139zM537.6 204.8c206.899 0 318.208 53.248 332.083 76.8-13.875 23.552-125.184 76.8-332.083 76.8s-318.208-53.248-332.083-76.8c13.875-23.552 125.184-76.8 332.083-76.8zM869.376 345.856v0 0zM573.030 686.592c-6.4 8.755-9.83 19.354-9.83 30.208v167.885l-51.2 17.050v-184.934c0-10.854-3.43-21.453-9.83-30.208l-228.147-312.115c68.762 21.709 161.382 35.123 263.578 35.123 102.298 0 195.021-13.414 263.834-35.174-0.102 0.051-0.205 0.051-0.307 0.102l-228.096 312.064z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["filter"],"grid":0},"attrs":[{}],"properties":{"order":18,"id":24,"name":"filter","prevSize":24,"code":59672},"setIdx":0,"setId":1,"iconIdx":85},{"icon":{"paths":["M512 0c-282.88 0-512 229.248-512 512 0 226.24 146.688 418.112 350.080 485.76 25.6 4.8 35.008-11.008 35.008-24.64 0-12.16-0.448-44.352-0.64-87.040-142.464 30.912-172.48-68.672-172.48-68.672-23.296-59.136-56.96-74.88-56.96-74.88-46.4-31.744 3.584-31.104 3.584-31.104 51.392 3.584 78.4 52.736 78.4 52.736 45.696 78.272 119.872 55.68 149.12 42.56 4.608-33.088 17.792-55.68 32.448-68.48-113.728-12.8-233.216-56.832-233.216-252.992 0-55.872 19.84-101.568 52.672-137.408-5.76-12.928-23.040-64.96 4.48-135.488 0 0 42.88-13.76 140.8 52.48 40.96-11.392 84.48-17.024 128-17.28 43.52 0.256 87.040 5.888 128 17.28 97.28-66.24 140.16-52.48 140.16-52.48 27.52 70.528 10.24 122.56 5.12 135.488 32.64 35.84 52.48 81.536 52.48 137.408 0 196.672-119.68 240-233.6 252.608 17.92 15.36 34.56 46.72 34.56 94.72 0 68.48-0.64 123.52-0.64 140.16 0 13.44 8.96 29.44 35.2 24.32 204.864-67.136 351.424-259.136 351.424-485.056 0-282.752-229.248-512-512-512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["brand","github"],"grid":0},"attrs":[{}],"properties":{"order":77,"id":25,"name":"github","prevSize":24,"code":59713},"setIdx":0,"setId":1,"iconIdx":86},{"icon":{"paths":["M512 512h-204.8v51.2h204.8v-51.2zM768 153.6h-51.2c0-28.314-22.886-51.2-51.2-51.2h-307.2c-28.314 0-51.2 22.886-51.2 51.2h-51.2c-28.314 0-51.2 22.886-51.2 51.2v665.6c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-665.6c0-28.314-22.886-51.2-51.2-51.2zM358.4 153.6h307.2v51.2h-307.2v-51.2zM768 819.2c0 28.314-22.886 51.2-51.2 51.2h-409.6c-28.314 0-51.2-22.886-51.2-51.2v-563.2c0-28.314 22.886-51.2 51.2-51.2 0 28.314 22.886 51.2 51.2 51.2h307.2c28.314 0 51.2-22.886 51.2-51.2 28.314 0 51.2 22.886 51.2 51.2v563.2zM307.2 460.8h409.6v-51.2h-409.6v51.2zM307.2 665.6h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["help"],"grid":0},"attrs":[{}],"properties":{"order":19,"id":26,"name":"help","prevSize":24,"code":59673},"setIdx":0,"setId":1,"iconIdx":87},{"icon":{"paths":["M512 0c-169.421 0-307.2 137.779-307.2 307.2 0 78.643 15.258 164.915 45.261 256.41 23.859 72.55 56.986 148.582 98.56 226.099 70.707 131.635 140.339 220.774 143.309 224.512 4.813 6.195 12.288 9.779 20.070 9.779 7.834 0 15.258-3.584 20.122-9.779 2.97-3.686 72.602-92.826 143.309-224.512 41.574-77.517 74.701-153.549 98.56-226.099 29.952-91.494 45.21-177.766 45.21-256.41 0-169.421-137.83-307.2-307.2-307.2zM630.682 764.672c-46.234 86.374-92.979 154.982-118.682 190.822-25.6-35.635-72.038-103.885-118.221-189.952-62.874-117.146-137.779-291.738-137.779-458.342 0-141.158 114.842-256 256-256s256 114.842 256 256c0 166.298-74.65 340.582-137.318 457.472zM512 153.6c-84.685 0-153.6 68.915-153.6 153.6s68.915 153.6 153.6 153.6 153.6-68.915 153.6-153.6-68.915-153.6-153.6-153.6zM512 409.6c-56.525 0-102.4-45.875-102.4-102.4 0-56.474 45.875-102.4 102.4-102.4 56.474 0 102.4 45.926 102.4 102.4 0 56.525-45.926 102.4-102.4 102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["location"],"grid":0},"attrs":[{}],"properties":{"order":25,"id":27,"name":"location, control-Map, type-Geolocation","prevSize":24,"code":59675},"setIdx":0,"setId":1,"iconIdx":88},{"icon":{"paths":["M512.273 83.782c-0.141 0.056-182.959 84.073-229.418 256.782-4.481 16.584 32.696 9.296 31.036 27.527-2.034 22.136-44.668 31.201-39.109 94.764 5.659 64.734 60.321 130.141 68.527 169.673v27.655c-0.497 8.54-4.566 31.715-18.018 43.036-7.378 6.19-17.322 8.421-30.436 6.782-18.205-2.275-25.449-14.468-28.345-24.309-4.753-16.218-0.322-35.123 10.345-44 10.724-8.924 12.17-24.842 3.236-35.564-8.934-10.712-24.858-12.161-35.582-3.218-25.995 21.64-36.887 61.52-26.491 97 9.815 33.392 36.197 55.884 70.6 60.182 4.903 0.609 9.566 0.909 14 0.909 26.623 0 44.661-10.175 55.582-19.455 32.866-27.97 35.449-74.593 35.636-79.818 0.009-0.309 0.018-0.618 0.018-0.927v-21.218h0.109v-1.418c0-12.351 10.008-22.364 22.382-22.364 11.944 0 21.609 9.346 22.273 21.109v202.491c-0.206 2.912-2.536 29.892-17.891 42.945-7.368 6.274-17.384 8.53-30.545 6.873-18.214-2.275-25.476-14.468-28.364-24.291-4.762-16.228-0.322-35.151 10.345-44.018 10.724-8.933 12.188-24.833 3.255-35.564-8.924-10.694-24.876-12.161-35.6-3.218-26.013 21.631-36.887 61.52-26.491 97 9.796 33.392 36.197 55.893 70.6 60.2 4.903 0.609 9.566 0.891 14 0.891 26.623 0 44.671-10.156 55.564-19.436 32.875-27.97 35.458-74.611 35.636-79.836 0.019-0.328 0.018-0.609 0.018-0.909v-225.636l0.127-0.055v-1c0-12.595 10.219-22.8 22.836-22.8 12.349 0 22.333 9.824 22.727 22.073v227.418c0 0.309-0 0.591 0.018 0.909 0.187 5.216 2.779 51.866 35.655 79.836 10.912 9.28 28.959 19.436 55.582 19.436 4.443 0 9.088-0.282 13.982-0.891 34.394-4.307 60.804-26.818 70.6-60.2 10.405-35.48-0.487-75.36-26.491-97-10.743-8.943-26.676-7.466-35.6 3.218-8.934 10.74-7.488 26.63 3.236 35.564 10.668 8.868 15.135 27.79 10.364 44.018-2.878 9.823-10.159 22.015-28.364 24.291-13.105 1.648-23.050-0.592-30.418-6.782-13.508-11.358-17.558-34.657-18.036-43v-201.818c0.297-12.093 10.14-21.818 22.327-21.818 12.374 0 22.4 10.003 22.4 22.364v1.418h0.073v21.218c0 0.318-0 0.628 0.018 0.927 0.178 5.216 2.779 51.848 35.655 79.818 10.912 9.28 28.941 19.455 55.564 19.455 4.434 0 9.107-0.292 14-0.891 34.394-4.298 60.786-26.818 70.582-60.2 10.405-35.48-0.487-75.351-26.491-97-10.743-8.933-26.667-7.476-35.582 3.236-8.943 10.722-7.488 26.622 3.236 35.545 10.668 8.877 15.117 27.8 10.345 44.018-2.878 9.842-10.159 22.025-28.364 24.291-13.086 1.648-23.050-0.583-30.418-6.764-13.508-11.368-17.549-34.675-18.018-43v-21.018c5.305-54.103 63.095-107.777 69.091-176.364 5.531-63.563-37.121-72.627-39.145-94.764-1.669-18.232 35.498-10.944 31.036-27.527-46.468-172.709-229.269-256.726-229.4-256.782z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["logo"],"grid":0},"attrs":[{}],"properties":{"order":31,"id":28,"name":"logo","prevSize":24,"code":59676},"setIdx":0,"setId":1,"iconIdx":89},{"icon":{"paths":["M947.2 0h-870.4c-42.342 0-76.8 34.458-76.8 76.8v870.4c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-870.4c0-42.342-34.458-76.8-76.8-76.8zM972.8 947.2c0 14.157-11.443 25.6-25.6 25.6h-870.4c-14.131 0-25.6-11.443-25.6-25.6v-870.4c0-14.131 11.469-25.6 25.6-25.6h870.4c14.157 0 25.6 11.469 25.6 25.6v870.4zM665.6 460.8c56.448 0 102.4-45.926 102.4-102.4s-45.952-102.4-102.4-102.4c-56.448 0-102.4 45.926-102.4 102.4s45.952 102.4 102.4 102.4zM665.6 307.2c28.211 0 51.2 22.989 51.2 51.2s-22.989 51.2-51.2 51.2c-28.211 0-51.2-22.989-51.2-51.2s22.989-51.2 51.2-51.2zM896 102.4h-768c-14.131 0-25.6 11.469-25.6 25.6v614.4c0 14.157 11.469 25.6 25.6 25.6h768c14.157 0 25.6-11.443 25.6-25.6v-614.4c0-14.131-11.443-25.6-25.6-25.6zM153.6 716.8v-118.246l164.301-184.858c4.198-4.787 9.728-7.373 15.462-7.475 5.734-0.051 11.29 2.458 15.642 7.040l283.238 303.539h-478.643zM870.4 716.8h-168.090l-315.853-338.432c-14.285-15.334-33.331-23.603-53.709-23.347-20.326 0.256-39.219 9.011-53.094 24.627l-126.054 141.798v-367.846h716.8v563.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["media"],"grid":0},"attrs":[{}],"properties":{"order":30,"id":29,"name":"media, type-Assets, trigger-AssetChanged","prevSize":24,"code":59677},"setIdx":0,"setId":1,"iconIdx":90},{"icon":{"paths":["M128 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM512 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM896 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["more"],"grid":0},"attrs":[{}],"properties":{"order":34,"id":30,"name":"more, dots","prevSize":24,"code":59678},"setIdx":0,"setId":1,"iconIdx":91},{"icon":{"paths":["M877.12 311.104l-66.304 66.368-228.224-228.224 66.368-66.368c25.216-25.152 66.048-25.152 91.264 0l136.896 137.024c25.216 25.216 25.216 65.984 0 91.2zM760.896 427.392l-386.176 386.112c-25.216 25.28-66.048 25.28-91.264 0l-136.96-136.896c-25.216-25.28-25.216-66.112 0-91.264l386.24-386.24 228.16 228.288zM64 896v-191.872l191.936 191.872h-191.936z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pencil"],"grid":0},"attrs":[{}],"properties":{"order":47,"id":31,"name":"pencil","prevSize":24,"code":59679},"setIdx":0,"setId":1,"iconIdx":92},{"icon":{"paths":["M892.083 131.917c-73.523-73.498-193.152-73.498-266.65 0l-157.184 157.107c-9.958 10.035-9.958 26.214 0 36.275 10.061 9.984 26.24 9.984 36.25 0l157.133-157.107c53.504-53.555 140.672-53.555 194.176 0 53.581 53.504 53.581 140.672 0 194.176l-186.138 186.163c-53.53 53.581-140.672 53.581-194.176 0-10.086-10.010-26.24-10.010-36.275 0-10.035 10.086-10.035 26.189 0 36.25 36.787 36.736 84.992 55.117 133.325 55.117s96.589-18.432 133.376-55.117l186.163-186.214c73.498-73.472 73.498-193.152 0-266.65zM519.45 698.726l-157.082 157.082c-53.504 53.555-140.672 53.555-194.176 0-53.581-53.504-53.581-140.672 0-194.176l186.138-186.163c53.53-53.581 140.672-53.581 194.176 0 10.086 9.984 26.189 9.984 36.275 0 10.035-10.086 10.035-26.214 0-36.25-73.549-73.498-193.203-73.498-266.701 0l-186.163 186.163c-73.498 73.574-73.498 193.203 0 266.701 36.787 36.71 85.043 55.117 133.325 55.117 48.333 0 96.538-18.406 133.325-55.117l157.133-157.133c10.010-10.010 10.010-26.189 0-36.224-10.010-9.984-26.189-9.984-36.25 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["reference"],"grid":0},"attrs":[{}],"properties":{"order":45,"id":32,"name":"reference","prevSize":24,"code":59680},"setIdx":0,"setId":1,"iconIdx":93},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-300.8c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v300.8c0 124.8-99.2 224-224 224zM224 339.2c-89.6 0-160 70.4-160 160v300.8c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-300.8c0-89.6-70.4-160-160-160h-576z","M828.8 201.6h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M716.8 64h-409.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h412.8c19.2 0 32 12.8 32 32s-16 32-35.2 32z","M800 416v64c0 48-38.4 83.2-83.2 83.2h-409.6c-44.8 3.2-83.2-35.2-83.2-83.2v-64h-54.4v64c0 76.8 64 140.8 140.8 140.8h406.4c76.8 0 140.8-64 140.8-140.8v-64h-57.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["schemas"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":46,"id":33,"name":"schemas, search-Schema","prevSize":24,"code":59681},"setIdx":0,"setId":1,"iconIdx":94},{"icon":{"paths":["M939.776 1003.776c-27.2 27.008-71.232 27.008-98.368 0l-168.96-168.96c-66.176 38.464-142.016 62.080-224 62.080-247.744 0-448.448-200.832-448.448-448.448 0-247.744 200.704-448.448 448.448-448.448 247.68 0 448.512 200.704 448.512 448.448 0 115.136-44.672 218.944-115.904 298.304l158.656 158.656c27.008 27.136 27.008 71.168 0.064 98.368zM448.448 128.128c-176.896 0-320.32 143.36-320.32 320.32s143.424 320.32 320.32 320.32c176.96 0 320.384-143.36 320.384-320.32s-143.488-320.32-320.384-320.32z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["search"],"grid":0},"attrs":[{}],"properties":{"order":23,"id":34,"name":"search","prevSize":24,"code":59682},"setIdx":0,"setId":1,"iconIdx":95},{"icon":{"paths":["M1019.11 440.755c-1.946-13.747-14.438-23.398-28.16-21.888-16.947 1.843-34.253-0.589-50.048-7.091-52.25-21.504-77.261-81.459-55.757-133.709 6.605-15.846 16.947-29.85 30.208-40.602 10.803-8.653 12.698-24.294 4.352-35.354-28.902-37.99-62.797-71.706-100.838-100.045-10.701-8.090-25.805-6.451-34.662 3.661-28.8 33.254-75.546 44.262-116.198 27.546-40.704-16.742-66.099-57.498-63.206-101.453 0.845-13.338-8.755-25.19-21.99-27.008-47.002-6.605-94.797-6.605-142.054 0.077-13.722 1.946-23.398 14.387-21.862 28.211 1.843 16.896-0.614 34.202-7.168 49.997-21.504 52.25-81.408 77.21-133.632 55.706-15.821-6.502-29.85-16.947-40.602-30.157-8.653-10.752-24.32-12.698-35.379-4.301-37.99 28.851-71.68 62.694-100.045 100.762-8.090 10.701-6.451 25.83 3.635 34.637 33.28 28.902 44.288 75.597 27.546 116.301-16.742 40.653-57.498 66.048-101.427 63.155-13.363-0.845-25.19 8.755-26.982 21.99-6.63 47.002-6.63 94.822 0.102 142.080 1.946 13.696 14.387 23.322 28.16 21.811 16.896-1.818 34.202 0.691 50.022 7.168 52.224 21.53 77.21 81.459 55.706 133.734-6.502 15.795-16.947 29.773-30.157 40.525-10.803 8.73-12.698 24.346-4.352 35.354 28.877 38.042 62.822 71.731 100.813 100.122 1.741 1.357 3.661 2.355 5.606 3.2 9.933 4.045 21.709 1.536 29.082-6.938 28.826-33.178 75.571-44.262 116.275-27.52 40.653 16.742 66.048 57.498 63.13 101.453-0.819 13.338 8.755 25.165 22.067 27.059 47.002 6.579 94.72 6.554 142.029-0.102 13.645-1.971 23.347-14.464 21.811-28.237-1.843-16.947 0.691-34.253 7.194-50.048 21.504-52.25 81.459-77.21 133.658-55.68 15.795 6.528 29.85 16.947 40.55 30.157 8.704 10.803 24.346 12.698 35.405 4.326 37.99-28.902 71.654-62.746 100.096-100.813 7.987-10.675 6.4-25.805-3.712-34.662-33.254-28.826-44.288-75.571-27.546-116.224 16.742-40.73 57.498-66.099 101.453-63.232 13.338 0.922 25.139-8.678 27.008-21.965 6.554-47.002 6.502-94.771-0.128-142.003zM971.059 554.010c-56.141 5.274-105.702 41.114-127.642 94.464s-12.058 113.613 24.090 156.902c-17.69 21.478-37.453 41.318-58.854 59.315-12.749-11.213-27.392-20.352-43.238-26.854-78.259-32.282-168.243 5.197-200.499 83.584-6.502 15.718-10.291 32.563-11.29 49.536-27.853 2.56-55.859 2.637-83.61 0.077-5.274-56.090-41.114-105.677-94.464-127.616-53.35-21.99-113.613-11.981-156.928 24.064-21.504-17.69-41.318-37.453-59.29-58.88 11.213-12.723 20.352-27.392 26.906-43.136 32.205-78.387-5.274-168.294-83.584-200.55-15.821-6.502-32.589-10.342-49.613-11.366-2.534-27.853-2.586-55.859 0-83.558 56.090-5.299 105.626-41.088 127.565-94.438 21.965-53.402 12.058-113.638-24.090-156.902 17.69-21.555 37.478-41.395 58.88-59.341 12.749 11.213 27.392 20.352 43.213 26.854 78.285 32.256 168.218-5.248 200.474-83.558 6.528-15.795 10.342-32.589 11.366-49.613 27.853-2.509 55.808-2.56 83.558 0 5.299 56.090 41.139 105.6 94.49 127.59 53.35 21.939 113.638 12.006 156.902-24.090 21.504 17.741 41.293 37.453 59.29 58.854-11.213 12.8-20.352 27.392-26.854 43.213-32.256 78.31 5.248 168.294 83.507 200.499 15.846 6.502 32.691 10.342 49.638 11.392 2.56 27.853 2.611 55.808 0.077 83.558zM512 307.2c-113.101 0-204.8 91.699-204.8 204.8 0 113.126 91.699 204.826 204.8 204.826s204.8-91.699 204.8-204.826c0-113.101-91.699-204.8-204.8-204.8zM512 665.626c-84.813 0-153.6-68.813-153.6-153.626 0-84.838 68.787-153.6 153.6-153.6 84.838 0 153.6 68.762 153.6 153.6 0 84.813-68.762 153.626-153.6 153.626z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings"],"grid":0},"attrs":[{}],"properties":{"order":22,"id":35,"name":"settings, search-Setting","prevSize":24,"code":59683},"setIdx":0,"setId":1,"iconIdx":96},{"icon":{"paths":["M77.005 102.605h128v332.8c0 14.131 11.418 25.6 25.6 25.6 14.106 0 25.6-11.469 25.6-25.6v-332.8h128c14.106 0 25.6-11.469 25.6-25.6 0-14.157-11.494-25.6-25.6-25.6h-307.2c-14.182 0-25.6 11.443-25.6 25.6 0 14.106 11.418 25.6 25.6 25.6zM947.405 716.979h-179.2v-102.4h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-204.8c-14.182 0-25.6 11.443-25.6 25.6v358.4c0 14.157 11.418 25.6 25.6 25.6 14.157 0 25.6-11.443 25.6-25.6v-179.2h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.494-25.6-25.6-25.6zM965.094 58.47c-9.958-9.933-26.112-9.933-36.045 0l-870.605 870.579c-9.958 9.984-9.958 26.086 0 36.045 10.010 9.984 26.112 9.984 36.045 0l870.605-870.579c9.958-9.933 9.958-26.086 0-36.045z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-boolean"],"grid":0},"attrs":[{}],"properties":{"order":21,"id":36,"name":"type-Boolean","prevSize":24,"code":59684},"setIdx":0,"setId":1,"iconIdx":97},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-datetime"],"grid":0},"attrs":[{}],"properties":{"order":24,"id":37,"name":"type-DateTime","prevSize":24,"code":59685},"setIdx":0,"setId":1,"iconIdx":98},{"icon":{"paths":["M179.2 256c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6h-25.6c-56.55 0-102.4 45.85-102.4 102.4v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 56.55 45.85 102.4 102.4 102.4h25.6c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-30.746-13.85-58.061-35.328-76.8 21.478-18.765 35.328-46.029 35.328-76.8v-179.2zM972.8 486.4h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-56.55-45.85-102.4-102.4-102.4h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 30.771 13.85 58.035 35.328 76.8-21.478 18.739-35.328 46.054-35.328 76.8v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h25.6c56.55 0 102.4-45.85 102.4-102.4v-179.2c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6zM512 332.8c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6c0-14.131-11.443-25.6-25.6-25.6zM512 435.2c-14.157 0-25.6 11.469-25.6 25.6v204.8c0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6v-204.8c0-14.131-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["json"],"grid":0},"attrs":[{}],"properties":{"order":20,"id":38,"name":"type-Json, json","prevSize":24,"code":59674},"setIdx":0,"setId":1,"iconIdx":99},{"icon":{"paths":["M256 665.6h-76.8v-332.8c0-14.131-11.469-25.6-25.6-25.6h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h51.2v307.2h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6zM614.4 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6v179.2c0 14.131 11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-179.2v-128h179.2c14.131 0 25.6-11.469 25.6-25.6v-179.2c0-14.131-11.469-25.6-25.6-25.6zM972.8 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6v-358.4c0-14.131-11.469-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-number"],"grid":0},"attrs":[{}],"properties":{"order":32,"id":39,"name":"type-Number","prevSize":24,"code":59686},"setIdx":0,"setId":1,"iconIdx":100},{"icon":{"paths":["M870.4 921.6h-716.8c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h716.8c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM194.688 817.152c13.030 5.555 28.083-0.461 33.613-13.44l125.030-291.712h317.338l125.005 291.712c4.173 9.677 13.568 15.488 23.526 15.488 3.405 0 6.81-0.64 10.112-2.048 13.005-5.606 18.995-20.659 13.44-33.638l-131.61-306.944c-0.051-0.051-0.051-0.154-0.102-0.205l-175.488-409.6c-4.045-9.472-13.312-15.565-23.552-15.565s-19.507 6.093-23.552 15.514l-175.488 409.6c-0.051 0.051-0.051 0.154-0.102 0.205l-131.61 306.97c-5.53 13.005 0.461 28.058 13.44 33.664zM512 141.773l136.704 319.027h-273.408l136.704-319.027z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-string"],"grid":0},"attrs":[{}],"properties":{"order":48,"id":40,"name":"type-String","prevSize":24,"code":59687},"setIdx":0,"setId":1,"iconIdx":101},{"icon":{"paths":["M955.221 848c0-0.109 10.752 0 0 0-52.751-161.392-240.461-224-443.178-224-202.269 0-389.979 63.392-443.066 224-11.2-0.109 0-1.232 0 0 0 61.936 49.615 112 110.654 112h664.823c61.151 0 110.766-50.064 110.766-112zM290.399 288c0 123.648 99.231 336 221.645 336s221.645-212.352 221.645-336c0-123.648-99.231-224-221.645-224s-221.645 100.352-221.645 224z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user"],"grid":0},"attrs":[{}],"properties":{"order":33,"id":41,"name":"user","prevSize":24,"code":59688},"setIdx":0,"setId":1,"iconIdx":102},{"icon":{"paths":["M469.333 614.997v281.003c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-281.003l97.835 97.835c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331l-170.667-170.667c-0.085-0.085-0.171-0.171-0.256-0.256-4.053-3.968-8.661-6.955-13.568-9.003-5.12-2.133-10.624-3.2-16.085-3.243-0.171 0-0.341 0-0.469 0-5.461 0.043-10.965 1.109-16.085 3.243-4.949 2.048-9.557 5.035-13.568 9.003-0.085 0.085-0.171 0.171-0.256 0.256l-170.667 170.667c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0zM890.411 822.101c30.379-16.555 56.149-38.443 76.672-63.915 21.333-26.411 36.949-56.619 46.379-88.576s12.629-65.835 9.003-99.584c-3.456-32.512-13.269-64.896-29.824-95.232-14.208-26.069-32.384-48.768-53.376-67.669-21.717-19.541-46.421-34.944-72.875-45.952-30.891-12.8-64.171-19.584-98.048-19.84h-22.528c-13.312-37.717-32.085-72.235-55.168-102.912-30.635-40.661-68.821-74.453-111.915-99.84s-91.179-42.411-141.568-49.536c-48.597-6.784-99.243-4.395-149.504 8.619s-95.744 35.413-134.912 64.939c-40.661 30.635-74.453 68.821-99.84 111.915s-42.411 91.179-49.493 141.568c-6.827 48.555-4.395 99.2 8.576 149.461 15.872 61.312 45.781 115.627 84.267 158.421 15.744 17.536 42.752 18.944 60.245 3.2s18.944-42.752 3.2-60.245c-29.355-32.64-52.693-74.667-65.109-122.752-10.155-39.253-11.989-78.592-6.699-116.224 5.504-39.125 18.773-76.501 38.571-110.123s46.080-63.317 77.653-87.083c30.379-22.869 65.664-40.32 104.917-50.475s78.592-11.989 116.224-6.699c39.125 5.504 76.544 18.731 110.123 38.528s63.317 46.080 87.083 77.653c22.869 30.379 40.32 65.664 50.475 104.917 4.907 18.56 21.547 32 41.301 32h53.461c22.869 0.171 45.269 4.736 65.92 13.312 17.707 7.339 34.133 17.621 48.512 30.592 13.909 12.501 25.984 27.605 35.541 45.099 11.093 20.352 17.579 41.899 19.883 63.488 2.389 22.443 0.256 45.013-6.016 66.432s-16.725 41.515-30.933 59.093c-13.611 16.896-30.763 31.445-51.115 42.581-20.693 11.264-28.331 37.205-17.024 57.899s37.205 28.331 57.899 17.024z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload-cloud"],"grid":0},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":24,"code":59763,"name":"upload-3"},"setIdx":0,"setId":1,"iconIdx":103},{"icon":{"paths":["M853.333 640v170.667c0 5.845-1.152 11.349-3.2 16.299-2.133 5.205-5.333 9.899-9.301 13.867s-8.661 7.125-13.867 9.301c-4.949 2.048-10.453 3.2-16.299 3.2h-597.333c-5.845 0-11.349-1.152-16.299-3.2-5.205-2.133-9.899-5.333-13.867-9.301s-7.125-8.661-9.301-13.867c-2.048-4.949-3.2-10.453-3.2-16.299v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v170.667c0 17.28 3.456 33.835 9.728 48.981 6.485 15.701 16 29.781 27.776 41.557s25.856 21.291 41.557 27.776c15.104 6.229 31.659 9.685 48.939 9.685h597.333c17.28 0 33.835-3.456 48.981-9.728 15.701-6.485 29.781-16 41.557-27.776s21.291-25.856 27.776-41.557c6.229-15.104 9.685-31.659 9.685-48.939v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667zM469.333 230.997v409.003c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-409.003l140.501 140.501c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331l-213.333-213.333c-0.043-0.043-0.128-0.085-0.171-0.171-4.053-4.011-8.704-7.040-13.653-9.088-10.453-4.309-22.229-4.309-32.683 0-4.949 2.048-9.6 5.077-13.653 9.088-0.043 0.043-0.128 0.085-0.171 0.171l-213.333 213.333c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload"],"grid":0},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59761,"name":"upload-4"},"setIdx":0,"setId":1,"iconIdx":104},{"icon":{"paths":["M621.254 877.254l320-320c24.994-24.992 24.994-65.516 0-90.51l-320-320c-24.994-24.992-65.516-24.992-90.51 0-24.994 24.994-24.994 65.516 0 90.51l210.746 210.746h-613.49c-35.346 0-64 28.654-64 64s28.654 64 64 64h613.49l-210.746 210.746c-12.496 12.496-18.744 28.876-18.744 45.254s6.248 32.758 18.744 45.254c24.994 24.994 65.516 24.994 90.51 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["arrow-right","right","next"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59766,"name":"arrow-right"},"setIdx":0,"setId":1,"iconIdx":105},{"icon":{"paths":["M448 576h128v-256h192l-256-256-256 256h192zM640 432v98.712l293.066 109.288-421.066 157.018-421.066-157.018 293.066-109.288v-98.712l-384 144v256l512 192 512-192v-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload","load","arrow"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59760,"name":"upload"},"setIdx":0,"setId":1,"iconIdx":106},{"icon":{"paths":["M585.143 548.557c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z","M585.143 219.443c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-bottom"],"grid":16},"attrs":[{},{}],"properties":{"order":125,"id":0,"name":"caret-bottom","prevSize":32,"code":59755},"setIdx":0,"setId":1,"iconIdx":107},{"icon":{"paths":["M585.143 804.577c0 20.005-16.567 36.571-36.571 36.571h-512c-20.005 0-36.571-16.567-36.571-36.571 0-9.728 3.986-18.871 10.862-25.71l256-256c6.839-6.839 16.018-10.862 25.71-10.862s18.871 3.986 25.71 10.862l256 256c6.839 6.839 10.862 16.018 10.862 25.71z","M585.143 475.423c0 20.005-16.567 36.571-36.571 36.571h-512c-20.005 0-36.571-16.567-36.571-36.571 0-9.728 3.986-18.871 10.862-25.71l256-256c6.839-6.839 16.018-10.862 25.71-10.862s18.871 3.986 25.71 10.862l256 256c6.839 6.839 10.862 16.018 10.862 25.71z"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-top"],"grid":16},"attrs":[{},{}],"properties":{"order":124,"id":1,"name":"caret-top","prevSize":32,"code":59756},"setIdx":0,"setId":1,"iconIdx":108},{"icon":{"paths":["M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M408.906 587.72l-35.3-37 138.1-131.9 138 131.9-35.3 37-102.7-98.1z","M511.706 773.12l-138.1-131.9 35.3-37 102.8 98.1 102.7-98.1 35.3 37z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["show"],"grid":16},"attrs":[{},{},{}],"properties":{"order":123,"id":2,"name":"show","prevSize":32,"code":59748},"setIdx":0,"setId":1,"iconIdx":109},{"icon":{"paths":["M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M348.394 15.988c-28.314 0-51.2 22.886-51.2 51.2v23.7h51.2v-23.7h307.2l204.8 204.8v512h-23.8v51.2h23.8c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2z","M408.906 587.72l-35.3-37 138.1-131.9 138 131.9-35.3 37-102.7-98.1z","M511.706 773.12l-138.1-131.9 35.3-37 102.8 98.1 102.7-98.1 35.3 37z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["show-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":122,"id":3,"name":"show-all","prevSize":32,"code":59749},"setIdx":0,"setId":1,"iconIdx":110},{"icon":{"paths":["M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M408.9 418.8l-35.3 37 138 131.9 138.1-131.9-35.3-37-102.8 98.1z","M511.6 604.2l-138 131.9 35.3 37 102.7-98.1 102.8 98.1 35.3-37z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hide"],"grid":16},"attrs":[{},{},{}],"properties":{"order":121,"id":4,"name":"hide","prevSize":32,"code":59750},"setIdx":0,"setId":1,"iconIdx":111},{"icon":{"paths":["M408.9 418.8l-35.3 37 138.1 131.9 138-131.9-35.3-37-102.7 98.1z","M511.7 604.2l-138.1 131.9 35.3 37 102.8-98.1 102.7 98.1 35.3-37z","M256 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-512v-460.8h-51.2v460.8c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM614.4 189.8l117.4 117.4h-117.4z","M348.394 15.988c-28.314 0-51.2 22.886-51.2 51.2v23.7h51.2v-23.7h307.2l204.8 204.8v512h-23.8v51.2h23.8c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hide-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":120,"id":5,"name":"hide-all","prevSize":32,"code":59751},"setIdx":0,"setId":1,"iconIdx":112},{"icon":{"paths":["M512 1024c-136.76 0-265.334-53.258-362.040-149.96-96.702-96.706-149.96-225.28-149.96-362.040 0-96.838 27.182-191.134 78.606-272.692 50-79.296 120.664-143.372 204.356-185.3l43 85.832c-68.038 34.084-125.492 86.186-166.15 150.67-41.746 66.208-63.812 142.798-63.812 221.49 0 229.382 186.618 416 416 416s416-186.618 416-416c0-78.692-22.066-155.282-63.81-221.49-40.66-64.484-98.114-116.584-166.15-150.67l43-85.832c83.692 41.928 154.358 106.004 204.356 185.3 51.422 81.558 78.604 175.854 78.604 272.692 0 136.76-53.258 265.334-149.96 362.040-96.706 96.702-225.28 149.96-362.040 149.96z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["spinner","loading","loading-wheel","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":6,"prevSize":32,"code":59737,"name":"spinner2"},"setIdx":0,"setId":1,"iconIdx":113},{"icon":{"paths":["M1024 397.050l-353.78-51.408-158.22-320.582-158.216 320.582-353.784 51.408 256 249.538-60.432 352.352 316.432-166.358 316.432 166.358-60.434-352.352 256.002-249.538z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-full","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59741,"name":"star-full"},"setIdx":0,"setId":1,"iconIdx":114},{"icon":{"paths":["M1024 397.050l-353.78-51.408-158.22-320.582-158.216 320.582-353.784 51.408 256 249.538-60.432 352.352 316.432-166.358 316.432 166.358-60.434-352.352 256.002-249.538zM512 753.498l-223.462 117.48 42.676-248.83-180.786-176.222 249.84-36.304 111.732-226.396 111.736 226.396 249.836 36.304-180.788 176.222 42.678 248.83-223.462-117.48z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-empty","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":8,"prevSize":32,"code":59742,"name":"star-empty"},"setIdx":0,"setId":1,"iconIdx":115},{"icon":{"paths":["M1024 226.4c-37.6 16.8-78.2 28-120.6 33 43.4-26 76.6-67.2 92.4-116.2-40.6 24-85.6 41.6-133.4 51-38.4-40.8-93-66.2-153.4-66.2-116 0-210 94-210 210 0 16.4 1.8 32.4 5.4 47.8-174.6-8.8-329.4-92.4-433-219.6-18 31-28.4 67.2-28.4 105.6 0 72.8 37 137.2 93.4 174.8-34.4-1-66.8-10.6-95.2-26.2 0 0.8 0 1.8 0 2.6 0 101.8 72.4 186.8 168.6 206-17.6 4.8-36.2 7.4-55.4 7.4-13.6 0-26.6-1.4-39.6-3.8 26.8 83.4 104.4 144.2 196.2 146-72 56.4-162.4 90-261 90-17 0-33.6-1-50.2-3 93.2 59.8 203.6 94.4 322.2 94.4 386.4 0 597.8-320.2 597.8-597.8 0-9.2-0.2-18.2-0.6-27.2 41-29.4 76.6-66.4 104.8-108.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["twitter","brand","tweet","social"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":9,"prevSize":32,"code":59740,"name":"twitter"},"setIdx":0,"setId":1,"iconIdx":116},{"icon":{"paths":["M728.992 512c137.754-87.334 231.008-255.208 231.008-448 0-21.676-1.192-43.034-3.478-64h-889.042c-2.29 20.968-3.48 42.326-3.48 64 0 192.792 93.254 360.666 231.006 448-137.752 87.334-231.006 255.208-231.006 448 0 21.676 1.19 43.034 3.478 64h889.042c2.288-20.966 3.478-42.324 3.478-64 0.002-192.792-93.252-360.666-231.006-448zM160 960c0-186.912 80.162-345.414 224-397.708v-100.586c-143.838-52.29-224-210.792-224-397.706v0h704c0 186.914-80.162 345.416-224 397.706v100.586c143.838 52.294 224 210.796 224 397.708h-704zM619.626 669.594c-71.654-40.644-75.608-93.368-75.626-125.366v-64.228c0-31.994 3.804-84.914 75.744-125.664 38.504-22.364 71.808-56.348 97.048-98.336h-409.582c25.266 42.032 58.612 76.042 97.166 98.406 71.654 40.644 75.606 93.366 75.626 125.366v64.228c0 31.992-3.804 84.914-75.744 125.664-72.622 42.18-126.738 125.684-143.090 226.336h501.67c-16.364-100.708-70.53-184.248-143.212-226.406z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hour-glass","loading","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":32,"code":59732,"name":"hour-glass"},"setIdx":0,"setId":1,"iconIdx":117},{"icon":{"paths":["M192 512c0-12.18 0.704-24.196 2.030-36.022l-184.98-60.104c-5.916 31.14-9.050 63.264-9.050 96.126 0 147.23 62.166 279.922 161.654 373.324l114.284-157.296c-52.124-56.926-83.938-132.758-83.938-216.028zM832 512c0 83.268-31.812 159.102-83.938 216.028l114.284 157.296c99.488-93.402 161.654-226.094 161.654-373.324 0-32.862-3.132-64.986-9.048-96.126l-184.98 60.104c1.324 11.828 2.028 23.842 2.028 36.022zM576 198.408c91.934 18.662 169.544 76.742 214.45 155.826l184.978-60.102c-73.196-155.42-222.24-268.060-399.428-290.156v194.432zM233.55 354.232c44.906-79.084 122.516-137.164 214.45-155.826v-194.43c-177.188 22.096-326.23 134.736-399.426 290.154l184.976 60.102zM644.556 803.328c-40.39 18.408-85.272 28.672-132.556 28.672s-92.166-10.264-132.554-28.67l-114.292 157.31c73.206 40.366 157.336 63.36 246.846 63.36s173.64-22.994 246.848-63.36l-114.292-157.312z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["spinner","loading","loading-wheel","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":32,"code":59731,"name":"spinner"},"setIdx":0,"setId":1,"iconIdx":118},{"icon":{"paths":["M658.744 749.256l-210.744-210.746v-282.51h128v229.49l173.256 173.254zM512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384s-171.922 384-384 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["clock","time","schedule"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":12,"prevSize":32,"code":59728,"name":"clock"},"setIdx":0,"setId":1,"iconIdx":119},{"icon":{"paths":["M128 320v640c0 35.2 28.8 64 64 64h576c35.2 0 64-28.8 64-64v-640h-704zM320 896h-64v-448h64v448zM448 896h-64v-448h64v448zM576 896h-64v-448h64v448zM704 896h-64v-448h64v448z","M848 128h-208v-80c0-26.4-21.6-48-48-48h-224c-26.4 0-48 21.6-48 48v80h-208c-26.4 0-48 21.6-48 48v80h832v-80c0-26.4-21.6-48-48-48zM576 128h-192v-63.198h192v63.198z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bin","trashcan","remove","delete","recycle","dispose"],"grid":16},"attrs":[{},{}],"properties":{"order":1,"id":13,"name":"bin2","prevSize":32,"code":59650},"setIdx":0,"setId":1,"iconIdx":120},{"icon":{"paths":["M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 960.002c-62.958 0-122.872-13.012-177.23-36.452l233.148-262.29c5.206-5.858 8.082-13.422 8.082-21.26v-96c0-17.674-14.326-32-32-32-112.99 0-232.204-117.462-233.374-118.626-6-6.002-14.14-9.374-22.626-9.374h-128c-17.672 0-32 14.328-32 32v192c0 12.122 6.848 23.202 17.69 28.622l110.31 55.156v187.886c-116.052-80.956-192-215.432-192-367.664 0-68.714 15.49-133.806 43.138-192h116.862c8.488 0 16.626-3.372 22.628-9.372l128-128c6-6.002 9.372-14.14 9.372-22.628v-77.412c40.562-12.074 83.518-18.588 128-18.588 70.406 0 137.004 16.26 196.282 45.2-4.144 3.502-8.176 7.164-12.046 11.036-36.266 36.264-56.236 84.478-56.236 135.764s19.97 99.5 56.236 135.764c36.434 36.432 85.218 56.264 135.634 56.26 3.166 0 6.342-0.080 9.518-0.236 13.814 51.802 38.752 186.656-8.404 372.334-0.444 1.744-0.696 3.488-0.842 5.224-81.324 83.080-194.7 134.656-320.142 134.656z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["earth","globe","language","web","internet","sphere","planet"],"defaultCode":59850,"grid":16},"attrs":[],"properties":{"ligatures":"earth, globe2","name":"earth","id":14,"order":91,"prevSize":32,"code":59850},"setIdx":0,"setId":1,"iconIdx":121},{"icon":{"paths":["M512.002 193.212v-65.212h128v-64c0-35.346-28.654-64-64.002-64h-191.998c-35.346 0-64 28.654-64 64v64h128v65.212c-214.798 16.338-384 195.802-384 414.788 0 229.75 186.25 416 416 416s416-186.25 416-416c0-218.984-169.202-398.448-384-414.788zM706.276 834.274c-60.442 60.44-140.798 93.726-226.274 93.726s-165.834-33.286-226.274-93.726c-60.44-60.44-93.726-140.8-93.726-226.274s33.286-165.834 93.726-226.274c58.040-58.038 134.448-91.018 216.114-93.548l-21.678 314.020c-1.86 26.29 12.464 37.802 31.836 37.802s33.698-11.512 31.836-37.802l-21.676-314.022c81.666 2.532 158.076 35.512 216.116 93.55 60.44 60.44 93.726 140.8 93.726 226.274s-33.286 165.834-93.726 226.274z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["stopwatch","time","speed","meter","chronometer"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":15,"prevSize":32,"code":59715,"name":"elapsed"},"setIdx":0,"setId":1,"iconIdx":122},{"icon":{"paths":["M522.2 438.8v175.6h290.4c-11.8 75.4-87.8 220.8-290.4 220.8-174.8 0-317.4-144.8-317.4-323.2s142.6-323.2 317.4-323.2c99.4 0 166 42.4 204 79l139-133.8c-89.2-83.6-204.8-134-343-134-283 0-512 229-512 512s229 512 512 512c295.4 0 491.6-207.8 491.6-500.2 0-33.6-3.6-59.2-8-84.8l-483.6-0.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["google","brand"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":16,"prevSize":32,"code":59707,"name":"google"},"setIdx":0,"setId":1,"iconIdx":123},{"icon":{"paths":["M592 448h-16v-192c0-105.87-86.13-192-192-192h-128c-105.87 0-192 86.13-192 192v192h-16c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48zM192 256c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192h-256v-192z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["lock","secure","private","encrypted"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":17,"prevSize":32,"code":59700,"name":"lock"},"setIdx":0,"setId":1,"iconIdx":124},{"icon":{"paths":["M0.35 512l-0.35-312.074 384-52.144v364.218zM448 138.482l511.872-74.482v448h-511.872zM959.998 576l-0.126 448-511.872-72.016v-375.984zM384 943.836l-383.688-52.594-0.020-315.242h383.708z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["windows8","brand","os"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":18,"prevSize":32,"code":59712,"name":"microsoft"},"setIdx":0,"setId":1,"iconIdx":125},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":32,"code":59695,"name":"pause"},"setIdx":0,"setId":1,"iconIdx":126},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":20,"prevSize":32,"code":59696,"name":"play"},"setIdx":0,"setId":1,"iconIdx":127},{"icon":{"paths":["M889.68 166.32c-93.608-102.216-228.154-166.32-377.68-166.32-282.77 0-512 229.23-512 512h96c0-229.75 186.25-416 416-416 123.020 0 233.542 53.418 309.696 138.306l-149.696 149.694h352v-352l-134.32 134.32z","M928 512c0 229.75-186.25 416-416 416-123.020 0-233.542-53.418-309.694-138.306l149.694-149.694h-352v352l134.32-134.32c93.608 102.216 228.154 166.32 377.68 166.32 282.77 0 512-229.23 512-512h-96z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["loop","repeat","player","reload","refresh","update","synchronize","arrows"],"grid":16},"attrs":[{},{}],"properties":{"order":49,"id":21,"prevSize":32,"code":59694,"name":"reset"},"setIdx":0,"setId":1,"iconIdx":128},{"icon":{"paths":["M933.79 610.25c-53.726-93.054-21.416-212.304 72.152-266.488l-100.626-174.292c-28.75 16.854-62.176 26.518-97.846 26.518-107.536 0-194.708-87.746-194.708-195.99h-201.258c0.266 33.41-8.074 67.282-25.958 98.252-53.724 93.056-173.156 124.702-266.862 70.758l-100.624 174.292c28.97 16.472 54.050 40.588 71.886 71.478 53.638 92.908 21.512 211.92-71.708 266.224l100.626 174.292c28.65-16.696 61.916-26.254 97.4-26.254 107.196 0 194.144 87.192 194.7 194.958h201.254c-0.086-33.074 8.272-66.57 25.966-97.218 53.636-92.906 172.776-124.594 266.414-71.012l100.626-174.29c-28.78-16.466-53.692-40.498-71.434-71.228zM512 719.332c-114.508 0-207.336-92.824-207.336-207.334 0-114.508 92.826-207.334 207.336-207.334 114.508 0 207.332 92.826 207.332 207.334-0.002 114.51-92.824 207.334-207.332 207.334z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cog","gear","preferences","settings","generate","control","options"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":22,"prevSize":32,"code":59693,"name":"settings2"},"setIdx":0,"setId":1,"iconIdx":129},{"icon":{"paths":["M512 128c-247.424 0-448 200.576-448 448s200.576 448 448 448 448-200.576 448-448-200.576-448-448-448zM512 936c-198.824 0-360-161.178-360-360 0-198.824 161.176-360 360-360 198.822 0 360 161.176 360 360 0 198.822-161.178 360-360 360zM934.784 287.174c16.042-28.052 25.216-60.542 25.216-95.174 0-106.040-85.96-192-192-192-61.818 0-116.802 29.222-151.92 74.596 131.884 27.236 245.206 105.198 318.704 212.578v0zM407.92 74.596c-35.116-45.374-90.102-74.596-151.92-74.596-106.040 0-192 85.96-192 192 0 34.632 9.174 67.122 25.216 95.174 73.5-107.38 186.822-185.342 318.704-212.578z","M512 576v-256h-64v320h256v-64z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["alarm","time","clock"],"grid":16},"attrs":[{},{}],"properties":{"order":2,"id":23,"prevSize":32,"code":59716,"name":"timeout"},"setIdx":0,"setId":1,"iconIdx":130},{"icon":{"paths":["M768 64c105.87 0 192 86.13 192 192v192h-128v-192c0-35.29-28.71-64-64-64h-128c-35.29 0-64 28.71-64 64v192h16c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48h-544c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h400v-192c0-105.87 86.13-192 192-192h128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["unlocked","lock-open"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":24,"prevSize":32,"code":59699,"name":"unlocked"},"setIdx":0,"setId":1,"iconIdx":131},{"icon":{"paths":["M832 416h-320v64h-64v-96h384v-192h-32v96c0 17.664-14.336 32-32 32h-576c-17.696 0-32-14.336-32-32v-128c0-17.696 14.304-32 32-32h576c17.664 0 32 14.304 32 32h64v256h-32zM736 160h-512v32h512v-32zM544 832c0 35.328-28.672 64-64 64s-64-28.672-64-64v-320h128v320zM480 786.656c-17.696 0-32 14.336-32 32 0 17.696 14.304 32 32 32 17.664 0 32-14.304 32-32 0-17.664-14.336-32-32-32z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["paint","tool"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59725,"name":"control-Color"},"setIdx":0,"setId":1,"iconIdx":132},{"icon":{"paths":["M1328 320c-8.832 0-16 7.168-16 16v640c0 8.832-7.168 16-16 16h-1248c-8.832 0-16-7.168-16-16v-640c0-8.832-7.168-16-16-16s-16 7.168-16 16v640c0 26.464 21.536 48 48 48h1248c26.464 0 48-21.536 48-48v-640c0-8.832-7.168-16-16-16zM1296 0h-1248c-26.464 0-48 21.536-48 48v192c0 8.832 7.168 16 16 16h1312c8.832 0 16-7.168 16-16v-192c0-26.464-21.536-48-48-48zM1312 224h-1280v-176c0-8.832 7.168-16 16-16h1248c8.832 0 16 7.168 16 16v176zM560 896c8.832 0 16-7.168 16-16v-512c0-8.832-7.168-16-16-16h-416c-8.832 0-16 7.168-16 16v512c0 8.832 7.168 16 16 16h416zM160 384h384v480h-384v-480zM720 480h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM720 640h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM720 800h480c8.832 0 16-7.168 16-16s-7.168-16-16-16h-480c-8.832 0-16 7.168-16 16s7.168 16 16 16zM96 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM224 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM352 128c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32z"],"width":1344,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59701,"name":"browser"},"setIdx":0,"setId":1,"iconIdx":133},{"icon":{"paths":["M927.936 272.992l-68.288-68.288c-12.608-12.576-32.96-12.576-45.536 0l-409.44 409.44-194.752-196.16c-12.576-12.576-32.928-12.576-45.536 0l-68.288 68.288c-12.576 12.608-12.576 32.96 0 45.536l285.568 287.488c12.576 12.576 32.96 12.576 45.536 0l500.736-500.768c12.576-12.544 12.576-32.96 0-45.536z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["checkmark","tick","approve","submit"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":0,"setId":1,"iconIdx":134},{"icon":{"paths":["M1020.192 401.824c-8.864-25.568-31.616-44.288-59.008-48.352l-266.432-39.616-115.808-240.448c-12.192-25.248-38.272-41.408-66.944-41.408s-54.752 16.16-66.944 41.408l-115.808 240.448-266.464 39.616c-27.36 4.064-50.112 22.784-58.944 48.352-8.8 25.632-2.144 53.856 17.184 73.12l195.264 194.944-45.28 270.432c-4.608 27.232 7.2 54.56 30.336 70.496 12.704 8.736 27.648 13.184 42.592 13.184 12.288 0 24.608-3.008 35.776-8.992l232.288-125.056 232.32 125.056c11.168 5.984 23.488 8.992 35.744 8.992 14.944 0 29.888-4.448 42.624-13.184 23.136-15.936 34.88-43.264 30.304-70.496l-45.312-270.432 195.328-194.944c19.296-19.296 25.92-47.52 17.184-73.12zM754.816 619.616c-16.384 16.32-23.808 39.328-20.064 61.888l45.312 270.432-232.32-124.992c-11.136-6.016-23.424-8.992-35.776-8.992-12.288 0-24.608 3.008-35.744 8.992l-232.32 124.992 45.312-270.432c3.776-22.56-3.648-45.568-20.032-61.888l-195.264-194.944 266.432-39.68c24.352-3.616 45.312-18.848 55.776-40.576l115.872-240.384 115.84 240.416c10.496 21.728 31.424 36.928 55.744 40.576l266.496 39.68-195.264 194.912z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star","favorite"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":3,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":0,"setId":1,"iconIdx":135},{"icon":{"paths":["M409.6 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM409.6 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["grid"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":0,"setId":1,"iconIdx":136},{"icon":{"paths":["M737.28 460.8h-296.96c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h296.96c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM839.68 716.8h-399.36c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h399.36c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM440.32 307.2h399.36c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2h-399.36c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2zM276.48 460.8h-92.16c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h92.16c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM276.48 716.8h-92.16c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h92.16c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2zM276.48 204.8h-92.16c-28.262 0-30.72 22.886-30.72 51.2s2.458 51.2 30.72 51.2h92.16c28.262 0 30.72-22.886 30.72-51.2s-2.458-51.2-30.72-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["list"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":1,"name":"list","prevSize":20,"code":59726},"setIdx":0,"setId":1,"iconIdx":137},{"icon":{"paths":["M636.518 0c68.608 0 102.912 46.694 102.912 100.198 0 66.816-59.597 128.614-137.165 128.614-64.973 0-102.861-38.4-101.069-101.888 0-53.402 45.107-126.925 135.322-126.925zM425.421 1024c-54.17 0-93.85-33.382-55.962-180.429l62.157-260.71c10.803-41.677 12.595-58.419 0-58.419-16.23 0-86.477 28.774-128.102 57.19l-27.034-45.056c131.686-111.923 283.187-177.51 348.211-177.51 54.118 0 63.13 65.178 36.096 165.376l-71.219 274.022c-12.595 48.384-7.219 65.075 5.427 65.075 16.23 0 69.478-20.070 121.805-61.798l30.72 41.677c-128.102 130.406-268.032 180.582-322.099 180.582z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["info"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":20,"code":59708,"name":"info"},"setIdx":0,"setId":1,"iconIdx":138}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showCodes":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"name":"icomoon","classSelector":".icon"},"historySize":50,"gridSize":16}} \ No newline at end of file diff --git a/frontend/app/theme/icomoon/style.css b/frontend/app/theme/icomoon/style.css index 96e56acaa..7bb6b40f6 100644 --- a/frontend/app/theme/icomoon/style.css +++ b/frontend/app/theme/icomoon/style.css @@ -1,10 +1,10 @@ @font-face { font-family: 'icomoon'; - src: url('fonts/icomoon.eot?osg65x'); - src: url('fonts/icomoon.eot?osg65x#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?osg65x') format('truetype'), - url('fonts/icomoon.woff?osg65x') format('woff'), - url('fonts/icomoon.svg?osg65x#icomoon') format('svg'); + src: url('fonts/icomoon.eot?trv5pt'); + src: url('fonts/icomoon.eot?trv5pt#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?trv5pt') format('truetype'), + url('fonts/icomoon.woff?trv5pt') format('woff'), + url('fonts/icomoon.svg?trv5pt#icomoon') format('svg'); font-weight: normal; font-style: normal; font-display: block; @@ -25,6 +25,9 @@ -moz-osx-font-smoothing: grayscale; } +.icon-component:before { + content: "\e986"; +} .icon-plugin:before { content: "\e985"; } @@ -58,9 +61,15 @@ .icon-search-Content:before { content: "\e958"; } +.icon-type-Component:before { + content: "\e958"; +} .icon-multiple-content:before { content: "\e957"; } +.icon-type-Components:before { + content: "\e957"; +} .icon-type-Array:before { content: "\e956"; }