From 4d513448b3d8e2920ae46c33e3c9d11728c50761 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 21 Nov 2018 08:58:29 +0100 Subject: [PATCH 01/33] Remove orleans health check. --- src/Squidex/Config/Domain/InfrastructureServices.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Squidex/Config/Domain/InfrastructureServices.cs b/src/Squidex/Config/Domain/InfrastructureServices.cs index 3c2b245c5..18671e30b 100644 --- a/src/Squidex/Config/Domain/InfrastructureServices.cs +++ b/src/Squidex/Config/Domain/InfrastructureServices.cs @@ -42,9 +42,6 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); - services.AddSingletonAs() - .As(); - services.AddSingletonAs() .As(); From 852b0400a529b653d618ddc8823999780b4eb709 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 21 Nov 2018 10:29:40 +0100 Subject: [PATCH 02/33] Readiness and liveness check. --- .../Diagnostics/OrleansAppsHealthCheck.cs | 6 ++++ .../Diagnostics/GetEventStoreHealthCheck.cs | 6 ++++ .../Diagnostics/MongoDBHealthCheck.cs | 6 ++++ .../Diagnostics/GCHealthCheck.cs | 5 ++++ .../Diagnostics/HealthCheckScopes.cs | 16 ++++++++++ .../Diagnostics/IHealthCheck.cs | 3 ++ .../Diagnostics/OrleansHealthCheck.cs | 6 ++++ .../Config/Domain/InfrastructureServices.cs | 9 ++++-- src/Squidex/Config/Web/WebExtensions.cs | 17 ++++++++++- .../Diagnostics/HealthCheckMiddleware.cs | 30 ++++++++++++++----- 10 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 src/Squidex.Infrastructure/Diagnostics/HealthCheckScopes.cs diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Diagnostics/OrleansAppsHealthCheck.cs b/src/Squidex.Domain.Apps.Entities/Apps/Diagnostics/OrleansAppsHealthCheck.cs index 279f14790..0e5f68fd9 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/Diagnostics/OrleansAppsHealthCheck.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/Diagnostics/OrleansAppsHealthCheck.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Orleans; @@ -19,6 +20,11 @@ namespace Squidex.Domain.Apps.Entities.Apps.Diagnostics { private readonly IAppsByNameIndex index; + public IEnumerable Scopes + { + get { yield return HealthCheckScopes.Cluster; } + } + public OrleansAppsHealthCheck(IGrainFactory grainFactory) { Guard.NotNull(grainFactory, nameof(grainFactory)); diff --git a/src/Squidex.Infrastructure.GetEventStore/Diagnostics/GetEventStoreHealthCheck.cs b/src/Squidex.Infrastructure.GetEventStore/Diagnostics/GetEventStoreHealthCheck.cs index 42ef4e206..a4f2d3aea 100644 --- a/src/Squidex.Infrastructure.GetEventStore/Diagnostics/GetEventStoreHealthCheck.cs +++ b/src/Squidex.Infrastructure.GetEventStore/Diagnostics/GetEventStoreHealthCheck.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using EventStore.ClientAPI; @@ -15,6 +16,11 @@ namespace Squidex.Infrastructure.Diagnostics { private readonly IEventStoreConnection connection; + public IEnumerable Scopes + { + get { yield return HealthCheckScopes.Node; } + } + public GetEventStoreHealthCheck(IEventStoreConnection connection) { Guard.NotNull(connection, nameof(connection)); diff --git a/src/Squidex.Infrastructure.MongoDb/Diagnostics/MongoDBHealthCheck.cs b/src/Squidex.Infrastructure.MongoDb/Diagnostics/MongoDBHealthCheck.cs index 33ed7b077..492c0eae6 100644 --- a/src/Squidex.Infrastructure.MongoDb/Diagnostics/MongoDBHealthCheck.cs +++ b/src/Squidex.Infrastructure.MongoDb/Diagnostics/MongoDBHealthCheck.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; @@ -15,6 +16,11 @@ namespace Squidex.Infrastructure.Diagnostics { private readonly IMongoDatabase mongoDatabase; + public IEnumerable Scopes + { + get { yield return HealthCheckScopes.Node; } + } + public MongoDBHealthCheck(IMongoDatabase mongoDatabase) { Guard.NotNull(mongoDatabase, nameof(mongoDatabase)); diff --git a/src/Squidex.Infrastructure/Diagnostics/GCHealthCheck.cs b/src/Squidex.Infrastructure/Diagnostics/GCHealthCheck.cs index 62d175e74..0a9b4aac7 100644 --- a/src/Squidex.Infrastructure/Diagnostics/GCHealthCheck.cs +++ b/src/Squidex.Infrastructure/Diagnostics/GCHealthCheck.cs @@ -17,6 +17,11 @@ namespace Squidex.Infrastructure.Diagnostics { private readonly long threshold; + public IEnumerable Scopes + { + get { yield return HealthCheckScopes.Node; } + } + public GCHealthCheck(IOptions options) { Guard.NotNull(options, nameof(options)); diff --git a/src/Squidex.Infrastructure/Diagnostics/HealthCheckScopes.cs b/src/Squidex.Infrastructure/Diagnostics/HealthCheckScopes.cs new file mode 100644 index 000000000..327c46c22 --- /dev/null +++ b/src/Squidex.Infrastructure/Diagnostics/HealthCheckScopes.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Diagnostics +{ + public static class HealthCheckScopes + { + public const string Any = "*"; + public const string Node = "node"; + public const string Cluster = "cluster"; + } +} diff --git a/src/Squidex.Infrastructure/Diagnostics/IHealthCheck.cs b/src/Squidex.Infrastructure/Diagnostics/IHealthCheck.cs index f139deaed..eaf8e11b0 100644 --- a/src/Squidex.Infrastructure/Diagnostics/IHealthCheck.cs +++ b/src/Squidex.Infrastructure/Diagnostics/IHealthCheck.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -12,6 +13,8 @@ namespace Squidex.Infrastructure.Diagnostics { public interface IHealthCheck { + IEnumerable Scopes { get; } + Task CheckHealthAsync(CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/src/Squidex.Infrastructure/Diagnostics/OrleansHealthCheck.cs b/src/Squidex.Infrastructure/Diagnostics/OrleansHealthCheck.cs index 8c6a26f1a..8351626d9 100644 --- a/src/Squidex.Infrastructure/Diagnostics/OrleansHealthCheck.cs +++ b/src/Squidex.Infrastructure/Diagnostics/OrleansHealthCheck.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Orleans; @@ -16,6 +17,11 @@ namespace Squidex.Infrastructure.Diagnostics { private readonly IManagementGrain managementGrain; + public IEnumerable Scopes + { + get { yield return HealthCheckScopes.Cluster; } + } + public OrleansHealthCheck(IGrainFactory grainFactory) { Guard.NotNull(grainFactory, nameof(grainFactory)); diff --git a/src/Squidex/Config/Domain/InfrastructureServices.cs b/src/Squidex/Config/Domain/InfrastructureServices.cs index 18671e30b..bf8d71575 100644 --- a/src/Squidex/Config/Domain/InfrastructureServices.cs +++ b/src/Squidex/Config/Domain/InfrastructureServices.cs @@ -42,6 +42,9 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); + services.AddSingletonAs() + .As(); + services.AddSingletonAs() .As(); @@ -51,12 +54,12 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); - services.AddSingletonAs() - .As(); - services.AddSingletonAs() .As(); + services.AddSingletonAs() + .As(); + services.AddTransient(typeof(Lazy<>), typeof(Lazier<>)); } } diff --git a/src/Squidex/Config/Web/WebExtensions.cs b/src/Squidex/Config/Web/WebExtensions.cs index fa649cab3..9886fbc73 100644 --- a/src/Squidex/Config/Web/WebExtensions.cs +++ b/src/Squidex/Config/Web/WebExtensions.cs @@ -5,8 +5,10 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpOverrides; +using Squidex.Infrastructure.Diagnostics; using Squidex.Pipeline; using Squidex.Pipeline.Diagnostics; using Squidex.Pipeline.Robots; @@ -31,7 +33,20 @@ namespace Squidex.Config.Web public static IApplicationBuilder UseMyHealthCheck(this IApplicationBuilder app) { - app.Map("/healthz", builder => builder.UseMiddleware()); + app.Map("/readiness", builder => + { + builder.UseMiddleware(HealthCheckScopes.Any); + }); + + app.Map("/healthz", builder => + { + builder.UseMiddleware(HealthCheckScopes.Node); + }); + + app.Map("/cluster-healthz", builder => + { + builder.UseMiddleware(HealthCheckScopes.Cluster); + }); return app; } diff --git a/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs b/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs index 11eec2ded..2025dbbfb 100644 --- a/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs +++ b/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs @@ -17,40 +17,46 @@ using Squidex.Infrastructure.Diagnostics; namespace Squidex.Pipeline.Diagnostics { - public sealed class HealthCheckMiddleware : IMiddleware + public sealed class HealthCheckMiddleware { private const string Suffix = "HealthCheck"; private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(2); private readonly Dictionary healthChecks; private readonly JsonSerializerSettings serializerSettings; + private readonly RequestDelegate next; + private readonly List scopes; - public HealthCheckMiddleware(IEnumerable healthChecks, JsonSerializerSettings serializerSettings) + public HealthCheckMiddleware(IEnumerable healthChecks, JsonSerializerSettings serializerSettings, RequestDelegate next, string scopes) { Guard.NotNull(healthChecks, nameof(healthChecks)); Guard.NotNull(serializerSettings, nameof(serializerSettings)); this.healthChecks = healthChecks.ToDictionary(GetName); + this.next = next; + this.scopes = SplitScopes(scopes); this.serializerSettings = serializerSettings; } - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async Task Invoke(HttpContext context) { if (CanServeRequest(context.Request)) { using (var cts = new CancellationTokenSource(Timeout)) { - var checks = await Task.WhenAll(healthChecks.Select(x => MakeHealthCheckAsync(x.Key, x.Value, cts.Token))); + var matchingChecks = healthChecks.Where(x => CanUseCheck(x.Value)); + + var results = await Task.WhenAll(matchingChecks.Select(x => MakeHealthCheckAsync(x.Key, x.Value, cts.Token))); context.Response.StatusCode = 200; context.Response.Headers.Add("Content-Type", "application/json"); - if (checks.Any(x => !x.Result.IsHealthy)) + if (results.Any(x => !x.Result.IsHealthy)) { context.Response.StatusCode = 503; } - var response = checks.ToDictionary(x => x.Name, x => x.Result); + var response = results.ToDictionary(x => x.Name, x => x.Result); await context.Response.WriteAsync(JsonConvert.SerializeObject(new { status = response }, Formatting.Indented, serializerSettings)); } @@ -61,11 +67,21 @@ namespace Squidex.Pipeline.Diagnostics } } - private static bool CanServeRequest(HttpRequest request) + private bool CanUseCheck(IHealthCheck check) + { + return scopes.Count == 0 || check.Scopes.Intersect(scopes).Any(); + } + + private bool CanServeRequest(HttpRequest request) { return HttpMethods.IsGet(request.Method) && (request.Path == "/" || string.IsNullOrEmpty(request.Path)); } + private static List SplitScopes(string scopes) + { + return scopes.Split(",").Where(x => x != "*").ToList(); + } + private static string GetName(IHealthCheck check) { var name = check.GetType().Name.ToCamelCase(); From d8955127fb04988b932d9588f8aca6a360a9f049 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 21 Nov 2018 20:54:47 +0100 Subject: [PATCH 03/33] Fix Admin fallback. --- .../MongoUserStore.cs | 1 + .../UserClaimsPrincipalFactoryWithEmail.cs | 13 ++++++++++++- .../OrleansDashboardAuthenticationMiddleware.cs | 17 ++++++++++++----- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs b/src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs index 62604760d..8ce972c1f 100644 --- a/src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs +++ b/src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs @@ -32,6 +32,7 @@ namespace Squidex.Domain.Users.MongoDb IUserLoginStore, IUserPasswordStore, IUserPhoneNumberStore, + IUserRoleStore, IUserSecurityStampStore, IUserTwoFactorStore, IUserTwoFactorRecoveryCodeStore, diff --git a/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs b/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs index f0efcdfd9..1d6c0f4e5 100644 --- a/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs +++ b/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs @@ -11,11 +11,15 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Squidex.Infrastructure.Security; +using Squidex.Shared; +using Squidex.Shared.Identity; namespace Squidex.Domain.Users { public sealed class UserClaimsPrincipalFactoryWithEmail : UserClaimsPrincipalFactory { + private const string AdministratorRole = "ADMINISTRATOR"; + public UserClaimsPrincipalFactoryWithEmail(UserManager userManager, RoleManager roleManager, IOptions optionsAccessor) : base(userManager, roleManager, optionsAccessor) { @@ -25,7 +29,14 @@ namespace Squidex.Domain.Users { var principal = await base.CreateAsync(user); - principal.Identities.First().AddClaim(new Claim(OpenIdClaims.Email, await UserManager.GetEmailAsync(user))); + var identity = principal.Identities.First(); + + identity.AddClaim(new Claim(OpenIdClaims.Email, await UserManager.GetEmailAsync(user))); + + if (await UserManager.IsInRoleAsync(user, AdministratorRole)) + { + identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, Permissions.Admin)); + } return principal; } diff --git a/src/Squidex/Areas/OrleansDashboard/Middlewares/OrleansDashboardAuthenticationMiddleware.cs b/src/Squidex/Areas/OrleansDashboard/Middlewares/OrleansDashboardAuthenticationMiddleware.cs index 08da9330f..a93e679d4 100644 --- a/src/Squidex/Areas/OrleansDashboard/Middlewares/OrleansDashboardAuthenticationMiddleware.cs +++ b/src/Squidex/Areas/OrleansDashboard/Middlewares/OrleansDashboardAuthenticationMiddleware.cs @@ -31,16 +31,23 @@ namespace Squidex.Areas.OrleansDashboard.Middlewares { var authentication = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); - if (!authentication.Succeeded || !authentication.Principal.Permissions().Allows(OrleansPermissions)) + if (authentication.Succeeded) { - await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties + if (authentication.Principal.Permissions().Allows(OrleansPermissions)) { - RedirectUri = context.Request.PathBase + context.Request.Path - }); + await next(context); + } + else + { + context.Response.StatusCode = 403; + } } else { - await next(context); + await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties + { + RedirectUri = context.Request.PathBase + context.Request.Path + }); } } } From 9c98560d35d9f2f8b026709f291c4caa760c27a8 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 22 Nov 2018 16:39:59 +0100 Subject: [PATCH 04/33] More tags editors and allowed values. --- .../Schemas/TagsFieldEditor.cs | 16 ++ .../Schemas/TagsFieldProperties.cs | 5 + .../Validators/AllowedValuesValidator.cs | 8 +- .../ValidateContent/ValidatorsFactory.cs | 9 +- .../Guards/FieldPropertiesValidator.cs | 12 ++ .../Converters/FieldPropertiesDtoFactory.cs | 6 +- .../Models/Fields/TagsFieldPropertiesDto.cs | 23 ++- .../shared/field-editor.component.html | 14 +- .../pages/schema/types/tags-ui.component.html | 59 ++++++- .../pages/schema/types/tags-ui.component.ts | 20 ++- .../forms/checkbox-group.component.html | 9 ++ .../forms/checkbox-group.component.scss | 12 ++ .../angular/forms/checkbox-group.component.ts | 79 ++++++++++ .../angular/forms/control-errors.component.ts | 3 +- .../angular/forms/dropdown.component.html | 26 --- .../angular/forms/dropdown.component.scss | 38 ----- .../angular/forms/dropdown.component.ts | 149 ------------------ .../angular/forms/validators.spec.ts | 24 +++ .../app/framework/angular/forms/validators.ts | 20 +++ src/Squidex/app/framework/declarations.ts | 2 +- src/Squidex/app/framework/module.ts | 6 +- .../app/shared/services/schemas.types.ts | 7 +- .../app/shared/state/contents.forms.spec.ts | 2 +- .../app/shared/state/contents.forms.ts | 6 + src/Squidex/app/theme/icomoon/demo.html | 18 ++- .../app/theme/icomoon/fonts/icomoon.eot | Bin 25972 -> 26200 bytes .../app/theme/icomoon/fonts/icomoon.svg | 1 + .../app/theme/icomoon/fonts/icomoon.ttf | Bin 25808 -> 26036 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 25884 -> 26112 bytes .../icomoon/icons/control-Checkboxes.svg | 68 ++++++++ src/Squidex/app/theme/icomoon/selection.json | 2 +- src/Squidex/app/theme/icomoon/style.css | 13 +- .../ValidateContent/TagsFieldTests.cs | 12 ++ .../TagsFieldPropertiesTests.cs | 28 ++++ 34 files changed, 455 insertions(+), 242 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldEditor.cs create mode 100644 src/Squidex/app/framework/angular/forms/checkbox-group.component.html create mode 100644 src/Squidex/app/framework/angular/forms/checkbox-group.component.scss create mode 100644 src/Squidex/app/framework/angular/forms/checkbox-group.component.ts delete mode 100644 src/Squidex/app/framework/angular/forms/dropdown.component.html delete mode 100644 src/Squidex/app/framework/angular/forms/dropdown.component.scss delete mode 100644 src/Squidex/app/framework/angular/forms/dropdown.component.ts create mode 100644 src/Squidex/app/theme/icomoon/icons/control-Checkboxes.svg diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldEditor.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldEditor.cs new file mode 100644 index 000000000..0c1b15c6b --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldEditor.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Domain.Apps.Core.Schemas +{ + public enum TagsFieldEditor + { + Tags, + Checkboxes, + Dropdown + } +} diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs index 0c2b5df37..a50cc4bd9 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs @@ -6,16 +6,21 @@ // ========================================================================== using Squidex.Infrastructure; +using System.Collections.Immutable; namespace Squidex.Domain.Apps.Core.Schemas { [TypeName("TagsField")] public sealed class TagsFieldProperties : FieldProperties { + public ImmutableList AllowedValues { get; set; } + public int? MinItems { get; set; } public int? MaxItems { get; set; } + public TagsFieldEditor Editor { get; set; } + public TagsFieldNormalization Normalization { get; set; } public override T Accept(IFieldPropertiesVisitor visitor) diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AllowedValuesValidator.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AllowedValuesValidator.cs index 9b1d6129d..cc1fcdfca 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AllowedValuesValidator.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AllowedValuesValidator.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Squidex.Infrastructure; @@ -14,9 +15,14 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators { public sealed class AllowedValuesValidator : IValidator { - private readonly T[] allowedValues; + private readonly IEnumerable allowedValues; public AllowedValuesValidator(params T[] allowedValues) + : this((IEnumerable)allowedValues) + { + } + + public AllowedValuesValidator(IEnumerable allowedValues) { Guard.NotNull(allowedValues, nameof(allowedValues)); diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs index eba15cb29..fc104e7e5 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs @@ -109,7 +109,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent if (field.Properties.AllowedValues != null) { - yield return new AllowedValuesValidator(field.Properties.AllowedValues.ToArray()); + yield return new AllowedValuesValidator(field.Properties.AllowedValues); } } @@ -145,7 +145,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent if (field.Properties.AllowedValues != null) { - yield return new AllowedValuesValidator(field.Properties.AllowedValues.ToArray()); + yield return new AllowedValuesValidator(field.Properties.AllowedValues); } } @@ -156,6 +156,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent yield return new CollectionValidator(field.Properties.IsRequired, field.Properties.MinItems, field.Properties.MaxItems); } + if (field.Properties.AllowedValues != null) + { + yield return new CollectionItemValidator(new AllowedValuesValidator(field.Properties.AllowedValues)); + } + yield return new CollectionItemValidator(new RequiredStringValidator()); } } diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs index 8beb2b8f1..3f10076f0 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs @@ -243,6 +243,18 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards public IEnumerable Visit(TagsFieldProperties properties) { + if (!properties.Editor.IsEnumValue()) + { + yield return new ValidationError("Editor is not a valid value.", + nameof(properties.Editor)); + } + + if ((properties.Editor == TagsFieldEditor.Checkboxes || properties.Editor == TagsFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Count == 0)) + { + yield return new ValidationError("Chekboxes or dropdown list need allowed values.", + nameof(properties.AllowedValues)); + } + if (properties.MaxItems.HasValue && properties.MinItems.HasValue && properties.MinItems.Value >= properties.MaxItems.Value) { yield return new ValidationError("Max items must be greater than min items.", diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs index 9750fc7c4..31bc2cc01 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Converters/FieldPropertiesDtoFactory.cs @@ -57,7 +57,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Converters public FieldPropertiesDto Visit(TagsFieldProperties properties) { - return SimpleMapper.Map(properties, new TagsFieldPropertiesDto()); + var result = SimpleMapper.Map(properties, new TagsFieldPropertiesDto()); + + result.AllowedValues = properties.AllowedValues?.ToArray(); + + return result; } public FieldPropertiesDto Visit(AssetsFieldProperties properties) diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs index 139bbdf8f..147309749 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs @@ -5,6 +5,9 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Immutable; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Reflection; @@ -24,9 +27,27 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// public int? MaxItems { get; set; } + /// + /// The allowed values for the field value. + /// + public string[] AllowedValues { get; set; } + + /// + /// The editor that is used to manage this field. + /// + [JsonConverter(typeof(StringEnumConverter))] + public TagsFieldEditor Editor { get; set; } + public override FieldProperties ToProperties() { - return SimpleMapper.Map(this, new TagsFieldProperties()); + var result = SimpleMapper.Map(this, new TagsFieldProperties()); + + if (AllowedValues != null) + { + result.AllowedValues = ImmutableList.Create(AllowedValues); + } + + return result; } } } diff --git a/src/Squidex/app/features/content/shared/field-editor.component.html b/src/Squidex/app/features/content/shared/field-editor.component.html index abdffb13b..839cc3d84 100644 --- a/src/Squidex/app/features/content/shared/field-editor.component.html +++ b/src/Squidex/app/features/content/shared/field-editor.component.html @@ -104,7 +104,19 @@ - + + + + + + + + + + + - Nothing to setup -
\ No newline at end of file +
+ + +
+ + + + Url to your plugin if you use a custom editor. + +
+
+
+ + +
+ + + + Define the placeholder for the input control. + +
+
+
+ + +
+ + + +
+
+
+ + +
+ +
+
+
\ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts index 68dadab87..260698455 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.ts @@ -5,17 +5,17 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { Component, Input } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { Component, Input, OnInit } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; -import { AssetsFieldPropertiesDto, FieldDto } from '@app/shared'; +import { FieldDto, TagsFieldPropertiesDto } from '@app/shared'; @Component({ selector: 'sqx-tags-ui', styleUrls: ['tags-ui.component.scss'], templateUrl: 'tags-ui.component.html' }) -export class TagsUIComponent { +export class TagsUIComponent implements OnInit { @Input() public editForm: FormGroup; @@ -23,5 +23,15 @@ export class TagsUIComponent { public field: FieldDto; @Input() - public properties: AssetsFieldPropertiesDto; + public properties: TagsFieldPropertiesDto; + + public ngOnInit() { + this.editForm.setControl('editor', + new FormControl(this.properties.editor, [ + Validators.required + ])); + + this.editForm.setControl('allowedValues', + new FormControl(this.properties.allowedValues)); + } } \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/forms/checkbox-group.component.html b/src/Squidex/app/framework/angular/forms/checkbox-group.component.html new file mode 100644 index 000000000..0f2a18bc1 --- /dev/null +++ b/src/Squidex/app/framework/angular/forms/checkbox-group.component.html @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/forms/checkbox-group.component.scss b/src/Squidex/app/framework/angular/forms/checkbox-group.component.scss new file mode 100644 index 000000000..c30feb8f0 --- /dev/null +++ b/src/Squidex/app/framework/angular/forms/checkbox-group.component.scss @@ -0,0 +1,12 @@ +@import '_mixins'; +@import '_vars'; + +.form-check { + display: inline-block; + margin-left: 0; + margin-right: 1rem; +} + +.form-check-input { + margin-top: .4rem; +} \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/forms/checkbox-group.component.ts b/src/Squidex/app/framework/angular/forms/checkbox-group.component.ts new file mode 100644 index 000000000..a8d3b4ac3 --- /dev/null +++ b/src/Squidex/app/framework/angular/forms/checkbox-group.component.ts @@ -0,0 +1,79 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; + +import { Types } from '@app/framework/internal'; +import { MathHelper } from '@app/shared'; + +export const SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CheckboxGroupComponent), multi: true +}; + +@Component({ + selector: 'sqx-checkbox-group', + styleUrls: ['./checkbox-group.component.scss'], + templateUrl: './checkbox-group.component.html', + providers: [SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckboxGroupComponent implements ControlValueAccessor { + private callChange = (v: any) => { /* NOOP */ }; + private callTouched = () => { /* NOOP */ }; + private checkedValues: string[] = []; + + @Input() + public values: string[] = []; + + public isDisabled = false; + + public control = MathHelper.guid(); + + constructor( + private readonly changeDetector: ChangeDetectorRef + ) { + } + + public writeValue(obj: any) { + this.checkedValues = Types.isArrayOfString(obj) ? obj.filter(x => this.values.indexOf(x) >= 0) : []; + + this.changeDetector.markForCheck(); + } + + public setDisabledState(isDisabled: boolean): void { + this.isDisabled = isDisabled; + + this.changeDetector.markForCheck(); + } + + public registerOnChange(fn: any) { + this.callChange = fn; + } + + public registerOnTouched(fn: any) { + this.callTouched = fn; + } + + public blur() { + this.callTouched(); + } + + public check(isChecked: boolean, value: string) { + if (isChecked) { + this.checkedValues = [value, ...this.checkedValues]; + } else { + this.checkedValues = this.checkedValues.filter(x => x !== value); + } + + this.callChange(this.checkedValues); + } + + public isChecked(value: string) { + return this.checkedValues.indexOf(value) >= 0; + } +} diff --git a/src/Squidex/app/framework/angular/forms/control-errors.component.ts b/src/Squidex/app/framework/angular/forms/control-errors.component.ts index e31f1f901..caeb9e437 100644 --- a/src/Squidex/app/framework/angular/forms/control-errors.component.ts +++ b/src/Squidex/app/framework/angular/forms/control-errors.component.ts @@ -22,7 +22,8 @@ const DEFAULT_ERRORS: { [key: string]: string } = { match: '{message}', validdatetime: '{field} is not a valid date time', validnumber: '{field} is not a valid number.', - validvalues: '{field} is not a valid value.' + validvalues: '{field} is not a valid value.', + validarrayvalues: '{field} contains an invalid value.' }; @Component({ diff --git a/src/Squidex/app/framework/angular/forms/dropdown.component.html b/src/Squidex/app/framework/angular/forms/dropdown.component.html deleted file mode 100644 index 7659f0b7c..000000000 --- a/src/Squidex/app/framework/angular/forms/dropdown.component.html +++ /dev/null @@ -1,26 +0,0 @@ - -
- - -
- {{selectedItem}} - - -
- - -
- -
-
-
- {{item}} - - -
-
-
-
\ No newline at end of file diff --git a/src/Squidex/app/framework/angular/forms/dropdown.component.scss b/src/Squidex/app/framework/angular/forms/dropdown.component.scss deleted file mode 100644 index 2b7ec23c4..000000000 --- a/src/Squidex/app/framework/angular/forms/dropdown.component.scss +++ /dev/null @@ -1,38 +0,0 @@ -@import '_mixins'; -@import '_vars'; - -$color-input-disabled: #eef1f4; - -.form-control { - & { - width: 100%; - } - - &[readonly] { - background: $color-input-background; - } - - &:disabled { - background: $color-input-disabled; - } -} - -.selection { - & { - position: relative; - overflow: hidden; - } - - .control-dropdown-item { - @include absolute(0, 1rem, 0, 0); - pointer-events: none; - } - - .icon-caret-down { - @include absolute(30%, .4rem, auto, auto); - cursor: pointer; - font-size: .9rem; - font-weight: normal; - pointer-events: none; - } -} \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/forms/dropdown.component.ts b/src/Squidex/app/framework/angular/forms/dropdown.component.ts deleted file mode 100644 index 1547138f1..000000000 --- a/src/Squidex/app/framework/angular/forms/dropdown.component.ts +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Squidex Headless CMS - * - * @license - * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. - */ - -import { AfterContentInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, forwardRef, Input, QueryList, TemplateRef } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; - -const KEY_ENTER = 13; -const KEY_ESCAPE = 27; -const KEY_UP = 38; -const KEY_DOWN = 40; - -import { ModalModel } from '@app/framework/internal'; - -export const SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DropdownComponent), multi: true -}; - -@Component({ - selector: 'sqx-dropdown', - styleUrls: ['./dropdown.component.scss'], - templateUrl: './dropdown.component.html', - providers: [SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR], - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class DropdownComponent implements AfterContentInit, ControlValueAccessor { - private callChange = (v: any) => { /* NOOP */ }; - private callTouched = () => { /* NOOP */ }; - - @Input() - public items: any[] = []; - - @ContentChildren(TemplateRef) - public templates: QueryList; - - public dropdown = new ModalModel(); - - public selectedItem: any; - public selectedIndex = -1; - public selectionTemplate: TemplateRef; - - public itemTemplate: TemplateRef; - - public isDisabled = false; - - constructor( - private readonly changeDetector: ChangeDetectorRef - ) { - } - - public ngAfterContentInit() { - if (this.templates.length === 1) { - this.itemTemplate = this.selectionTemplate = this.templates.first; - } else { - this.templates.forEach(template => { - if (template.name === 'selection') { - this.selectionTemplate = template; - } else { - this.itemTemplate = template; - } - }); - } - } - - public writeValue(obj: any) { - this.selectIndex(this.items && obj ? this.items.indexOf(obj) : 0); - - this.changeDetector.markForCheck(); - } - - public setDisabledState(isDisabled: boolean): void { - this.isDisabled = isDisabled; - - this.changeDetector.markForCheck(); - } - - public registerOnChange(fn: any) { - this.callChange = fn; - } - - public registerOnTouched(fn: any) { - this.callTouched = fn; - } - - public onKeyDown(event: KeyboardEvent) { - switch (event.keyCode) { - case KEY_UP: - this.up(); - return false; - case KEY_DOWN: - this.down(); - return false; - case KEY_ESCAPE: - case KEY_ENTER: - if (this.dropdown.isOpen) { - this.close(); - return false; - } - } - - return true; - } - - public open() { - this.dropdown.show(); - this.callTouched(); - } - - public selectIndexAndClose(selectedIndex: number) { - this.selectIndex(selectedIndex); - this.close(); - } - - private close() { - this.dropdown.hide(); - } - - private up() { - this.selectIndex(this.selectedIndex - 1); - } - - private down() { - this.selectIndex(this.selectedIndex + 1); - } - - private selectIndex(selectedIndex: number) { - if (selectedIndex < 0) { - selectedIndex = 0; - } - - const items = this.items || []; - - if (selectedIndex >= items.length) { - selectedIndex = items.length - 1; - } - - const value = items[selectedIndex]; - - if (value !== this.selectedItem) { - this.selectedIndex = selectedIndex; - this.selectedItem = value; - - this.callChange(value); - } - } -} \ No newline at end of file diff --git a/src/Squidex/app/framework/angular/forms/validators.spec.ts b/src/Squidex/app/framework/angular/forms/validators.spec.ts index 3624fb416..5a9126443 100644 --- a/src/Squidex/app/framework/angular/forms/validators.spec.ts +++ b/src/Squidex/app/framework/angular/forms/validators.spec.ts @@ -101,6 +101,30 @@ describe('ValidatorsEx.validValues', () => { }); }); +describe('ValidatorsEx.validArrayValues', () => { + it('should return null validator if values not defined', () => { + const validator = ValidatorsEx.validArrayValues(null!); + + expect(validator).toBe(Validators.nullValidator); + }); + + it('should return null if value is in allowed values', () => { + const input = new FormControl([10, 20]); + + const error = ValidatorsEx.validArrayValues([10, 20, 30])(input); + + expect(error).toBeNull(); + }); + + it('should return error if value is not in allowed values', () => { + const input = new FormControl([50]); + + const error = ValidatorsEx.validArrayValues([10, 20, 30])(input); + + expect(error.validarrayvalues).toBeDefined(); + }); +}); + describe('ValidatorsEx.match', () => { it('should revalidate if other control changes', () => { const validator = ValidatorsEx.match('password', 'Passwords are not the same.'); diff --git a/src/Squidex/app/framework/angular/forms/validators.ts b/src/Squidex/app/framework/angular/forms/validators.ts index 3bbd8831f..32c6557bf 100644 --- a/src/Squidex/app/framework/angular/forms/validators.ts +++ b/src/Squidex/app/framework/angular/forms/validators.ts @@ -125,6 +125,26 @@ export module ValidatorsEx { }; } + export function validArrayValues(values: T[]): ValidatorFn { + if (!values) { + return Validators.nullValidator; + } + + return (control: AbstractControl) => { + const ns: T[] = control.value; + + if (ns) { + for (let n of ns) { + if (values.indexOf(n) < 0) { + return { validarrayvalues: false }; + } + } + } + + return null; + }; + } + export function noop(): ValidatorFn { return () => { return null; diff --git a/src/Squidex/app/framework/declarations.ts b/src/Squidex/app/framework/declarations.ts index 8537ff51c..5c2e813be 100644 --- a/src/Squidex/app/framework/declarations.ts +++ b/src/Squidex/app/framework/declarations.ts @@ -6,12 +6,12 @@ */ export * from './angular/forms/autocomplete.component'; +export * from './angular/forms/checkbox-group.component'; export * from './angular/forms/code-editor.component'; export * from './angular/forms/confirm-click.directive'; export * from './angular/forms/control-errors.component'; export * from './angular/forms/copy.directive'; export * from './angular/forms/date-time-editor.component'; -export * from './angular/forms/dropdown.component'; export * from './angular/forms/file-drop.directive'; export * from './angular/forms/focus-on-init.directive'; export * from './angular/forms/form-error.component'; diff --git a/src/Squidex/app/framework/module.ts b/src/Squidex/app/framework/module.ts index 8e4d0404d..afaa033b4 100644 --- a/src/Squidex/app/framework/module.ts +++ b/src/Squidex/app/framework/module.ts @@ -15,6 +15,7 @@ import { AutocompleteComponent, CachingInterceptor, CanDeactivateGuard, + CheckboxGroupComponent, ClipboardService, CodeEditorComponent, ConfirmClickDirective, @@ -28,7 +29,6 @@ import { DialogRendererComponent, DialogService, DisplayNamePipe, - DropdownComponent, DurationPipe, FileDropDirective, FileSizePipe, @@ -92,6 +92,7 @@ import { ], declarations: [ AutocompleteComponent, + CheckboxGroupComponent, ConfirmClickDirective, ControlErrorsComponent, CodeEditorComponent, @@ -103,7 +104,6 @@ import { DayPipe, DialogRendererComponent, DisplayNamePipe, - DropdownComponent, DurationPipe, FileDropDirective, FileSizePipe, @@ -152,6 +152,7 @@ import { ], exports: [ AutocompleteComponent, + CheckboxGroupComponent, CodeEditorComponent, CommonModule, ConfirmClickDirective, @@ -164,7 +165,6 @@ import { DayPipe, DialogRendererComponent, DisplayNamePipe, - DropdownComponent, DurationPipe, FileDropDirective, FileSizePipe, diff --git a/src/Squidex/app/shared/services/schemas.types.ts b/src/Squidex/app/shared/services/schemas.types.ts index 17f759351..8ec7a5a6a 100644 --- a/src/Squidex/app/shared/services/schemas.types.ts +++ b/src/Squidex/app/shared/services/schemas.types.ts @@ -73,7 +73,7 @@ export function createProperties(fieldType: string, values: Object | null = null properties = new StringFieldPropertiesDto('Input'); break; case 'Tags': - properties = new TagsFieldPropertiesDto(); + properties = new TagsFieldPropertiesDto('Tags'); break; default: throw 'Invalid properties type'; @@ -302,11 +302,12 @@ export class TagsFieldPropertiesDto extends FieldPropertiesDto { public readonly minItems?: number; public readonly maxItems?: number; + public readonly allowedValues?: string[]; - constructor( + constructor(editor: string, props?: Partial ) { - super('Default', props); + super('Tags', props); } public accept(visitor: FieldPropertiesVisitor): T { diff --git a/src/Squidex/app/shared/state/contents.forms.spec.ts b/src/Squidex/app/shared/state/contents.forms.spec.ts index 61da6789d..2a72eab7d 100644 --- a/src/Squidex/app/shared/state/contents.forms.spec.ts +++ b/src/Squidex/app/shared/state/contents.forms.spec.ts @@ -166,7 +166,7 @@ describe('AssetsField', () => { }); describe('TagsField', () => { - const field = createField(new TagsFieldPropertiesDto({ isRequired: true, minItems: 1, maxItems: 5 })); + const field = createField(new TagsFieldPropertiesDto('Tags', { isRequired: true, minItems: 1, maxItems: 5 })); it('should create validators', () => { expect(FieldValidatorsFactory.createValidators(field, false).length).toBe(3); diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index 74cb686d7..9d01a9c1c 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -250,6 +250,12 @@ export class FieldValidatorsFactory implements FieldPropertiesVisitor 0) { + const values: (string | null)[] = properties.allowedValues; + + validators.push(ValidatorsEx.validArrayValues(values)); + } + return validators; } diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index ddaa0218e..7bccee9a6 100644 --- a/src/Squidex/app/theme/icomoon/demo.html +++ b/src/Squidex/app/theme/icomoon/demo.html @@ -9,7 +9,7 @@
-

Font Name: icomoon (Glyphs: 101)

+

Font Name: icomoon (Glyphs: 102)

Grid Size: 24

@@ -1372,6 +1372,22 @@

Grid Size: 14

+
+
+ + + + icon-control-Checkboxes +
+
+ + +
+
+ liga: + +
+
diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 9b248387b6f8b141299da2579e0214076421012c..65d6a6ba58180fc3638a0464a9354bdd786741aa 100644 GIT binary patch delta 456 zcmexzit)x7Mz)AF28J!E6WPpIN)vJ_Cpwf19$;W#*aO4~$+?LIw{36zn|MN|eq)*1 zR0amd2@DMJ4H>D4DI(LY0~r_+1%T?zGJpb{Osv^Jz6X%6l95|d(d{XA1IW(->RFMK zpPb12=Cuw3L$U}^{#tHgMFB%2V-%482FO>)OUzB3>Bae*fgyzlsJ^Wrzqo{f87RY$ zIt3)pz|72ec5(`1H)GP|4~)vJa|Pn~7i^YbDveg)Vqo~corQsUI|DC+G=mz07K0vx z5rY|n6@wjv6VR;5mAulL%!+Jc;)+IQrY35Pf{KEy#-hs1XtXd;jIm+z2VRL7?!U8S zc?6l#xcT}2@G~0!`*ZcGJ_@DX(7?>X&jpm{=HmZ%2F{wrBg+NiF#G;H%V=zH<)1l- z*1yV>1*Wes2{df(j16a&smw_zjpw)d%D~M6@+89znd%G}J^4?9Ib+sllf(s#lP@G) kmz2^wpkJeZ04U7}#953H3}PUq3`~;~Q-wF5PhQFh0FJ|a{{R30 delta 280 zcmca{hVjcOMz)ev28IhM6WPpI?#Jj^OkS8GGBG4sa6bbB!yX_`NX|_xxNURm_rw!2 z^{lh|ycif5ConL?Ey+ktOc80haUZC}1gOp|11P}B#F_=<=K%RC8M!4D?Ve&cfPA2O z#w9uV$%$90URyCRB!Sdl$xW;%U}#{BVqi$-0P+>`5_3~$dU5^+@-=|!+Y0iFOBk4e zG7KpjK=KUC%#3Fyr!aOiCQkmqsLVP?AeMjrW(lU!=*^jN!OSuidNKFo`E9;3aI=6k zG29UL(udKLZzP&CW^NWpTEIAYOY&vWAbmdlAO=RDbS7g2gBVB|1Jh*3G~vygQ + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index 05f1693ef32269165b2fb0f78ca2f7fdc4a28e9c..b79c68b236ec999fc8cec640e779aab48a14ede7 100644 GIT binary patch delta 488 zcmca`l5xvv#(D-u1_lOhh6V;^1_S?KeItG$-UC39JwTk0oSRs1+xFH!1_nkMAU`KP zvA6(83jp~YK$;^xr!sA0nc7q!e*yzTd_zWRVv5Lg>p%vEM4%c5vkagBClhNnknaKH zt7PPsRCIfa-2n1)fO=Ns2&X~1%Lc#*Z$vR2b`K9y@=-22U07`>mHET0p@*ze5M0k4x delta 300 zcmdmTn(@L(#(D-u1_lOhh6V;^1_S?KeItG$-u*z4JwTk0oSRs1+ve791_nkMAU`KP zvA6(83jp~YK$;^xr!tLocApoJKY@WEZb?RJVv0!1jr%~YCO~oyea3wdfqJW`+F^Yj9nFGjI$V<#ko$191 zbU?BOP(xcmesKu{Gf;*hWdlf_ftmTt!~@-oiIaU8m09Nq#PZMIT*6oyz4>TtFtdz> zUd;V?ew(ih+$0M(d*u*h`lzzm=uP;3g2 zuL8oHOsv@%xg`}qu^mADD?qs0Q|v}gelk#o4 zj8S=sxv4<02%yF`5T5D9`MV&$xCH2n2XJ-FKo&Fe*~vVN-Hb_-XD}+W&J~E`U$FTA zV`;Pk7X!op?JNw;+ZlKnq#4v0v>5aljDRk-Vz6Uy0vb74kypB&S&>alT+ztP)I^O@ zP*IT8SX7xAjTQ!qF*Y!zar5(Y|D6RSnF_%aH%v&DM-a^X!_R2^@6Xk%`Y4okLjyAl zKNmgJ}J$Oj%(13X?#?X2aNUW|_*Igwl9^ zo39MqEI|Ja{ delta 324 zcmZoT!#L*@qe!{Gn;Qco0}!OjFmQwDlnWC@wCndL=Oz{~Ffe8SMRGv+w#}{I>50W4 zu`5762NVmW=TxQv#qKaL#4Q0~*4cet8L5dW3=9bkKs9C{EYfo0eg;qwD7FL0R{>#8 zCf2Ns+>#2Q7*H=GP%q<>c2BVzIr+&zb$&?=Kt&*nu3V{lZIzo?0kk+d1jtta;|9j4 zyu{p8pjZh|V;cz1^y2(okY5bsr~HAdV+OLAna@n-VeDp1oIHb3nRSjpEdTt?2N+AE zHw(rEGs{@$#oUkQxB1Gz%>q=*z;Hv@OCLs0Zb&p|%-p;qaRKAxnB>dcLHd09LEzBJ K+-#R}h!FtJmQm^e diff --git a/src/Squidex/app/theme/icomoon/icons/control-Checkboxes.svg b/src/Squidex/app/theme/icomoon/icons/control-Checkboxes.svg new file mode 100644 index 000000000..a490a8d81 --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/control-Checkboxes.svg @@ -0,0 +1,68 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/selection.json b/src/Squidex/app/theme/icomoon/selection.json index d4997ec93..afe317112 100644 --- a/src/Squidex/app/theme/icomoon/selection.json +++ b/src/Squidex/app/theme/icomoon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":0,"setId":6,"iconIdx":0},{"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":1,"id":0,"name":"comments","prevSize":24,"code":59743},"setIdx":0,"setId":6,"iconIdx":1},{"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":2,"prevSize":24,"code":59739,"name":"backup"},"setIdx":5,"setId":1,"iconIdx":21},{"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":0,"prevSize":24,"code":59738,"name":"support"},"setIdx":5,"setId":1,"iconIdx":22},{"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":0,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":5,"setId":1,"iconIdx":23},{"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":0,"prevSize":24,"code":59710,"name":"download"},"setIdx":5,"setId":1,"iconIdx":24},{"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":0,"prevSize":32,"code":59737,"name":"spinner2"},"setIdx":1,"setId":5,"iconIdx":0},{"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":2,"prevSize":32,"code":59741,"name":"star-full"},"setIdx":5,"setId":1,"iconIdx":3},{"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":1,"prevSize":32,"code":59742,"name":"star-empty"},"setIdx":5,"setId":1,"iconIdx":4},{"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":0,"prevSize":32,"code":59740,"name":"twitter"},"setIdx":5,"setId":1,"iconIdx":5},{"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":1,"prevSize":32,"code":59732,"name":"hour-glass"},"setIdx":5,"setId":1,"iconIdx":6},{"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":0,"prevSize":32,"code":59731,"name":"spinner"},"setIdx":5,"setId":1,"iconIdx":7},{"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":0,"prevSize":32,"code":59728,"name":"clock"},"setIdx":5,"setId":1,"iconIdx":8},{"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":0,"name":"bin2","prevSize":32,"code":59650},"setIdx":5,"setId":1,"iconIdx":9},{"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":202,"order":91,"prevSize":32,"code":59850},"setIdx":5,"setId":1,"iconIdx":10},{"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":2,"prevSize":32,"code":59715,"name":"elapsed"},"setIdx":5,"setId":1,"iconIdx":11},{"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":0,"prevSize":32,"code":59707,"name":"google"},"setIdx":5,"setId":1,"iconIdx":12},{"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":0,"prevSize":32,"code":59700,"name":"lock"},"setIdx":5,"setId":1,"iconIdx":13},{"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":1,"prevSize":32,"code":59712,"name":"microsoft"},"setIdx":5,"setId":1,"iconIdx":14},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":1,"prevSize":32,"code":59695,"name":"pause"},"setIdx":5,"setId":1,"iconIdx":15},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":0,"prevSize":32,"code":59696,"name":"play"},"setIdx":5,"setId":1,"iconIdx":16},{"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":2,"prevSize":32,"code":59694,"name":"reset"},"setIdx":5,"setId":1,"iconIdx":17},{"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":1,"prevSize":32,"code":59693,"name":"settings2"},"setIdx":5,"setId":1,"iconIdx":18},{"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":1,"prevSize":32,"code":59716,"name":"timeout"},"setIdx":5,"setId":1,"iconIdx":19},{"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":1,"prevSize":32,"code":59699,"name":"unlocked"},"setIdx":5,"setId":1,"iconIdx":20},{"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":1,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":2,"setId":4,"iconIdx":0},{"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":0,"name":"list","prevSize":20,"code":59726},"setIdx":2,"setId":4,"iconIdx":1},{"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":0,"prevSize":20,"code":59708,"name":"info"},"setIdx":5,"setId":1,"iconIdx":100},{"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":3,"setId":3,"iconIdx":0},{"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"],"attrs":[{}],"width":1344,"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59701,"name":"browser"},"setIdx":5,"setId":1,"iconIdx":97},{"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":0,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":5,"setId":1,"iconIdx":98},{"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":0,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":5,"setId":1,"iconIdx":99},{"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,"grid":0,"tags":["prerender"]},"attrs":[{},{},{}],"properties":{"order":114,"id":1,"name":"prerender","prevSize":32,"code":59724},"setIdx":4,"setId":2,"iconIdx":0},{"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,"grid":0,"tags":["circle"]},"attrs":[{}],"properties":{"order":106,"id":0,"name":"circle","prevSize":32,"code":59729},"setIdx":5,"setId":1,"iconIdx":26},{"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,"grid":0,"tags":["control-Slug"]},"attrs":[{},{}],"properties":{"order":103,"id":0,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":5,"setId":1,"iconIdx":28},{"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,"grid":0,"tags":["Tags"]},"attrs":[{},{},{},{}],"properties":{"order":98,"id":0,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":5,"setId":1,"iconIdx":30},{"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,"grid":0,"tags":["activity"]},"attrs":[{}],"properties":{"order":12,"id":36,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":5,"setId":1,"iconIdx":31},{"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,"grid":0,"tags":["add"]},"attrs":[{}],"properties":{"order":13,"id":35,"name":"add, plus","prevSize":32,"code":59653},"setIdx":5,"setId":1,"iconIdx":32},{"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,"grid":0,"tags":["check-circle"]},"attrs":[{}],"properties":{"order":14,"id":34,"name":"check-circle","prevSize":32,"code":59654},"setIdx":5,"setId":1,"iconIdx":33},{"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,"grid":0,"tags":["check-circle-filled"]},"attrs":[{}],"properties":{"order":27,"id":33,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":5,"setId":1,"iconIdx":34},{"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,"grid":0,"tags":["close"]},"attrs":[{}],"properties":{"order":28,"id":32,"name":"close","prevSize":32,"code":59656},"setIdx":5,"setId":1,"iconIdx":35},{"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,"grid":0,"tags":["content"]},"attrs":[{}],"properties":{"order":37,"id":31,"name":"type-References","prevSize":32,"code":59657},"setIdx":5,"setId":1,"iconIdx":36},{"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,"grid":0,"tags":["control-checkbox"]},"attrs":[{}],"properties":{"order":38,"id":30,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":5,"setId":1,"iconIdx":37},{"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,"grid":0,"tags":["control-dropdown"]},"attrs":[{}],"properties":{"order":39,"id":29,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":5,"setId":1,"iconIdx":38},{"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,"grid":0,"tags":["control-input"]},"attrs":[{}],"properties":{"order":41,"id":28,"name":"control-Input","prevSize":32,"code":59660},"setIdx":5,"setId":1,"iconIdx":39},{"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,"grid":0,"tags":["control-radio"]},"attrs":[{}],"properties":{"order":42,"id":27,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":5,"setId":1,"iconIdx":40},{"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,"grid":0,"tags":["control-textarea"]},"attrs":[{}],"properties":{"order":17,"id":26,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":5,"setId":1,"iconIdx":41},{"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,"grid":0,"tags":["control-toggle"]},"attrs":[{}],"properties":{"order":16,"id":25,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":5,"setId":1,"iconIdx":42},{"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,"grid":0,"tags":["copy"]},"attrs":[{}],"properties":{"order":90,"id":24,"name":"copy","prevSize":32,"code":59664},"setIdx":5,"setId":1,"iconIdx":43},{"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,"grid":0,"tags":["dashboard"]},"attrs":[{},{},{}],"properties":{"order":26,"id":23,"name":"dashboard","prevSize":32,"code":59665},"setIdx":5,"setId":1,"iconIdx":44},{"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,"grid":0,"tags":["delete"]},"attrs":[{}],"properties":{"order":29,"id":22,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":5,"setId":1,"iconIdx":45},{"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,"grid":0,"tags":["delete-filled"]},"attrs":[{}],"properties":{"order":36,"id":21,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":5,"setId":1,"iconIdx":46},{"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,"grid":0,"tags":["document-delete"]},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":5,"setId":1,"iconIdx":47},{"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,"grid":0,"tags":["document-disable"]},"attrs":[{}],"properties":{"order":40,"id":19,"name":"document-disable","prevSize":32,"code":59669},"setIdx":5,"setId":1,"iconIdx":48},{"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,"grid":0,"tags":["document-publish"]},"attrs":[{}],"properties":{"order":44,"id":18,"name":"document-publish","prevSize":32,"code":59670},"setIdx":5,"setId":1,"iconIdx":49},{"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,"grid":0,"tags":["drag"]},"attrs":[{}],"properties":{"order":43,"id":17,"name":"drag","prevSize":32,"code":59671},"setIdx":5,"setId":1,"iconIdx":50},{"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,"grid":0,"tags":["filter"]},"attrs":[{}],"properties":{"order":18,"id":16,"name":"filter","prevSize":32,"code":59672},"setIdx":5,"setId":1,"iconIdx":51},{"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":0,"name":"github","prevSize":32,"code":59713},"setIdx":5,"setId":1,"iconIdx":52},{"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,"grid":0,"tags":["help"]},"attrs":[{}],"properties":{"order":19,"id":15,"name":"help","prevSize":32,"code":59673},"setIdx":5,"setId":1,"iconIdx":53},{"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,"grid":0,"tags":["location"]},"attrs":[{}],"properties":{"order":25,"id":13,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":5,"setId":1,"iconIdx":54},{"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,"grid":0,"tags":["logo"]},"attrs":[{}],"properties":{"order":31,"id":12,"name":"logo","prevSize":32,"code":59676},"setIdx":5,"setId":1,"iconIdx":55},{"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,"grid":0,"tags":["media"]},"attrs":[{}],"properties":{"order":30,"id":11,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":5,"setId":1,"iconIdx":56},{"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,"grid":0,"tags":["more"]},"attrs":[{}],"properties":{"order":34,"id":10,"name":"more, dots","prevSize":32,"code":59678},"setIdx":5,"setId":1,"iconIdx":57},{"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,"grid":0,"tags":["pencil"]},"attrs":[{}],"properties":{"order":47,"id":9,"name":"pencil","prevSize":32,"code":59679},"setIdx":5,"setId":1,"iconIdx":58},{"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,"grid":0,"tags":["reference"]},"attrs":[{}],"properties":{"order":45,"id":8,"name":"reference","prevSize":32,"code":59680},"setIdx":5,"setId":1,"iconIdx":59},{"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,"grid":0,"tags":["schemas"]},"attrs":[{},{},{},{}],"properties":{"order":46,"id":7,"name":"schemas","prevSize":32,"code":59681},"setIdx":5,"setId":1,"iconIdx":60},{"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,"grid":0,"tags":["search"]},"attrs":[{}],"properties":{"order":23,"id":6,"name":"search","prevSize":32,"code":59682},"setIdx":5,"setId":1,"iconIdx":61},{"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,"grid":0,"tags":["settings"]},"attrs":[{}],"properties":{"order":22,"id":5,"name":"settings","prevSize":32,"code":59683},"setIdx":5,"setId":1,"iconIdx":62},{"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,"grid":0,"tags":["type-boolean"]},"attrs":[{}],"properties":{"order":21,"id":4,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":5,"setId":1,"iconIdx":63},{"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,"grid":0,"tags":["type-datetime"]},"attrs":[{}],"properties":{"order":24,"id":3,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":5,"setId":1,"iconIdx":64},{"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,"grid":0,"tags":["json"]},"attrs":[{}],"properties":{"order":20,"id":14,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":5,"setId":1,"iconIdx":65},{"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,"grid":0,"tags":["type-number"]},"attrs":[{}],"properties":{"order":32,"id":2,"name":"type-Number","prevSize":32,"code":59686},"setIdx":5,"setId":1,"iconIdx":66},{"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,"grid":0,"tags":["type-string"]},"attrs":[{}],"properties":{"order":48,"id":1,"name":"type-String","prevSize":32,"code":59687},"setIdx":5,"setId":1,"iconIdx":67},{"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,"grid":0,"tags":["user"]},"attrs":[{}],"properties":{"order":33,"id":0,"name":"user","prevSize":32,"code":59688},"setIdx":5,"setId":1,"iconIdx":68},{"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,"grid":14,"tags":["control-Html"]},"attrs":[{},{},{},{}],"properties":{"order":116,"id":217,"name":"control-Html","prevSize":32,"code":59744},"setIdx":5,"setId":1,"iconIdx":0},{"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"],"attrs":[{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["single-content"]},"attrs":[{},{},{},{}],"properties":{"order":112,"id":214,"name":"single-content","prevSize":32,"code":59736},"setIdx":5,"setId":1,"iconIdx":69},{"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"],"attrs":[{},{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["multiple-content"]},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":213,"name":"multiple-content","prevSize":32,"code":59735},"setIdx":5,"setId":1,"iconIdx":70},{"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,"grid":14,"tags":["type-Array"]},"attrs":[{},{},{},{}],"properties":{"order":108,"id":211,"name":"type-Array","prevSize":32,"code":59734},"setIdx":5,"setId":1,"iconIdx":71},{"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"],"attrs":[{}],"width":366,"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59733,"name":"exclamation"},"setIdx":5,"setId":1,"iconIdx":72},{"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,"grid":14,"tags":["orleans"]},"attrs":[{}],"properties":{"order":99,"id":209,"name":"orleans","prevSize":32,"code":59723},"setIdx":5,"setId":1,"iconIdx":75},{"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,"grid":14,"tags":["document-lock"]},"attrs":[{},{}],"properties":{"order":97,"id":208,"name":"document-lock","prevSize":32,"code":59721},"setIdx":5,"setId":1,"iconIdx":76},{"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,"grid":14,"tags":["document-unpublish"]},"attrs":[{},{}],"properties":{"order":96,"id":207,"name":"document-unpublish","prevSize":32,"code":59711},"setIdx":5,"setId":1,"iconIdx":77},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59648,"name":"angle-down"},"setIdx":5,"setId":1,"iconIdx":78},{"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"],"attrs":[{}],"width":384,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":32,"code":59649,"name":"angle-left"},"setIdx":5,"setId":1,"iconIdx":79},{"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"],"attrs":[{}],"width":347,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":0,"prevSize":32,"code":59697,"name":"angle-right"},"setIdx":5,"setId":1,"iconIdx":80},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":2,"prevSize":32,"code":59651,"name":"angle-up"},"setIdx":5,"setId":1,"iconIdx":81},{"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,"grid":14,"tags":["api"]},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":206,"name":"api","prevSize":32,"code":59717},"setIdx":5,"setId":1,"iconIdx":82},{"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,"grid":14,"tags":["assets"]},"attrs":[{},{},{}],"properties":{"order":95,"id":205,"name":"assets","prevSize":32,"code":59720},"setIdx":5,"setId":1,"iconIdx":83},{"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"],"attrs":[{}],"width":951,"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59709,"name":"bug"},"setIdx":5,"setId":1,"iconIdx":84},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":4,"prevSize":32,"code":59692,"name":"caret-down"},"setIdx":5,"setId":1,"iconIdx":85},{"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"],"attrs":[{}],"width":402,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":6,"prevSize":32,"code":59690,"name":"caret-left"},"setIdx":5,"setId":1,"iconIdx":86},{"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"],"attrs":[{}],"width":329,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59689,"name":"caret-right"},"setIdx":5,"setId":1,"iconIdx":87},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":5,"prevSize":32,"code":59691,"name":"caret-up"},"setIdx":5,"setId":1,"iconIdx":88},{"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,"grid":14,"tags":["content"]},"attrs":[{},{},{},{}],"properties":{"order":93,"id":204,"name":"contents, trigger-ContentChanged","prevSize":32,"code":59718},"setIdx":5,"setId":1,"iconIdx":89},{"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,"grid":14,"tags":["control-date"]},"attrs":[{}],"properties":{"order":71,"id":42,"name":"control-Date","prevSize":32,"code":59702},"setIdx":5,"setId":1,"iconIdx":90},{"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,"grid":14,"tags":["control-date-time"]},"attrs":[{}],"properties":{"order":70,"id":41,"name":"control-DateTime","prevSize":32,"code":59703},"setIdx":5,"setId":1,"iconIdx":91},{"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,"grid":14,"tags":["control-Markdown"]},"attrs":[{}],"properties":{"order":72,"id":43,"name":"control-Markdown","prevSize":32,"code":59704},"setIdx":5,"setId":1,"iconIdx":92},{"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":14,"order":83,"prevSize":32,"code":61450},"setIdx":5,"setId":1,"iconIdx":93},{"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":178,"order":89,"prevSize":32,"code":61641},"setIdx":5,"setId":1,"iconIdx":94},{"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,"grid":14,"tags":["user-o"]},"attrs":[{}],"properties":{"order":64,"id":38,"name":"user-o","prevSize":32,"code":59698},"setIdx":5,"setId":1,"iconIdx":95},{"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,"grid":14,"tags":["webhooks"]},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":203,"name":"rules","prevSize":32,"code":59719},"setIdx":5,"setId":1,"iconIdx":96}],"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,"classSelector":".icon","name":"icomoon"},"historySize":100,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":0,"setId":6,"iconIdx":0},{"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":1,"id":0,"name":"comments","prevSize":24,"code":59743},"setIdx":0,"setId":6,"iconIdx":1},{"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":2,"prevSize":24,"code":59739,"name":"backup"},"setIdx":5,"setId":1,"iconIdx":23},{"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":0,"prevSize":24,"code":59738,"name":"support"},"setIdx":5,"setId":1,"iconIdx":24},{"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":0,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":5,"setId":1,"iconIdx":25},{"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":0,"prevSize":24,"code":59710,"name":"download"},"setIdx":5,"setId":1,"iconIdx":26},{"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":0,"prevSize":32,"code":59737,"name":"spinner2"},"setIdx":1,"setId":5,"iconIdx":0},{"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":2,"prevSize":32,"code":59741,"name":"star-full"},"setIdx":5,"setId":1,"iconIdx":5},{"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":1,"prevSize":32,"code":59742,"name":"star-empty"},"setIdx":5,"setId":1,"iconIdx":6},{"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":0,"prevSize":32,"code":59740,"name":"twitter"},"setIdx":5,"setId":1,"iconIdx":7},{"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":1,"prevSize":32,"code":59732,"name":"hour-glass"},"setIdx":5,"setId":1,"iconIdx":8},{"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":0,"prevSize":32,"code":59731,"name":"spinner"},"setIdx":5,"setId":1,"iconIdx":9},{"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":0,"prevSize":32,"code":59728,"name":"clock"},"setIdx":5,"setId":1,"iconIdx":10},{"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":0,"name":"bin2","prevSize":32,"code":59650},"setIdx":5,"setId":1,"iconIdx":11},{"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":202,"order":91,"prevSize":32,"code":59850},"setIdx":5,"setId":1,"iconIdx":12},{"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":2,"prevSize":32,"code":59715,"name":"elapsed"},"setIdx":5,"setId":1,"iconIdx":13},{"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":0,"prevSize":32,"code":59707,"name":"google"},"setIdx":5,"setId":1,"iconIdx":14},{"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":0,"prevSize":32,"code":59700,"name":"lock"},"setIdx":5,"setId":1,"iconIdx":15},{"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":1,"prevSize":32,"code":59712,"name":"microsoft"},"setIdx":5,"setId":1,"iconIdx":16},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":1,"prevSize":32,"code":59695,"name":"pause"},"setIdx":5,"setId":1,"iconIdx":17},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":0,"prevSize":32,"code":59696,"name":"play"},"setIdx":5,"setId":1,"iconIdx":18},{"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":2,"prevSize":32,"code":59694,"name":"reset"},"setIdx":5,"setId":1,"iconIdx":19},{"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":1,"prevSize":32,"code":59693,"name":"settings2"},"setIdx":5,"setId":1,"iconIdx":20},{"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":1,"prevSize":32,"code":59716,"name":"timeout"},"setIdx":5,"setId":1,"iconIdx":21},{"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":1,"prevSize":32,"code":59699,"name":"unlocked"},"setIdx":5,"setId":1,"iconIdx":22},{"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":1,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":2,"setId":4,"iconIdx":0},{"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":0,"name":"list","prevSize":20,"code":59726},"setIdx":2,"setId":4,"iconIdx":1},{"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":0,"prevSize":20,"code":59708,"name":"info"},"setIdx":5,"setId":1,"iconIdx":102},{"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":3,"setId":3,"iconIdx":0},{"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"],"attrs":[{}],"width":1344,"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59701,"name":"browser"},"setIdx":5,"setId":1,"iconIdx":99},{"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":0,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":5,"setId":1,"iconIdx":100},{"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":0,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":5,"setId":1,"iconIdx":101},{"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,"grid":0,"tags":["prerender"]},"attrs":[{},{},{}],"properties":{"order":114,"id":1,"name":"prerender","prevSize":32,"code":59724},"setIdx":4,"setId":2,"iconIdx":0},{"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,"grid":0,"tags":["circle"]},"attrs":[{}],"properties":{"order":106,"id":0,"name":"circle","prevSize":32,"code":59729},"setIdx":5,"setId":1,"iconIdx":28},{"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,"grid":0,"tags":["control-Slug"]},"attrs":[{},{}],"properties":{"order":103,"id":0,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":5,"setId":1,"iconIdx":30},{"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,"grid":0,"tags":["Tags"]},"attrs":[{},{},{},{}],"properties":{"order":98,"id":0,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":5,"setId":1,"iconIdx":32},{"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,"grid":0,"tags":["activity"]},"attrs":[{}],"properties":{"order":12,"id":36,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":5,"setId":1,"iconIdx":33},{"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,"grid":0,"tags":["add"]},"attrs":[{}],"properties":{"order":13,"id":35,"name":"add, plus","prevSize":32,"code":59653},"setIdx":5,"setId":1,"iconIdx":34},{"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,"grid":0,"tags":["check-circle"]},"attrs":[{}],"properties":{"order":14,"id":34,"name":"check-circle","prevSize":32,"code":59654},"setIdx":5,"setId":1,"iconIdx":35},{"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,"grid":0,"tags":["check-circle-filled"]},"attrs":[{}],"properties":{"order":27,"id":33,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":5,"setId":1,"iconIdx":36},{"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,"grid":0,"tags":["close"]},"attrs":[{}],"properties":{"order":28,"id":32,"name":"close","prevSize":32,"code":59656},"setIdx":5,"setId":1,"iconIdx":37},{"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,"grid":0,"tags":["content"]},"attrs":[{}],"properties":{"order":37,"id":31,"name":"type-References","prevSize":32,"code":59657},"setIdx":5,"setId":1,"iconIdx":38},{"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,"grid":0,"tags":["control-checkbox"]},"attrs":[{}],"properties":{"order":38,"id":30,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":5,"setId":1,"iconIdx":39},{"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,"grid":0,"tags":["control-dropdown"]},"attrs":[{}],"properties":{"order":39,"id":29,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":5,"setId":1,"iconIdx":40},{"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,"grid":0,"tags":["control-input"]},"attrs":[{}],"properties":{"order":41,"id":28,"name":"control-Input","prevSize":32,"code":59660},"setIdx":5,"setId":1,"iconIdx":41},{"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,"grid":0,"tags":["control-radio"]},"attrs":[{}],"properties":{"order":42,"id":27,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":5,"setId":1,"iconIdx":42},{"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,"grid":0,"tags":["control-textarea"]},"attrs":[{}],"properties":{"order":17,"id":26,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":5,"setId":1,"iconIdx":43},{"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,"grid":0,"tags":["control-toggle"]},"attrs":[{}],"properties":{"order":16,"id":25,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":5,"setId":1,"iconIdx":44},{"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,"grid":0,"tags":["copy"]},"attrs":[{}],"properties":{"order":90,"id":24,"name":"copy","prevSize":32,"code":59664},"setIdx":5,"setId":1,"iconIdx":45},{"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,"grid":0,"tags":["dashboard"]},"attrs":[{},{},{}],"properties":{"order":26,"id":23,"name":"dashboard","prevSize":32,"code":59665},"setIdx":5,"setId":1,"iconIdx":46},{"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,"grid":0,"tags":["delete"]},"attrs":[{}],"properties":{"order":29,"id":22,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":5,"setId":1,"iconIdx":47},{"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,"grid":0,"tags":["delete-filled"]},"attrs":[{}],"properties":{"order":36,"id":21,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":5,"setId":1,"iconIdx":48},{"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,"grid":0,"tags":["document-delete"]},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":5,"setId":1,"iconIdx":49},{"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,"grid":0,"tags":["document-disable"]},"attrs":[{}],"properties":{"order":40,"id":19,"name":"document-disable","prevSize":32,"code":59669},"setIdx":5,"setId":1,"iconIdx":50},{"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,"grid":0,"tags":["document-publish"]},"attrs":[{}],"properties":{"order":44,"id":18,"name":"document-publish","prevSize":32,"code":59670},"setIdx":5,"setId":1,"iconIdx":51},{"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,"grid":0,"tags":["drag"]},"attrs":[{}],"properties":{"order":43,"id":17,"name":"drag","prevSize":32,"code":59671},"setIdx":5,"setId":1,"iconIdx":52},{"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,"grid":0,"tags":["filter"]},"attrs":[{}],"properties":{"order":18,"id":16,"name":"filter","prevSize":32,"code":59672},"setIdx":5,"setId":1,"iconIdx":53},{"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":0,"name":"github","prevSize":32,"code":59713},"setIdx":5,"setId":1,"iconIdx":54},{"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,"grid":0,"tags":["help"]},"attrs":[{}],"properties":{"order":19,"id":15,"name":"help","prevSize":32,"code":59673},"setIdx":5,"setId":1,"iconIdx":55},{"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,"grid":0,"tags":["location"]},"attrs":[{}],"properties":{"order":25,"id":13,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":5,"setId":1,"iconIdx":56},{"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,"grid":0,"tags":["logo"]},"attrs":[{}],"properties":{"order":31,"id":12,"name":"logo","prevSize":32,"code":59676},"setIdx":5,"setId":1,"iconIdx":57},{"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,"grid":0,"tags":["media"]},"attrs":[{}],"properties":{"order":30,"id":11,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":5,"setId":1,"iconIdx":58},{"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,"grid":0,"tags":["more"]},"attrs":[{}],"properties":{"order":34,"id":10,"name":"more, dots","prevSize":32,"code":59678},"setIdx":5,"setId":1,"iconIdx":59},{"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,"grid":0,"tags":["pencil"]},"attrs":[{}],"properties":{"order":47,"id":9,"name":"pencil","prevSize":32,"code":59679},"setIdx":5,"setId":1,"iconIdx":60},{"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,"grid":0,"tags":["reference"]},"attrs":[{}],"properties":{"order":45,"id":8,"name":"reference","prevSize":32,"code":59680},"setIdx":5,"setId":1,"iconIdx":61},{"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,"grid":0,"tags":["schemas"]},"attrs":[{},{},{},{}],"properties":{"order":46,"id":7,"name":"schemas","prevSize":32,"code":59681},"setIdx":5,"setId":1,"iconIdx":62},{"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,"grid":0,"tags":["search"]},"attrs":[{}],"properties":{"order":23,"id":6,"name":"search","prevSize":32,"code":59682},"setIdx":5,"setId":1,"iconIdx":63},{"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,"grid":0,"tags":["settings"]},"attrs":[{}],"properties":{"order":22,"id":5,"name":"settings","prevSize":32,"code":59683},"setIdx":5,"setId":1,"iconIdx":64},{"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,"grid":0,"tags":["type-boolean"]},"attrs":[{}],"properties":{"order":21,"id":4,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":5,"setId":1,"iconIdx":65},{"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,"grid":0,"tags":["type-datetime"]},"attrs":[{}],"properties":{"order":24,"id":3,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":5,"setId":1,"iconIdx":66},{"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,"grid":0,"tags":["json"]},"attrs":[{}],"properties":{"order":20,"id":14,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":5,"setId":1,"iconIdx":67},{"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,"grid":0,"tags":["type-number"]},"attrs":[{}],"properties":{"order":32,"id":2,"name":"type-Number","prevSize":32,"code":59686},"setIdx":5,"setId":1,"iconIdx":68},{"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,"grid":0,"tags":["type-string"]},"attrs":[{}],"properties":{"order":48,"id":1,"name":"type-String","prevSize":32,"code":59687},"setIdx":5,"setId":1,"iconIdx":69},{"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,"grid":0,"tags":["user"]},"attrs":[{}],"properties":{"order":33,"id":0,"name":"user","prevSize":32,"code":59688},"setIdx":5,"setId":1,"iconIdx":70},{"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,"grid":14,"tags":["control-Checkboxes"]},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":219,"name":"control-Checkboxes","prevSize":32,"code":59746},"setIdx":5,"setId":1,"iconIdx":0},{"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,"grid":14,"tags":["control-Html"]},"attrs":[{},{},{},{}],"properties":{"order":116,"id":217,"name":"control-Html","prevSize":32,"code":59744},"setIdx":5,"setId":1,"iconIdx":2},{"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"],"attrs":[{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["single-content"]},"attrs":[{},{},{},{}],"properties":{"order":112,"id":214,"name":"single-content","prevSize":32,"code":59736},"setIdx":5,"setId":1,"iconIdx":71},{"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"],"attrs":[{},{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["multiple-content"]},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":213,"name":"multiple-content","prevSize":32,"code":59735},"setIdx":5,"setId":1,"iconIdx":72},{"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,"grid":14,"tags":["type-Array"]},"attrs":[{},{},{},{}],"properties":{"order":108,"id":211,"name":"type-Array","prevSize":32,"code":59734},"setIdx":5,"setId":1,"iconIdx":73},{"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"],"attrs":[{}],"width":366,"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59733,"name":"exclamation"},"setIdx":5,"setId":1,"iconIdx":74},{"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,"grid":14,"tags":["orleans"]},"attrs":[{}],"properties":{"order":99,"id":209,"name":"orleans","prevSize":32,"code":59723},"setIdx":5,"setId":1,"iconIdx":77},{"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,"grid":14,"tags":["document-lock"]},"attrs":[{},{}],"properties":{"order":97,"id":208,"name":"document-lock","prevSize":32,"code":59721},"setIdx":5,"setId":1,"iconIdx":78},{"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,"grid":14,"tags":["document-unpublish"]},"attrs":[{},{}],"properties":{"order":96,"id":207,"name":"document-unpublish","prevSize":32,"code":59711},"setIdx":5,"setId":1,"iconIdx":79},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59648,"name":"angle-down"},"setIdx":5,"setId":1,"iconIdx":80},{"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"],"attrs":[{}],"width":384,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":32,"code":59649,"name":"angle-left"},"setIdx":5,"setId":1,"iconIdx":81},{"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"],"attrs":[{}],"width":347,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":0,"prevSize":32,"code":59697,"name":"angle-right"},"setIdx":5,"setId":1,"iconIdx":82},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":2,"prevSize":32,"code":59651,"name":"angle-up"},"setIdx":5,"setId":1,"iconIdx":83},{"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,"grid":14,"tags":["api"]},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":206,"name":"api","prevSize":32,"code":59717},"setIdx":5,"setId":1,"iconIdx":84},{"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,"grid":14,"tags":["assets"]},"attrs":[{},{},{}],"properties":{"order":95,"id":205,"name":"assets","prevSize":32,"code":59720},"setIdx":5,"setId":1,"iconIdx":85},{"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"],"attrs":[{}],"width":951,"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59709,"name":"bug"},"setIdx":5,"setId":1,"iconIdx":86},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":4,"prevSize":32,"code":59692,"name":"caret-down"},"setIdx":5,"setId":1,"iconIdx":87},{"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"],"attrs":[{}],"width":402,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":6,"prevSize":32,"code":59690,"name":"caret-left"},"setIdx":5,"setId":1,"iconIdx":88},{"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"],"attrs":[{}],"width":329,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59689,"name":"caret-right"},"setIdx":5,"setId":1,"iconIdx":89},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":5,"prevSize":32,"code":59691,"name":"caret-up"},"setIdx":5,"setId":1,"iconIdx":90},{"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,"grid":14,"tags":["content"]},"attrs":[{},{},{},{}],"properties":{"order":93,"id":204,"name":"contents, trigger-ContentChanged","prevSize":32,"code":59718},"setIdx":5,"setId":1,"iconIdx":91},{"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,"grid":14,"tags":["control-date"]},"attrs":[{}],"properties":{"order":71,"id":42,"name":"control-Date","prevSize":32,"code":59702},"setIdx":5,"setId":1,"iconIdx":92},{"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,"grid":14,"tags":["control-date-time"]},"attrs":[{}],"properties":{"order":70,"id":41,"name":"control-DateTime","prevSize":32,"code":59703},"setIdx":5,"setId":1,"iconIdx":93},{"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,"grid":14,"tags":["control-Markdown"]},"attrs":[{}],"properties":{"order":72,"id":43,"name":"control-Markdown","prevSize":32,"code":59704},"setIdx":5,"setId":1,"iconIdx":94},{"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":14,"order":83,"prevSize":32,"code":61450},"setIdx":5,"setId":1,"iconIdx":95},{"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":178,"order":89,"prevSize":32,"code":61641},"setIdx":5,"setId":1,"iconIdx":96},{"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,"grid":14,"tags":["user-o"]},"attrs":[{}],"properties":{"order":64,"id":38,"name":"user-o","prevSize":32,"code":59698},"setIdx":5,"setId":1,"iconIdx":97},{"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,"grid":14,"tags":["webhooks"]},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":203,"name":"rules","prevSize":32,"code":59719},"setIdx":5,"setId":1,"iconIdx":98}],"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,"classSelector":".icon","name":"icomoon"},"historySize":100,"gridSize":16}} \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/style.css b/src/Squidex/app/theme/icomoon/style.css index 76fcb8ae6..8f767b9f5 100644 --- a/src/Squidex/app/theme/icomoon/style.css +++ b/src/Squidex/app/theme/icomoon/style.css @@ -1,10 +1,10 @@ @font-face { font-family: 'icomoon'; - src: url('fonts/icomoon.eot?wza1pz'); - src: url('fonts/icomoon.eot?wza1pz#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?wza1pz') format('truetype'), - url('fonts/icomoon.woff?wza1pz') format('woff'), - url('fonts/icomoon.svg?wza1pz#icomoon') format('svg'); + src: url('fonts/icomoon.eot?l0yskd'); + src: url('fonts/icomoon.eot?l0yskd#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?l0yskd') format('truetype'), + url('fonts/icomoon.woff?l0yskd') format('woff'), + url('fonts/icomoon.svg?l0yskd#icomoon') format('svg'); font-weight: normal; font-style: normal; } @@ -276,6 +276,9 @@ .icon-user:before { content: "\e928"; } +.icon-control-Checkboxes:before { + content: "\e962"; +} .icon-control-Html:before { content: "\e960"; } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs index 6b763aadc..e8ec0795c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using FluentAssertions; @@ -102,6 +103,17 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new[] { "Must have not more than 1 item(s)." }); } + [Fact] + public async Task Should_add_errors_if_value_contains_an_not_allowed_values() + { + var sut = Field(new TagsFieldProperties { AllowedValues = ImmutableList.Create("tag-2", "tag-3") }); + + await sut.ValidateAsync(CreateValue("tag-1", "tag-2", null), errors); + + errors.Should().BeEquivalentTo( + new[] { "[1]: Not an allowed value." }); + } + private static JToken CreateValue(params string[] ids) { return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids.OfType().ToArray()); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/TagsFieldPropertiesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/TagsFieldPropertiesTests.cs index 73719d63b..b456d3424 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/TagsFieldPropertiesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/TagsFieldPropertiesTests.cs @@ -29,5 +29,33 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties new ValidationError("Max items must be greater than min items.", "MinItems", "MaxItems") }); } + + [Fact] + public void Should_add_error_if_radio_button_has_no_allowed_values() + { + var sut = new TagsFieldProperties { Editor = TagsFieldEditor.Checkboxes }; + + var errors = FieldPropertiesValidator.Validate(sut).ToList(); + + errors.Should().BeEquivalentTo( + new List + { + new ValidationError("Checkboxes or dropdown list need allowed values.", "AllowedValues") + }); + } + + [Fact] + public void Should_add_error_if_editor_is_not_valid() + { + var sut = new TagsFieldProperties { Editor = (TagsFieldEditor)123 }; + + var errors = FieldPropertiesValidator.Validate(sut).ToList(); + + errors.Should().BeEquivalentTo( + new List + { + new ValidationError("Editor is not a valid value.", "Editor") + }); + } } } From 46e27a82a289b023aa04fbb992f4e7f37bd271b4 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 22 Nov 2018 18:21:22 +0100 Subject: [PATCH 05/33] Bugfixes in usage tracker. --- .../Assets/AssetUsageTracker.cs | 4 +- .../Assets/AssetUsageTracker_EventHandling.cs | 7 ++- .../Guards/FieldPropertiesValidator.cs | 2 +- .../UsageTracking/BackgroundUsageTracker.cs | 27 +++++----- .../UsageTracking/CachingUsageTracker.cs | 16 +++--- .../UsageTracking/IUsageTracker.cs | 6 +-- .../Statistics/UsagesController.cs | 4 +- src/Squidex/Pipeline/ApiCostsFilter.cs | 4 +- .../BackgroundUsageTrackerTests.cs | 49 ++++++++++--------- ...erTests.cs => CachingUsageTrackerTests.cs} | 21 ++++---- .../Pipeline/ApiCostsFilterTests.cs | 12 ++--- 11 files changed, 84 insertions(+), 68 deletions(-) rename tests/Squidex.Infrastructure.Tests/UsageTracking/{ThreadingUsageTrackerTests.cs => CachingUsageTrackerTests.cs} (64%) diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs index 0199126dc..9f0da274a 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs @@ -34,7 +34,9 @@ namespace Squidex.Domain.Apps.Entities.Assets public async Task GetTotalSizeAsync(Guid appId) { - var entries = await usageStore.QueryAsync(appId.ToString(), SummaryDate, SummaryDate); + var key = GetKey(appId); + + var entries = await usageStore.QueryAsync(key, SummaryDate, SummaryDate); return (long)entries.Select(x => x.Counters.Get(CounterTotalSize)).FirstOrDefault(); } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs index dfefeb9e1..5f8bfceae 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs @@ -60,11 +60,16 @@ namespace Squidex.Domain.Apps.Entities.Assets [CounterTotalCount] = count }; - var key = appId.ToString(); + var key = GetKey(appId); return Task.WhenAll( usageStore.TrackUsagesAsync(new UsageUpdate(date, key, Category, counters)), usageStore.TrackUsagesAsync(new UsageUpdate(SummaryDate, key, Category, counters))); } + + private static string GetKey(Guid appId) + { + return $"{appId}_Assets"; + } } } diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs index 3f10076f0..19eea457e 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs @@ -251,7 +251,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards if ((properties.Editor == TagsFieldEditor.Checkboxes || properties.Editor == TagsFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Count == 0)) { - yield return new ValidationError("Chekboxes or dropdown list need allowed values.", + yield return new ValidationError("Checkboxes or dropdown list need allowed values.", nameof(properties.AllowedValues)); } diff --git a/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs index 3dcc82b19..4de7138ad 100644 --- a/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs @@ -96,15 +96,15 @@ namespace Squidex.Infrastructure.UsageTracking } } - public Task TrackAsync(string key, string category, double weight, double elapsedMs) + public Task TrackAsync(Guid appId, string category, double weight, double elapsedMs) { - Guard.NotNull(key, nameof(key)); + var key = GetKey(appId); ThrowIfDisposed(); if (weight > 0) { - category = CleanCategory(category); + category = GetCategory(category); usages.AddOrUpdate((key, category), _ => new Usage(elapsedMs, weight), (k, x) => x.Add(elapsedMs, weight)); } @@ -112,14 +112,14 @@ namespace Squidex.Infrastructure.UsageTracking return TaskHelper.Done; } - public async Task>> QueryAsync(string key, DateTime fromDate, DateTime toDate) + public async Task>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate) { - Guard.NotNull(key, nameof(key)); - ThrowIfDisposed(); + var key = GetKey(appId); + var usagesFlat = await usageRepository.QueryAsync(key, fromDate, toDate); - var usagesByCategory = usagesFlat.GroupBy(x => CleanCategory(x.Category)).ToDictionary(x => x.Key, x => x.ToList()); + var usagesByCategory = usagesFlat.GroupBy(x => GetCategory(x.Category)).ToDictionary(x => x.Key, x => x.ToList()); var result = new Dictionary>(); @@ -167,12 +167,12 @@ namespace Squidex.Infrastructure.UsageTracking return result; } - public async Task GetMonthlyCallsAsync(string key, DateTime date) + public async Task GetMonthlyCallsAsync(Guid appId, DateTime date) { - Guard.NotNull(key, nameof(key)); - ThrowIfDisposed(); + var key = GetKey(appId); + var dateFrom = new DateTime(date.Year, date.Month, 1); var dateTo = dateFrom.AddMonths(1).AddDays(-1); @@ -181,9 +181,14 @@ namespace Squidex.Infrastructure.UsageTracking return originalUsages.Sum(x => (long)x.Counters.Get(CounterTotalCalls)); } - private static string CleanCategory(string category) + private static string GetCategory(string category) { return !string.IsNullOrWhiteSpace(category) ? category.Trim() : "*"; } + + private static string GetKey(Guid appId) + { + return $"{appId}_API"; + } } } diff --git a/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs index 732a48596..4485a6bb2 100644 --- a/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs @@ -25,27 +25,25 @@ namespace Squidex.Infrastructure.UsageTracking this.inner = inner; } - public Task>> QueryAsync(string key, DateTime fromDate, DateTime toDate) + public Task>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate) { - return inner.QueryAsync(key, fromDate, toDate); + return inner.QueryAsync(appId, fromDate, toDate); } - public Task TrackAsync(string key, string category, double weight, double elapsedMs) + public Task TrackAsync(Guid appId, string category, double weight, double elapsedMs) { - return inner.TrackAsync(key, category, weight, elapsedMs); + return inner.TrackAsync(appId, category, weight, elapsedMs); } - public Task GetMonthlyCallsAsync(string key, DateTime date) + public Task GetMonthlyCallsAsync(Guid appId, DateTime date) { - Guard.NotNull(key, nameof(key)); - - var cacheKey = string.Concat(key, date); + var cacheKey = string.Concat(appId, date); return Cache.GetOrCreateAsync(cacheKey, entry => { entry.AbsoluteExpirationRelativeToNow = CacheDuration; - return inner.GetMonthlyCallsAsync(key, date); + return inner.GetMonthlyCallsAsync(appId, date); }); } } diff --git a/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs index f0945d1e1..3fe05d8bf 100644 --- a/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs @@ -13,10 +13,10 @@ namespace Squidex.Infrastructure.UsageTracking { public interface IUsageTracker { - Task TrackAsync(string key, string category, double weight, double elapsedMs); + Task TrackAsync(Guid appId, string category, double weight, double elapsedMs); - Task GetMonthlyCallsAsync(string key, DateTime date); + Task GetMonthlyCallsAsync(Guid appId, DateTime date); - Task>> QueryAsync(string key, DateTime fromDate, DateTime toDate); + Task>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate); } } diff --git a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs index 67d0295df..fdbcc6a4d 100644 --- a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs @@ -58,7 +58,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics [ApiCosts(0)] public async Task GetMonthlyCalls(string app) { - var count = await usageTracker.GetMonthlyCallsAsync(AppId.ToString(), DateTime.Today); + var count = await usageTracker.GetMonthlyCallsAsync(AppId, DateTime.Today); var plan = appPlanProvider.GetPlanForApp(App); @@ -90,7 +90,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics return BadRequest(); } - var entities = await usageTracker.QueryAsync(AppId.ToString(), fromDate.Date, toDate.Date); + var entities = await usageTracker.QueryAsync(AppId, fromDate.Date, toDate.Date); var response = entities.ToDictionary(x => x.Key, x => x.Value.Select(CallsUsageDto.FromUsage).ToList()); diff --git a/src/Squidex/Pipeline/ApiCostsFilter.cs b/src/Squidex/Pipeline/ApiCostsFilter.cs index 9a41b9c9e..0cba6287f 100644 --- a/src/Squidex/Pipeline/ApiCostsFilter.cs +++ b/src/Squidex/Pipeline/ApiCostsFilter.cs @@ -53,7 +53,7 @@ namespace Squidex.Pipeline { var plan = appPlanProvider.GetPlanForApp(appFeature.App); - var usage = await usageTracker.GetMonthlyCallsAsync(appFeature.App.Id.ToString(), DateTime.Today); + var usage = await usageTracker.GetMonthlyCallsAsync(appFeature.App.Id, DateTime.Today); if (plan.MaxApiCalls >= 0 && usage > plan.MaxApiCalls * 1.1) { @@ -72,7 +72,7 @@ namespace Squidex.Pipeline { var elapsedMs = watch.Stop(); - await usageTracker.TrackAsync(appFeature.App.Id.ToString(), context.HttpContext.User.OpenIdClientId(), FilterDefinition.Weight, elapsedMs); + await usageTracker.TrackAsync(appFeature.App.Id, context.HttpContext.User.OpenIdClientId(), FilterDefinition.Weight, elapsedMs); } } else diff --git a/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs b/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs index e3ae304e2..df62c2b69 100644 --- a/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs +++ b/tests/Squidex.Infrastructure.Tests/UsageTracking/BackgroundUsageTrackerTests.cs @@ -19,6 +19,7 @@ namespace Squidex.Infrastructure.UsageTracking { private readonly IUsageRepository usageStore = A.Fake(); private readonly ISemanticLog log = A.Fake(); + private readonly Guid appId = Guid.NewGuid(); private readonly BackgroundUsageTracker sut; public BackgroundUsageTrackerTests() @@ -31,7 +32,7 @@ namespace Squidex.Infrastructure.UsageTracking { sut.Dispose(); - return Assert.ThrowsAsync(() => sut.TrackAsync("MyKey1", "category1", 1, 1000)); + return Assert.ThrowsAsync(() => sut.TrackAsync(appId, "category1", 1, 1000)); } [Fact] @@ -39,7 +40,7 @@ namespace Squidex.Infrastructure.UsageTracking { sut.Dispose(); - return Assert.ThrowsAsync(() => sut.QueryAsync("MyKey1", DateTime.Today, DateTime.Today.AddDays(1))); + return Assert.ThrowsAsync(() => sut.QueryAsync(appId, DateTime.Today, DateTime.Today.AddDays(1))); } [Fact] @@ -47,7 +48,7 @@ namespace Squidex.Infrastructure.UsageTracking { sut.Dispose(); - return Assert.ThrowsAsync(() => sut.GetMonthlyCallsAsync("MyKey1", DateTime.Today)); + return Assert.ThrowsAsync(() => sut.GetMonthlyCallsAsync(appId, DateTime.Today)); } [Fact] @@ -63,10 +64,10 @@ namespace Squidex.Infrastructure.UsageTracking new StoredUsage("category1", date.AddDays(7), Counters(17, 22)) }; - A.CallTo(() => usageStore.QueryAsync("MyKey1", new DateTime(2016, 1, 1), new DateTime(2016, 1, 31))) + A.CallTo(() => usageStore.QueryAsync($"{appId}_API", new DateTime(2016, 1, 1), new DateTime(2016, 1, 31))) .Returns(originalData); - var result = await sut.GetMonthlyCallsAsync("MyKey1", date); + var result = await sut.GetMonthlyCallsAsync(appId, date); Assert.Equal(55, result); } @@ -86,10 +87,10 @@ namespace Squidex.Infrastructure.UsageTracking new StoredUsage(null, f.AddDays(2), Counters(11, 14)) }; - A.CallTo(() => usageStore.QueryAsync("MyKey1", f, t)) + A.CallTo(() => usageStore.QueryAsync($"{appId}_API", f, t)) .Returns(originalData); - var result = await sut.QueryAsync("MyKey1", f, t); + var result = await sut.QueryAsync(appId, f, t); var expected = new Dictionary> { @@ -120,10 +121,10 @@ namespace Squidex.Infrastructure.UsageTracking var f = DateTime.Today; var t = DateTime.Today.AddDays(4); - A.CallTo(() => usageStore.QueryAsync("MyKey1", f, t)) + A.CallTo(() => usageStore.QueryAsync($"{appId}_API", f, t)) .Returns(new List()); - var result = await sut.QueryAsync("MyKey1", f, t); + var result = await sut.QueryAsync(appId, f, t); var expected = new Dictionary> { @@ -143,8 +144,8 @@ namespace Squidex.Infrastructure.UsageTracking [Fact] public async Task Should_not_track_if_weight_less_than_zero() { - await sut.TrackAsync("MyKey1", "MyCategory", -1, 1000); - await sut.TrackAsync("MyKey1", "MyCategory", 0, 1000); + await sut.TrackAsync(appId, "MyCategory", -1, 1000); + await sut.TrackAsync(appId, "MyCategory", 0, 1000); sut.Next(); sut.Dispose(); @@ -156,18 +157,22 @@ namespace Squidex.Infrastructure.UsageTracking [Fact] public async Task Should_aggregate_and_store_on_dispose() { + var appId1 = Guid.NewGuid(); + var appId2 = Guid.NewGuid(); + var appId3 = Guid.NewGuid(); + var today = DateTime.Today; - await sut.TrackAsync("MyKey1", "MyCategory1", 1, 1000); + await sut.TrackAsync(appId1, "MyCategory1", 1, 1000); - await sut.TrackAsync("MyKey2", "MyCategory1", 1.0, 2000); - await sut.TrackAsync("MyKey2", "MyCategory1", 0.5, 3000); + await sut.TrackAsync(appId2, "MyCategory1", 1.0, 2000); + await sut.TrackAsync(appId2, "MyCategory1", 0.5, 3000); - await sut.TrackAsync("MyKey3", "MyCategory1", 0.3, 4000); - await sut.TrackAsync("MyKey3", "MyCategory1", 0.1, 5000); + await sut.TrackAsync(appId3, "MyCategory1", 0.3, 4000); + await sut.TrackAsync(appId3, "MyCategory1", 0.1, 5000); - await sut.TrackAsync("MyKey3", null, 0.5, 2000); - await sut.TrackAsync("MyKey3", null, 0.5, 6000); + await sut.TrackAsync(appId3, null, 0.5, 2000); + await sut.TrackAsync(appId3, null, 0.5, 6000); UsageUpdate[] updates = null; @@ -179,10 +184,10 @@ namespace Squidex.Infrastructure.UsageTracking updates.Should().BeEquivalentTo(new[] { - new UsageUpdate(today, "MyKey1", "MyCategory1", Counters(1.0, 1000)), - new UsageUpdate(today, "MyKey2", "MyCategory1", Counters(1.5, 5000)), - new UsageUpdate(today, "MyKey3", "MyCategory1", Counters(0.4, 9000)), - new UsageUpdate(today, "MyKey3", "*", Counters(1, 8000)) + new UsageUpdate(today, $"{appId1}_API", "MyCategory1", Counters(1.0, 1000)), + new UsageUpdate(today, $"{appId2}_API", "MyCategory1", Counters(1.5, 5000)), + new UsageUpdate(today, $"{appId3}_API", "MyCategory1", Counters(0.4, 9000)), + new UsageUpdate(today, $"{appId3}_API", "*", Counters(1, 8000)) }, o => o.ComparingByMembers()); A.CallTo(() => usageStore.TrackUsagesAsync(A.Ignored)) diff --git a/tests/Squidex.Infrastructure.Tests/UsageTracking/ThreadingUsageTrackerTests.cs b/tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs similarity index 64% rename from tests/Squidex.Infrastructure.Tests/UsageTracking/ThreadingUsageTrackerTests.cs rename to tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs index 4a3bc30c9..51fec6632 100644 --- a/tests/Squidex.Infrastructure.Tests/UsageTracking/ThreadingUsageTrackerTests.cs +++ b/tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs @@ -14,13 +14,14 @@ using Xunit; namespace Squidex.Infrastructure.UsageTracking { - public class ThreadingUsageTrackerTests + public class CachingUsageTrackerTests { private readonly MemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); + private readonly Guid appId = Guid.NewGuid(); private readonly IUsageTracker inner = A.Fake(); private readonly IUsageTracker sut; - public ThreadingUsageTrackerTests() + public CachingUsageTrackerTests() { sut = new CachingUsageTracker(inner, cache); } @@ -28,34 +29,34 @@ namespace Squidex.Infrastructure.UsageTracking [Fact] public async Task Should_forward_track_call() { - await sut.TrackAsync("MyKey", "MyCategory", 123, 456); + await sut.TrackAsync(appId, "MyCategory", 123, 456); - A.CallTo(() => inner.TrackAsync("MyKey", "MyCategory", 123, 456)) + A.CallTo(() => inner.TrackAsync(appId, "MyCategory", 123, 456)) .MustHaveHappened(); } [Fact] public async Task Should_forward_query_call() { - await sut.QueryAsync("MyKey", DateTime.MaxValue, DateTime.MinValue); + await sut.QueryAsync(appId, DateTime.MaxValue, DateTime.MinValue); - A.CallTo(() => inner.QueryAsync("MyKey", DateTime.MaxValue, DateTime.MinValue)) + A.CallTo(() => inner.QueryAsync(appId, DateTime.MaxValue, DateTime.MinValue)) .MustHaveHappened(); } [Fact] public async Task Should_cache_monthly_usage() { - A.CallTo(() => inner.GetMonthlyCallsAsync("MyKey", DateTime.Today)) + A.CallTo(() => inner.GetMonthlyCallsAsync(appId, DateTime.Today)) .Returns(100); - var result1 = await sut.GetMonthlyCallsAsync("MyKey", DateTime.Today); - var result2 = await sut.GetMonthlyCallsAsync("MyKey", DateTime.Today); + var result1 = await sut.GetMonthlyCallsAsync(appId, DateTime.Today); + var result2 = await sut.GetMonthlyCallsAsync(appId, DateTime.Today); Assert.Equal(100, result1); Assert.Equal(100, result2); - A.CallTo(() => inner.GetMonthlyCallsAsync("MyKey", DateTime.Today)) + A.CallTo(() => inner.GetMonthlyCallsAsync(appId, DateTime.Today)) .MustHaveHappened(Repeated.Exactly.Once); } } diff --git a/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs b/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs index 161dc6864..2a50055b8 100644 --- a/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs +++ b/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs @@ -57,7 +57,7 @@ namespace Squidex.Pipeline A.CallTo(() => appPlan.MaxApiCalls) .ReturnsLazily(x => apiCallsMax); - A.CallTo(() => usageTracker.GetMonthlyCallsAsync(A.Ignored, DateTime.Today)) + A.CallTo(() => usageTracker.GetMonthlyCallsAsync(A.Ignored, DateTime.Today)) .ReturnsLazily(x => Task.FromResult(apiCallsCurrent)); next = () => @@ -85,7 +85,7 @@ namespace Squidex.Pipeline Assert.Equal(429, (actionContext.Result as StatusCodeResult).StatusCode); Assert.False(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) .MustNotHaveHappened(); } @@ -103,7 +103,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) .MustHaveHappened(); } @@ -121,7 +121,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) .MustHaveHappened(); } @@ -139,7 +139,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) .MustNotHaveHappened(); } @@ -155,7 +155,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) .MustNotHaveHappened(); } From a3f17dc7b08568f55ce38a7050f0cb89842adbbd Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 23 Nov 2018 10:00:59 +0100 Subject: [PATCH 06/33] Tags icon and fixes in usage tracking. --- .../Assets/AssetUsageTracker.cs | 2 +- .../UsageTracking/BackgroundUsageTracker.cs | 22 ++++---- .../UsageTracking/CachingUsageTracker.cs | 20 ++++--- .../UsageTracking/IUsageTracker.cs | 6 +- .../Statistics/UsagesController.cs | 4 +- src/Squidex/Pipeline/ApiCostsFilter.cs | 4 +- .../pages/schema/types/tags-ui.component.html | 2 +- src/Squidex/app/theme/icomoon/demo.html | 18 +++++- .../app/theme/icomoon/fonts/icomoon.eot | Bin 26200 -> 26364 bytes .../app/theme/icomoon/fonts/icomoon.svg | 1 + .../app/theme/icomoon/fonts/icomoon.ttf | Bin 26036 -> 26200 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 26112 -> 26276 bytes src/Squidex/app/theme/icomoon/selection.json | 2 +- src/Squidex/app/theme/icomoon/style.css | 13 +++-- .../BackgroundUsageTrackerTests.cs | 52 +++++++++--------- .../UsageTracking/CachingUsageTrackerTests.cs | 18 +++--- .../Pipeline/ApiCostsFilterTests.cs | 12 ++-- 17 files changed, 102 insertions(+), 74 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs index 9f0da274a..eb6eb6168 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker.cs @@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var enriched = new List(); - var usagesFlat = await usageStore.QueryAsync(appId.ToString(), fromDate, toDate); + var usagesFlat = await usageStore.QueryAsync(GetKey(appId), fromDate, toDate); for (var date = fromDate; date <= toDate; date = date.AddDays(1)) { diff --git a/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs index 4de7138ad..2cb0240f7 100644 --- a/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs @@ -96,9 +96,9 @@ namespace Squidex.Infrastructure.UsageTracking } } - public Task TrackAsync(Guid appId, string category, double weight, double elapsedMs) + public Task TrackAsync(string key, string category, double weight, double elapsedMs) { - var key = GetKey(appId); + key = GetKey(key); ThrowIfDisposed(); @@ -112,11 +112,11 @@ namespace Squidex.Infrastructure.UsageTracking return TaskHelper.Done; } - public async Task>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate) + public async Task>> QueryAsync(string key, DateTime fromDate, DateTime toDate) { - ThrowIfDisposed(); + key = GetKey(key); - var key = GetKey(appId); + ThrowIfDisposed(); var usagesFlat = await usageRepository.QueryAsync(key, fromDate, toDate); var usagesByCategory = usagesFlat.GroupBy(x => GetCategory(x.Category)).ToDictionary(x => x.Key, x => x.ToList()); @@ -167,11 +167,11 @@ namespace Squidex.Infrastructure.UsageTracking return result; } - public async Task GetMonthlyCallsAsync(Guid appId, DateTime date) + public async Task GetMonthlyCallsAsync(string key, DateTime date) { - ThrowIfDisposed(); + key = GetKey(key); - var key = GetKey(appId); + ThrowIfDisposed(); var dateFrom = new DateTime(date.Year, date.Month, 1); var dateTo = dateFrom.AddMonths(1).AddDays(-1); @@ -186,9 +186,11 @@ namespace Squidex.Infrastructure.UsageTracking return !string.IsNullOrWhiteSpace(category) ? category.Trim() : "*"; } - private static string GetKey(Guid appId) + private static string GetKey(string key) { - return $"{appId}_API"; + Guard.NotNull(key, nameof(key)); + + return $"{key}_API"; } } } diff --git a/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs index 4485a6bb2..7998c422a 100644 --- a/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/CachingUsageTracker.cs @@ -25,25 +25,31 @@ namespace Squidex.Infrastructure.UsageTracking this.inner = inner; } - public Task>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate) + public Task>> QueryAsync(string key, DateTime fromDate, DateTime toDate) { - return inner.QueryAsync(appId, fromDate, toDate); + Guard.NotNull(key, nameof(key)); + + return inner.QueryAsync(key, fromDate, toDate); } - public Task TrackAsync(Guid appId, string category, double weight, double elapsedMs) + public Task TrackAsync(string key, string category, double weight, double elapsedMs) { - return inner.TrackAsync(appId, category, weight, elapsedMs); + Guard.NotNull(key, nameof(key)); + + return inner.TrackAsync(key, category, weight, elapsedMs); } - public Task GetMonthlyCallsAsync(Guid appId, DateTime date) + public Task GetMonthlyCallsAsync(string key, DateTime date) { - var cacheKey = string.Concat(appId, date); + Guard.NotNull(key, nameof(key)); + + var cacheKey = string.Concat(key, date); return Cache.GetOrCreateAsync(cacheKey, entry => { entry.AbsoluteExpirationRelativeToNow = CacheDuration; - return inner.GetMonthlyCallsAsync(appId, date); + return inner.GetMonthlyCallsAsync(key, date); }); } } diff --git a/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs b/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs index 3fe05d8bf..f0945d1e1 100644 --- a/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs +++ b/src/Squidex.Infrastructure/UsageTracking/IUsageTracker.cs @@ -13,10 +13,10 @@ namespace Squidex.Infrastructure.UsageTracking { public interface IUsageTracker { - Task TrackAsync(Guid appId, string category, double weight, double elapsedMs); + Task TrackAsync(string key, string category, double weight, double elapsedMs); - Task GetMonthlyCallsAsync(Guid appId, DateTime date); + Task GetMonthlyCallsAsync(string key, DateTime date); - Task>> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate); + Task>> QueryAsync(string key, DateTime fromDate, DateTime toDate); } } diff --git a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs index fdbcc6a4d..67d0295df 100644 --- a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs @@ -58,7 +58,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics [ApiCosts(0)] public async Task GetMonthlyCalls(string app) { - var count = await usageTracker.GetMonthlyCallsAsync(AppId, DateTime.Today); + var count = await usageTracker.GetMonthlyCallsAsync(AppId.ToString(), DateTime.Today); var plan = appPlanProvider.GetPlanForApp(App); @@ -90,7 +90,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics return BadRequest(); } - var entities = await usageTracker.QueryAsync(AppId, fromDate.Date, toDate.Date); + var entities = await usageTracker.QueryAsync(AppId.ToString(), fromDate.Date, toDate.Date); var response = entities.ToDictionary(x => x.Key, x => x.Value.Select(CallsUsageDto.FromUsage).ToList()); diff --git a/src/Squidex/Pipeline/ApiCostsFilter.cs b/src/Squidex/Pipeline/ApiCostsFilter.cs index 0cba6287f..9a41b9c9e 100644 --- a/src/Squidex/Pipeline/ApiCostsFilter.cs +++ b/src/Squidex/Pipeline/ApiCostsFilter.cs @@ -53,7 +53,7 @@ namespace Squidex.Pipeline { var plan = appPlanProvider.GetPlanForApp(appFeature.App); - var usage = await usageTracker.GetMonthlyCallsAsync(appFeature.App.Id, DateTime.Today); + var usage = await usageTracker.GetMonthlyCallsAsync(appFeature.App.Id.ToString(), DateTime.Today); if (plan.MaxApiCalls >= 0 && usage > plan.MaxApiCalls * 1.1) { @@ -72,7 +72,7 @@ namespace Squidex.Pipeline { var elapsedMs = watch.Stop(); - await usageTracker.TrackAsync(appFeature.App.Id, context.HttpContext.User.OpenIdClientId(), FilterDefinition.Weight, elapsedMs); + await usageTracker.TrackAsync(appFeature.App.Id.ToString(), context.HttpContext.User.OpenIdClientId(), FilterDefinition.Weight, elapsedMs); } } else diff --git a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html index 17717042d..750a2187a 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/types/tags-ui.component.html @@ -28,7 +28,7 @@ diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index 7bccee9a6..07508b600 100644 --- a/src/Squidex/app/theme/icomoon/demo.html +++ b/src/Squidex/app/theme/icomoon/demo.html @@ -9,7 +9,7 @@
-

Font Name: icomoon (Glyphs: 102)

+

Font Name: icomoon (Glyphs: 103)

Grid Size: 24

@@ -1372,6 +1372,22 @@

Grid Size: 14

+
+
+ + + + icon-control-Tags +
+
+ + +
+
+ liga: + +
+
diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 65d6a6ba58180fc3638a0464a9354bdd786741aa..72467e8885537c0ecc2039befc1652854caf5d91 100644 GIT binary patch delta 446 zcmca{hVjo?Mz%j`3=9!z6WPpIR!)9-ck;p%k%=M6f(IEG81?{hLUL|m!EL+Sj1y1D z)c@uzTF1b^H~}cEkdd00A~I9yCIds_2B12#44?of6Kf8T{{qNY$;d6K=-(@z$-t1r z1Jtu7CqFrnd9l<528QGvK=~WFi4_G5O^i_t3@JeK7!>jnb5mz}asCGKf#xx`733F} zFfapU7}6|2@(j$(jOQk&Fm^L0PyWED%sNjXo`2zH38ui9dS-@+42mpV%$5wi42lfq zK;5RsrY362N^GKn;^uVWY@allnw#6jdw~Y(+LP-Zy|{5D@1xLH7+ zVz?ojuLGke-$*oP%-$@JG?$UNgkj?3HOY6yv-Ab@&lm_WFai~2Ge$6offO?^O?FHZ K-n=D4DI(LY0~r_+1%T?zGJpb{Osv^Jz6X%6l95|d(d{XA1IW(->RFMK zpPb12=Cuw3L$U}^{#tHgMFB%2V-%482FO>)OUzB3>Bae*fgyzlsJ^Wrzqo{f87RY$ zIt3)pz|72ec5(`1H)GP|4~)vJa|Pn~7i^Yb3XIvz86V6nQ<;-c8qaU@m4TZDq>15% pOmzl~o?MY+&X~1%L(*Kv$$=?%cn|2;=pO(|G6HedW~ + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index b79c68b236ec999fc8cec640e779aab48a14ede7..ec3e7d32406bfad08cd4a0bc6f506a58a2d88664 100644 GIT binary patch delta 466 zcmdmTn(@XN#(D-u1_lOhh6V;^1_S?KeItG$-h)7qJwTk0oSRs1+wL|{1)~g*pOcvfP)UzfhKiM&nd9l<528QGvKm|8)6DtZBni!)P7*c=+GAQIF=BCc{ z;`|Nd0}W(sE66V{0Xh^2(kwvo49v{uCLZW!OrGq+sLVP~AfA8W<`Txhn0jW0i42M? zT+EgXybOvA=0Lrs#-=7}%1Ugag5u_a%*sk?wu~lb){Le=Az4NdF>6LfJw|OtQDY-9 zc}8|V2-D1-k@0hZiK?neWaMurU0YjSCnvk`a62c)HzJk_*6NCu!jt+$Y!p>26l_H{ zG36RMshXIm{(ZDiej(%Pf3>!{|8#A&!|ndrg)@GZl+l)v+_ni!-Q9dRHk4WB?#sz5 zR delta 302 zcmca{hH=Yj#(D-u1_lOhh6V;^1_S?KeItG$-UC39JwTk0oSRs1+xFH!1_nkMAU`KP zvA6(83jp~YK$;^xr!sA0nc7q!e*yzTd_zWRVv5Lg>p%vEM4%c5vkagBClhNnknaKH zt7PPsRCIfa-2n1)fO=NsYM81vAT3 z<|LHH^V@u7;AR17VYnevodKgKUr97)%-YP8G?#Jm+T=Up2lQ+74*(@Wp^?QH!5{`w Q$iOt&F->^$=9Hz30NVmi5C8xG diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.woff b/src/Squidex/app/theme/icomoon/fonts/icomoon.woff index bee1b19e727c4ca0e2b3c791879b37dbf6e4b4bd..1380b3b1859fefda391edf25c16359142d81652e 100644 GIT binary patch delta 490 zcmZoT!?@%uqe!{Gn;Qco0}!MwVc-VS5feqU>klU9CKfO-FlGRSazOaD-EGG7#A1-x z6(FAjiUrbhD${^scNiEF6hQblXVJQh)Wj49hQvQWHD(|zGE?bh22hZJA;|>DR{>#8 zCf1yc+>#2QSOif28W8T^E1sE?pA1yzm%;*6bOVH$7fW5pO{@S~oC36jK>>`L7^CtM zb5nt0KuZ|gKzODX=kJ32;u4@wTHxxKfh=a`bCY=(yBU)w&tOz$ohJ~_zi{&b#=w|* zW`>CjiY#2rmJGZMiVWsJLrjfLP1KZ?*hB@z%>|j2mDFq*P0XwrO@TtPj3Q#zjEs7W z+Ki&cMq=`e?0gWWnLQ)p=K>Q|Rg=ib-%h%=wz^JEcH!Z6PK<9vEETNP6)lA)^@-Rh zs#qx4ifm%aHFQ!nF;V^dXrcT<#?}97ZFT?Y+G>Z}{j&>a{46P>EhD*Y6PUWYnLjR+ zS?2D`$t&aeZN4&agF*xt9!2P`6?jH$;6tSky}y$6x#vRzXF82J;iS1q_(3}i7gpPkIZ*v*(Uc?P30>s*02 z{so&4Fb2kK-WV6mEK`}2P#Vu~^Ob>{1*n#R;f72#$j@MUvO43b!oA2nI1A&A`9}3b)PwQ(); private readonly ISemanticLog log = A.Fake(); - private readonly Guid appId = Guid.NewGuid(); + private readonly string key = Guid.NewGuid().ToString(); private readonly BackgroundUsageTracker sut; public BackgroundUsageTrackerTests() @@ -32,7 +32,7 @@ namespace Squidex.Infrastructure.UsageTracking { sut.Dispose(); - return Assert.ThrowsAsync(() => sut.TrackAsync(appId, "category1", 1, 1000)); + return Assert.ThrowsAsync(() => sut.TrackAsync(key, "category1", 1, 1000)); } [Fact] @@ -40,7 +40,7 @@ namespace Squidex.Infrastructure.UsageTracking { sut.Dispose(); - return Assert.ThrowsAsync(() => sut.QueryAsync(appId, DateTime.Today, DateTime.Today.AddDays(1))); + return Assert.ThrowsAsync(() => sut.QueryAsync(key, DateTime.Today, DateTime.Today.AddDays(1))); } [Fact] @@ -48,7 +48,7 @@ namespace Squidex.Infrastructure.UsageTracking { sut.Dispose(); - return Assert.ThrowsAsync(() => sut.GetMonthlyCallsAsync(appId, DateTime.Today)); + return Assert.ThrowsAsync(() => sut.GetMonthlyCallsAsync(key, DateTime.Today)); } [Fact] @@ -64,10 +64,10 @@ namespace Squidex.Infrastructure.UsageTracking new StoredUsage("category1", date.AddDays(7), Counters(17, 22)) }; - A.CallTo(() => usageStore.QueryAsync($"{appId}_API", new DateTime(2016, 1, 1), new DateTime(2016, 1, 31))) + A.CallTo(() => usageStore.QueryAsync($"{key}_API", new DateTime(2016, 1, 1), new DateTime(2016, 1, 31))) .Returns(originalData); - var result = await sut.GetMonthlyCallsAsync(appId, date); + var result = await sut.GetMonthlyCallsAsync(key, date); Assert.Equal(55, result); } @@ -87,10 +87,10 @@ namespace Squidex.Infrastructure.UsageTracking new StoredUsage(null, f.AddDays(2), Counters(11, 14)) }; - A.CallTo(() => usageStore.QueryAsync($"{appId}_API", f, t)) + A.CallTo(() => usageStore.QueryAsync($"{key}_API", f, t)) .Returns(originalData); - var result = await sut.QueryAsync(appId, f, t); + var result = await sut.QueryAsync(key, f, t); var expected = new Dictionary> { @@ -121,10 +121,10 @@ namespace Squidex.Infrastructure.UsageTracking var f = DateTime.Today; var t = DateTime.Today.AddDays(4); - A.CallTo(() => usageStore.QueryAsync($"{appId}_API", f, t)) + A.CallTo(() => usageStore.QueryAsync($"{key}_API", f, t)) .Returns(new List()); - var result = await sut.QueryAsync(appId, f, t); + var result = await sut.QueryAsync(key, f, t); var expected = new Dictionary> { @@ -144,8 +144,8 @@ namespace Squidex.Infrastructure.UsageTracking [Fact] public async Task Should_not_track_if_weight_less_than_zero() { - await sut.TrackAsync(appId, "MyCategory", -1, 1000); - await sut.TrackAsync(appId, "MyCategory", 0, 1000); + await sut.TrackAsync(key, "MyCategory", -1, 1000); + await sut.TrackAsync(key, "MyCategory", 0, 1000); sut.Next(); sut.Dispose(); @@ -157,22 +157,22 @@ namespace Squidex.Infrastructure.UsageTracking [Fact] public async Task Should_aggregate_and_store_on_dispose() { - var appId1 = Guid.NewGuid(); - var appId2 = Guid.NewGuid(); - var appId3 = Guid.NewGuid(); + var key1 = Guid.NewGuid().ToString(); + var key2 = Guid.NewGuid().ToString(); + var key3 = Guid.NewGuid().ToString(); var today = DateTime.Today; - await sut.TrackAsync(appId1, "MyCategory1", 1, 1000); + await sut.TrackAsync(key1, "MyCategory1", 1, 1000); - await sut.TrackAsync(appId2, "MyCategory1", 1.0, 2000); - await sut.TrackAsync(appId2, "MyCategory1", 0.5, 3000); + await sut.TrackAsync(key2, "MyCategory1", 1.0, 2000); + await sut.TrackAsync(key2, "MyCategory1", 0.5, 3000); - await sut.TrackAsync(appId3, "MyCategory1", 0.3, 4000); - await sut.TrackAsync(appId3, "MyCategory1", 0.1, 5000); + await sut.TrackAsync(key3, "MyCategory1", 0.3, 4000); + await sut.TrackAsync(key3, "MyCategory1", 0.1, 5000); - await sut.TrackAsync(appId3, null, 0.5, 2000); - await sut.TrackAsync(appId3, null, 0.5, 6000); + await sut.TrackAsync(key3, null, 0.5, 2000); + await sut.TrackAsync(key3, null, 0.5, 6000); UsageUpdate[] updates = null; @@ -184,10 +184,10 @@ namespace Squidex.Infrastructure.UsageTracking updates.Should().BeEquivalentTo(new[] { - new UsageUpdate(today, $"{appId1}_API", "MyCategory1", Counters(1.0, 1000)), - new UsageUpdate(today, $"{appId2}_API", "MyCategory1", Counters(1.5, 5000)), - new UsageUpdate(today, $"{appId3}_API", "MyCategory1", Counters(0.4, 9000)), - new UsageUpdate(today, $"{appId3}_API", "*", Counters(1, 8000)) + new UsageUpdate(today, $"{key1}_API", "MyCategory1", Counters(1.0, 1000)), + new UsageUpdate(today, $"{key2}_API", "MyCategory1", Counters(1.5, 5000)), + new UsageUpdate(today, $"{key3}_API", "MyCategory1", Counters(0.4, 9000)), + new UsageUpdate(today, $"{key3}_API", "*", Counters(1, 8000)) }, o => o.ComparingByMembers()); A.CallTo(() => usageStore.TrackUsagesAsync(A.Ignored)) diff --git a/tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs b/tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs index 51fec6632..4ceb57a93 100644 --- a/tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs +++ b/tests/Squidex.Infrastructure.Tests/UsageTracking/CachingUsageTrackerTests.cs @@ -17,7 +17,7 @@ namespace Squidex.Infrastructure.UsageTracking public class CachingUsageTrackerTests { private readonly MemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); - private readonly Guid appId = Guid.NewGuid(); + private readonly string key = Guid.NewGuid().ToString(); private readonly IUsageTracker inner = A.Fake(); private readonly IUsageTracker sut; @@ -29,34 +29,34 @@ namespace Squidex.Infrastructure.UsageTracking [Fact] public async Task Should_forward_track_call() { - await sut.TrackAsync(appId, "MyCategory", 123, 456); + await sut.TrackAsync(key, "MyCategory", 123, 456); - A.CallTo(() => inner.TrackAsync(appId, "MyCategory", 123, 456)) + A.CallTo(() => inner.TrackAsync(key, "MyCategory", 123, 456)) .MustHaveHappened(); } [Fact] public async Task Should_forward_query_call() { - await sut.QueryAsync(appId, DateTime.MaxValue, DateTime.MinValue); + await sut.QueryAsync(key, DateTime.MaxValue, DateTime.MinValue); - A.CallTo(() => inner.QueryAsync(appId, DateTime.MaxValue, DateTime.MinValue)) + A.CallTo(() => inner.QueryAsync(key, DateTime.MaxValue, DateTime.MinValue)) .MustHaveHappened(); } [Fact] public async Task Should_cache_monthly_usage() { - A.CallTo(() => inner.GetMonthlyCallsAsync(appId, DateTime.Today)) + A.CallTo(() => inner.GetMonthlyCallsAsync(key, DateTime.Today)) .Returns(100); - var result1 = await sut.GetMonthlyCallsAsync(appId, DateTime.Today); - var result2 = await sut.GetMonthlyCallsAsync(appId, DateTime.Today); + var result1 = await sut.GetMonthlyCallsAsync(key, DateTime.Today); + var result2 = await sut.GetMonthlyCallsAsync(key, DateTime.Today); Assert.Equal(100, result1); Assert.Equal(100, result2); - A.CallTo(() => inner.GetMonthlyCallsAsync(appId, DateTime.Today)) + A.CallTo(() => inner.GetMonthlyCallsAsync(key, DateTime.Today)) .MustHaveHappened(Repeated.Exactly.Once); } } diff --git a/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs b/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs index 2a50055b8..161dc6864 100644 --- a/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs +++ b/tests/Squidex.Tests/Pipeline/ApiCostsFilterTests.cs @@ -57,7 +57,7 @@ namespace Squidex.Pipeline A.CallTo(() => appPlan.MaxApiCalls) .ReturnsLazily(x => apiCallsMax); - A.CallTo(() => usageTracker.GetMonthlyCallsAsync(A.Ignored, DateTime.Today)) + A.CallTo(() => usageTracker.GetMonthlyCallsAsync(A.Ignored, DateTime.Today)) .ReturnsLazily(x => Task.FromResult(apiCallsCurrent)); next = () => @@ -85,7 +85,7 @@ namespace Squidex.Pipeline Assert.Equal(429, (actionContext.Result as StatusCodeResult).StatusCode); Assert.False(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) .MustNotHaveHappened(); } @@ -103,7 +103,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) .MustHaveHappened(); } @@ -121,7 +121,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, 13, A.Ignored)) .MustHaveHappened(); } @@ -139,7 +139,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) .MustNotHaveHappened(); } @@ -155,7 +155,7 @@ namespace Squidex.Pipeline Assert.True(isNextCalled); - A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) + A.CallTo(() => usageTracker.TrackAsync(A.Ignored, A.Ignored, A.Ignored, A.Ignored)) .MustNotHaveHappened(); } From 12f6b3ddd24d4c66ffa9c1ad5558758d52c58ce9 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 24 Nov 2018 13:28:47 +0100 Subject: [PATCH 07/33] Minor performance improvements. --- .../Apps/LanguageConfig.cs | 3 +- .../Schemas/ArrayField.cs | 11 +- .../Schemas/ArrayFieldProperties.cs | 6 +- .../Schemas/AssetsFieldProperties.cs | 8 +- .../Schemas/BooleanFieldProperties.cs | 8 +- .../Schemas/DateTimeFieldProperties.cs | 8 +- .../Schemas/FieldProperties.cs | 4 +- .../Schemas/FieldRegistry.cs | 8 +- .../Schemas/Fields.cs | 164 ++++++++---------- .../Schemas/GeolocationFieldProperties.cs | 8 +- .../Schemas/IField.cs | 8 +- .../Schemas/IFieldSettings.cs | 18 ++ .../Schemas/Json/JsonFieldModel.cs | 5 +- .../Schemas/Json/JsonNestedFieldModel.cs | 7 +- .../Schemas/Json/JsonSchemaModel.cs | 66 +++---- .../Schemas/JsonFieldProperties.cs | 8 +- .../Schemas/NestedField.cs | 9 +- .../Schemas/NestedField{T}.cs | 8 +- .../Schemas/NumberFieldProperties.cs | 8 +- .../Schemas/ReferencesFieldProperties.cs | 8 +- .../Schemas/RootField.cs | 9 +- .../Schemas/RootField{T}.cs | 8 +- .../Schemas/StringFieldProperties.cs | 8 +- .../Schemas/TagsFieldProperties.cs | 8 +- .../Contents/GraphQL/CachingGraphQLService.cs | 2 +- .../CollectionExtensions.cs | 26 +++ src/Squidex.Infrastructure/Language.cs | 2 +- .../Log/IArrayWriter.cs | 5 + .../Log/IObjectWriter.cs | 6 + .../Log/IObjectWriterFactory.cs | 16 ++ .../Log/JsonLogWriter.cs | 35 +++- .../Log/JsonLogWriterFactory.cs | 61 +++++++ src/Squidex.Infrastructure/Log/SemanticLog.cs | 38 ++-- .../Security/PermissionSet.cs | 2 +- .../States/Persistence{TSnapshot,TKey}.cs | 3 +- src/Squidex.Infrastructure/ValidationError.cs | 2 +- .../Controllers/Apps/AppClientsController.cs | 3 +- .../Controllers/Apps/AppPatternsController.cs | 2 +- .../Api/Controllers/Apps/AppsController.cs | 3 +- .../Api/Controllers/Apps/Models/AppDto.cs | 3 +- .../Controllers/Apps/Models/AppLanguageDto.cs | 8 +- .../Apps/Models/ContributorsDto.cs | 3 +- .../Api/Controllers/Apps/Models/RoleDto.cs | 5 +- .../Apps/Models/UpdateLanguageDto.cs | 3 +- .../Controllers/Backups/BackupsController.cs | 3 +- .../Comments/Models/CommentsDto.cs | 8 +- .../Contents/ContentsController.cs | 1 + .../EventConsumersController.cs | 2 +- .../Controllers/History/HistoryController.cs | 3 +- .../Languages/LanguagesController.cs | 2 +- .../Controllers/Plans/Models/AppPlansDto.cs | 5 +- .../Converters/RuleTriggerDtoFactory.cs | 2 +- .../Controllers/Rules/Models/RuleEventsDto.cs | 1 + .../Triggers/ContentChangedTriggerDto.cs | 2 +- .../Api/Controllers/Rules/RulesController.cs | 2 +- .../Controllers/Schemas/SchemasController.cs | 3 +- .../Statistics/UsagesController.cs | 5 +- .../Api/Controllers/Users/Models/UserDto.cs | 6 +- .../Frontend/Middlewares/WebpackMiddleware.cs | 2 +- src/Squidex/Config/Domain/LoggingServices.cs | 7 +- src/Squidex/Config/Web/WebExtensions.cs | 1 - .../Pipeline/ApiExceptionFilterAttribute.cs | 2 +- src/Squidex/Pipeline/ETagExtensions.cs | 53 +++++- .../app/theme/icomoon/icons/control-Tags.svg | 75 ++++++++ .../Model/Schemas/FieldRegistryTests.cs | 4 +- .../Apps/RoleExtensionsRests.cs | 3 +- .../Log/JsonLogWriterTests.cs | 10 +- .../Log/SemanticLogAdapterTests.cs | 4 +- .../Log/SemanticLogTests.cs | 29 +++- 69 files changed, 580 insertions(+), 289 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldSettings.cs create mode 100644 src/Squidex.Infrastructure/Log/IObjectWriterFactory.cs create mode 100644 src/Squidex.Infrastructure/Log/JsonLogWriterFactory.cs create mode 100644 src/Squidex/app/theme/icomoon/icons/control-Tags.svg diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs index 9b4374720..05ce64873 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; using System.Linq; using Squidex.Infrastructure; @@ -13,7 +14,7 @@ namespace Squidex.Domain.Apps.Core.Apps { public sealed class LanguageConfig : IFieldPartitionItem { - private static readonly Language[] DefaultFallback = new Language[0]; + private static readonly Language[] DefaultFallback = Array.Empty(); private readonly Language language; private readonly Language[] languageFallbacks; diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayField.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayField.cs index 7a74a39f0..1de894b81 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayField.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayField.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Squidex.Infrastructure; using System; using System.Collections.Generic; using System.Diagnostics.Contracts; @@ -30,11 +31,19 @@ namespace Squidex.Domain.Apps.Core.Schemas get { return fields.ByName; } } - public ArrayField(long id, string name, Partitioning partitioning, ArrayFieldProperties properties) + public ArrayField(long id, string name, Partitioning partitioning, ArrayFieldProperties properties = null, IFieldSettings settings = null) : base(id, name, partitioning, properties) { } + public ArrayField(long id, string name, Partitioning partitioning, NestedField[] fields, ArrayFieldProperties properties = null, IFieldSettings settings = null) + : this(id, name, partitioning, properties) + { + Guard.NotNull(fields, nameof(fields)); + + this.fields = new FieldCollection(fields); + } + [Pure] public ArrayField DeleteField(long fieldId) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayFieldProperties.cs index f3f6100d9..8a970c2af 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayFieldProperties.cs @@ -27,12 +27,12 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IArrayField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Array(id, name, partitioning, this); + return Fields.Array(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { throw new NotSupportedException(); } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs index 62b3be7c1..2e39adc21 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs @@ -47,14 +47,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Assets(id, name, partitioning, this); + return Fields.Assets(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.Assets(id, name, this); + return Fields.Assets(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs index a4a0750a5..435f9c529 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs @@ -28,14 +28,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Boolean(id, name, partitioning, this); + return Fields.Boolean(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.Boolean(id, name, this); + return Fields.Boolean(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs index efbcad12b..3e79836f0 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs @@ -33,14 +33,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.DateTime(id, name, partitioning, this); + return Fields.DateTime(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.DateTime(id, name, this); + return Fields.DateTime(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs index a9c8d0421..59aabc380 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs @@ -21,8 +21,8 @@ namespace Squidex.Domain.Apps.Core.Schemas public abstract T Accept(IFieldVisitor visitor, IField field); - public abstract RootField CreateRootField(long id, string name, Partitioning partitioning); + public abstract RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null); - public abstract NestedField CreateNestedField(long id, string name); + public abstract NestedField CreateNestedField(long id, string name, IFieldSettings settings = null); } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs index 2cc7be0de..cd32ac6b7 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs @@ -42,18 +42,18 @@ namespace Squidex.Domain.Apps.Core.Schemas } } - public RootField CreateRootField(long id, string name, Partitioning partitioning, FieldProperties properties) + public RootField CreateRootField(long id, string name, Partitioning partitioning, FieldProperties properties, IFieldSettings settings = null) { CheckProperties(properties); - return properties.CreateRootField(id, name, partitioning); + return properties.CreateRootField(id, name, partitioning, settings); } - public NestedField CreateNestedField(long id, string name, FieldProperties properties) + public NestedField CreateNestedField(long id, string name, FieldProperties properties, IFieldSettings settings = null) { CheckProperties(properties); - return properties.CreateNestedField(id, name); + return properties.CreateNestedField(id, name, settings); } private void CheckProperties(FieldProperties properties) diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs index de6e49e28..5da91b6a1 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Fields.cs @@ -13,117 +13,107 @@ namespace Squidex.Domain.Apps.Core.Schemas { public static RootField Array(long id, string name, Partitioning partitioning, params NestedField[] fields) { - var result = new ArrayField(id, name, partitioning, new ArrayFieldProperties()); - - if (fields != null) - { - foreach (var field in fields) - { - result = result.AddField(field); - } - } - - return result; + return new ArrayField(id, name, partitioning, fields: fields); } - public static ArrayField Array(long id, string name, Partitioning partitioning, ArrayFieldProperties properties = null) + public static ArrayField Array(long id, string name, Partitioning partitioning, ArrayFieldProperties properties = null, IFieldSettings settings = null) { - return new ArrayField(id, name, partitioning, properties ?? new ArrayFieldProperties()); + return new ArrayField(id, name, partitioning, properties, settings); } - public static RootField Assets(long id, string name, Partitioning partitioning, AssetsFieldProperties properties = null) + public static RootField Assets(long id, string name, Partitioning partitioning, AssetsFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new AssetsFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField Boolean(long id, string name, Partitioning partitioning, BooleanFieldProperties properties = null) + public static RootField Boolean(long id, string name, Partitioning partitioning, BooleanFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new BooleanFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField DateTime(long id, string name, Partitioning partitioning, DateTimeFieldProperties properties = null) + public static RootField DateTime(long id, string name, Partitioning partitioning, DateTimeFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new DateTimeFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField Geolocation(long id, string name, Partitioning partitioning, GeolocationFieldProperties properties = null) + public static RootField Geolocation(long id, string name, Partitioning partitioning, GeolocationFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new GeolocationFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField Json(long id, string name, Partitioning partitioning, JsonFieldProperties properties = null) + public static RootField Json(long id, string name, Partitioning partitioning, JsonFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new JsonFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField Number(long id, string name, Partitioning partitioning, NumberFieldProperties properties = null) + public static RootField Number(long id, string name, Partitioning partitioning, NumberFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new NumberFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField References(long id, string name, Partitioning partitioning, ReferencesFieldProperties properties = null) + public static RootField References(long id, string name, Partitioning partitioning, ReferencesFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new ReferencesFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField String(long id, string name, Partitioning partitioning, StringFieldProperties properties = null) + public static RootField String(long id, string name, Partitioning partitioning, StringFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new StringFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static RootField Tags(long id, string name, Partitioning partitioning, TagsFieldProperties properties = null) + public static RootField Tags(long id, string name, Partitioning partitioning, TagsFieldProperties properties = null, IFieldSettings settings = null) { - return new RootField(id, name, partitioning, properties ?? new TagsFieldProperties()); + return new RootField(id, name, partitioning, properties, settings); } - public static NestedField Assets(long id, string name, AssetsFieldProperties properties = null) + public static NestedField Assets(long id, string name, AssetsFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new AssetsFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField Boolean(long id, string name, BooleanFieldProperties properties = null) + public static NestedField Boolean(long id, string name, BooleanFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new BooleanFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField DateTime(long id, string name, DateTimeFieldProperties properties = null) + public static NestedField DateTime(long id, string name, DateTimeFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new DateTimeFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField Geolocation(long id, string name, GeolocationFieldProperties properties = null) + public static NestedField Geolocation(long id, string name, GeolocationFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new GeolocationFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField Json(long id, string name, JsonFieldProperties properties = null) + public static NestedField Json(long id, string name, JsonFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new JsonFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField Number(long id, string name, NumberFieldProperties properties = null) + public static NestedField Number(long id, string name, NumberFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new NumberFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField References(long id, string name, ReferencesFieldProperties properties = null) + public static NestedField References(long id, string name, ReferencesFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new ReferencesFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField String(long id, string name, StringFieldProperties properties = null) + public static NestedField String(long id, string name, StringFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new StringFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static NestedField Tags(long id, string name, TagsFieldProperties properties = null) + public static NestedField Tags(long id, string name, TagsFieldProperties properties = null, IFieldSettings settings = null) { - return new NestedField(id, name, properties ?? new TagsFieldProperties()); + return new NestedField(id, name, properties, settings); } - public static Schema AddArray(this Schema schema, long id, string name, Partitioning partitioning, Func handler, ArrayFieldProperties properties = null) + public static Schema AddArray(this Schema schema, long id, string name, Partitioning partitioning, Func handler, ArrayFieldProperties properties = null, IFieldSettings settings = null) { - var field = Array(id, name, partitioning, properties); + var field = Array(id, name, partitioning, properties, settings); if (handler != null) { @@ -133,94 +123,94 @@ 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) + 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)); + 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) + 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)); + 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) + 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)); + 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) + 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)); + 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) + 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)); + 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) + 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)); + 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) + 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)); + 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) + 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)); + 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) + 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)); + return schema.AddField(Tags(id, name, partitioning, properties, settings)); } - public static ArrayField AddAssets(this ArrayField field, long id, string name, AssetsFieldProperties properties = 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)); + return field.AddField(Assets(id, name, properties, settings)); } - public static ArrayField AddBoolean(this ArrayField field, long id, string name, BooleanFieldProperties properties = 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)); + return field.AddField(Boolean(id, name, properties, settings)); } - public static ArrayField AddDateTime(this ArrayField field, long id, string name, DateTimeFieldProperties properties = null) + public static ArrayField AddDateTime(this ArrayField field, long id, string name, DateTimeFieldProperties properties = null, IFieldSettings settings = null) { - return field.AddField(DateTime(id, name, properties)); + return field.AddField(DateTime(id, name, properties, settings)); } - public static ArrayField AddGeolocation(this ArrayField field, long id, string name, GeolocationFieldProperties properties = 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)); + return field.AddField(Geolocation(id, name, properties, settings)); } - public static ArrayField AddJson(this ArrayField field, long id, string name, JsonFieldProperties properties = 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)); + return field.AddField(Json(id, name, properties, settings)); } - public static ArrayField AddNumber(this ArrayField field, long id, string name, NumberFieldProperties properties = 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)); + return field.AddField(Number(id, name, properties, settings)); } - public static ArrayField AddReferences(this ArrayField field, long id, string name, ReferencesFieldProperties properties = 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)); + return field.AddField(References(id, name, properties, settings)); } - public static ArrayField AddString(this ArrayField field, long id, string name, StringFieldProperties properties = 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)); + return field.AddField(String(id, name, properties, settings)); } - public static ArrayField AddTags(this ArrayField field, long id, string name, TagsFieldProperties properties = 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)); + return field.AddField(Tags(id, name, properties, settings)); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs index 9136b723c..fadf558fa 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs @@ -24,14 +24,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Geolocation(id, name, partitioning, this); + return Fields.Geolocation(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.Geolocation(id, name, this); + return Fields.Geolocation(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs index 6cc86239d..52b1b0bd2 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/IField.cs @@ -7,18 +7,12 @@ namespace Squidex.Domain.Apps.Core.Schemas { - public interface IField + public interface IField : IFieldSettings { long Id { get; } string Name { get; } - bool IsLocked { get; } - - bool IsDisabled { get; } - - bool IsHidden { get; } - FieldProperties RawProperties { get; } T Accept(IFieldVisitor visitor); diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldSettings.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldSettings.cs new file mode 100644 index 000000000..4caeb7827 --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/IFieldSettings.cs @@ -0,0 +1,18 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Domain.Apps.Core.Schemas +{ + public interface IFieldSettings + { + bool IsLocked { get; } + + bool IsDisabled { get; } + + bool IsHidden { get; } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs index 952ef87f1..ebd6f722f 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs @@ -5,12 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; using Newtonsoft.Json; namespace Squidex.Domain.Apps.Core.Schemas.Json { - public sealed class JsonFieldModel + public sealed class JsonFieldModel : IFieldSettings { [JsonProperty] public long Id { get; set; } @@ -34,6 +33,6 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json public FieldProperties Properties { get; set; } [JsonProperty] - public List Children { get; set; } + public JsonNestedFieldModel[] Children { get; set; } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs index 59b2035e7..50240e695 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs @@ -9,7 +9,7 @@ using Newtonsoft.Json; namespace Squidex.Domain.Apps.Core.Schemas.Json { - public sealed class JsonNestedFieldModel + public sealed class JsonNestedFieldModel : IFieldSettings { [JsonProperty] public long Id { get; set; } @@ -25,5 +25,10 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json [JsonProperty] public FieldProperties Properties { get; set; } + + public bool IsLocked + { + get { return false; } + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs index 37af1b9e6..7e27ef756 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs @@ -5,15 +5,16 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; +using System; using System.Linq; using Newtonsoft.Json; +using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Core.Schemas.Json { public sealed class JsonSchemaModel { - private static readonly RootField[] Empty = new RootField[0]; + private static readonly RootField[] Empty = Array.Empty(); [JsonProperty] public string Name { get; set; } @@ -25,7 +26,7 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json public SchemaProperties Properties { get; set; } [JsonProperty] - public List Fields { get; set; } + public JsonFieldModel[] Fields { get; set; } public JsonSchemaModel() { @@ -38,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json Properties = schema.Properties; Fields = - schema.Fields.Select(x => + schema.Fields.ToArray(x => new JsonFieldModel { Id = x.Id, @@ -49,16 +50,16 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json IsDisabled = x.IsDisabled, Partitioning = x.Partitioning.Key, Properties = x.RawProperties - }).ToList(); + }); IsPublished = schema.IsPublished; } - private static List CreateChildren(IField field) + private static JsonNestedFieldModel[] CreateChildren(IField field) { if (field is ArrayField arrayField) { - return arrayField.Fields.Select(x => + return arrayField.Fields.ToArray(x => new JsonNestedFieldModel { Id = x.Id, @@ -66,7 +67,7 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json IsHidden = x.IsHidden, IsDisabled = x.IsDisabled, Properties = x.RawProperties - }).ToList(); + }); } return null; @@ -78,55 +79,28 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json if (Fields != null) { - fields = new RootField[Fields.Count]; - - for (var i = 0; i < fields.Length; i++) + fields = Fields.ToArray(fieldModel => { - var fieldModel = Fields[i]; - var parititonKey = new Partitioning(fieldModel.Partitioning); - var field = registry.CreateRootField(fieldModel.Id, fieldModel.Name, parititonKey, fieldModel.Properties); + RootField field; - if (field is ArrayField arrayField && fieldModel.Children?.Count > 0) + if (fieldModel.Properties is ArrayFieldProperties arrayProperties && fieldModel.Children?.Length > 0) { - foreach (var nestedFieldModel in fieldModel.Children) + var nestedFields = fieldModel.Children.ToArray(nestedFieldModel => { - var nestedField = registry.CreateNestedField(nestedFieldModel.Id, nestedFieldModel.Name, nestedFieldModel.Properties); - - if (nestedFieldModel.IsHidden) - { - nestedField = nestedField.Hide(); - } - - if (nestedFieldModel.IsDisabled) - { - nestedField = nestedField.Disable(); - } - - arrayField = arrayField.AddField(nestedField); - } - - field = arrayField; - } - - if (fieldModel.IsDisabled) - { - field = field.Disable(); - } + return registry.CreateNestedField(nestedFieldModel.Id, nestedFieldModel.Name, nestedFieldModel.Properties, nestedFieldModel); + }); - if (fieldModel.IsLocked) - { - field = field.Lock(); + field = new ArrayField(fieldModel.Id, fieldModel.Name, parititonKey, nestedFields, arrayProperties, fieldModel); } - - if (fieldModel.IsHidden) + else { - field = field.Hide(); + field = registry.CreateRootField(fieldModel.Id, fieldModel.Name, parititonKey, fieldModel.Properties, fieldModel); } - fields[i] = field; - } + return field; + }); } return new Schema(Name, fields, Properties, IsPublished); diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs index 6edb4f80b..87a5adea6 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs @@ -22,14 +22,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Json(id, name, partitioning, this); + return Fields.Json(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.Json(id, name, this); + return Fields.Json(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs index c958951ad..9643c2ea4 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs @@ -45,13 +45,20 @@ namespace Squidex.Domain.Apps.Core.Schemas public abstract FieldProperties RawProperties { get; } - protected NestedField(long id, string name) + protected NestedField(long id, string name, IFieldSettings settings = null) { Guard.NotNullOrEmpty(name, nameof(name)); Guard.GreaterThan(id, 0, nameof(id)); fieldId = id; fieldName = name; + + if (settings != null) + { + isLocked = settings.IsLocked; + isHidden = settings.IsHidden; + isDisabled = settings.IsDisabled; + } } [Pure] diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs index 7de914a4b..808de167b 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs @@ -25,12 +25,10 @@ namespace Squidex.Domain.Apps.Core.Schemas get { return properties; } } - public NestedField(long id, string name, T properties) - : base(id, name) + public NestedField(long id, string name, T properties = null, IFieldSettings settings = null) + : base(id, name, settings) { - Guard.NotNull(properties, nameof(properties)); - - SetProperties(properties); + SetProperties(properties ?? new T()); } [Pure] diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs index 3238aff25..e16a47f28 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs @@ -35,14 +35,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Number(id, name, partitioning, this); + return Fields.Number(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.Number(id, name, this); + return Fields.Number(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs index 98e4bb5ec..71cfe0cff 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs @@ -29,14 +29,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.References(id, name, partitioning, this); + return Fields.References(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.References(id, name, this); + return Fields.References(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs index 461f60365..6c21a1054 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs @@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Core.Schemas public abstract FieldProperties RawProperties { get; } - protected RootField(long id, string name, Partitioning partitioning) + protected RootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { Guard.NotNullOrEmpty(name, nameof(name)); Guard.GreaterThan(id, 0, nameof(id)); @@ -61,6 +61,13 @@ namespace Squidex.Domain.Apps.Core.Schemas fieldName = name; this.partitioning = partitioning; + + if (settings != null) + { + isLocked = settings.IsLocked; + isHidden = settings.IsHidden; + isDisabled = settings.IsDisabled; + } } [Pure] diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs index 90165643b..cbe6716d0 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs @@ -25,12 +25,10 @@ namespace Squidex.Domain.Apps.Core.Schemas get { return properties; } } - public RootField(long id, string name, Partitioning partitioning, T properties) - : base(id, name, partitioning) + public RootField(long id, string name, Partitioning partitioning, T properties = null, IFieldSettings settings = null) + : base(id, name, partitioning, settings) { - Guard.NotNull(properties, nameof(properties)); - - SetProperties(properties); + SetProperties(properties ?? new T()); } [Pure] diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs index e9731480d..eaee1f7a5 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs @@ -39,14 +39,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.String(id, name, partitioning, this); + return Fields.String(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.String(id, name, this); + return Fields.String(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs index a50cc4bd9..a1c1f822e 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs @@ -33,14 +33,14 @@ namespace Squidex.Domain.Apps.Core.Schemas return visitor.Visit((IField)field); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { - return Fields.Tags(id, name, partitioning, this); + return Fields.Tags(id, name, partitioning, this, settings); } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { - return Fields.Tags(id, name, this); + return Fields.Tags(id, name, this, settings); } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs index dce94972e..bdb223f40 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/CachingGraphQLService.cs @@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var result = await Task.WhenAll(queries.Select(q => QueryInternalAsync(model, ctx, q))); - return (result.Any(x => x.HasError), result.Select(x => x.Response).ToArray()); + return (result.Any(x => x.HasError), result.ToArray(x => x.Response)); } public async Task<(bool HasError, object Response)> QueryAsync(QueryContext context, GraphQLQuery query) diff --git a/src/Squidex.Infrastructure/CollectionExtensions.cs b/src/Squidex.Infrastructure/CollectionExtensions.cs index 61513594d..1d26ce8b4 100644 --- a/src/Squidex.Infrastructure/CollectionExtensions.cs +++ b/src/Squidex.Infrastructure/CollectionExtensions.cs @@ -62,6 +62,32 @@ namespace Squidex.Infrastructure return source.Concat(Enumerable.Repeat(value, 1)); } + public static TResult[] ToArray(this T[] value, Func convert) + { + var result = new TResult[value.Length]; + + for (var i = 0; i < value.Length; i++) + { + result[i] = convert(value[i]); + } + + return result; + } + + public static TResult[] ToArray(this IReadOnlyCollection value, Func convert) + { + var result = new TResult[value.Count]; + var i = 0; + + foreach (var v in value) + { + result[i] = convert(v); + i++; + } + + return result; + } + public static int SequentialHashCode(this IEnumerable collection) { return collection.SequentialHashCode(EqualityComparer.Default); diff --git a/src/Squidex.Infrastructure/Language.cs b/src/Squidex.Infrastructure/Language.cs index c3c6afb71..ba5c546b6 100644 --- a/src/Squidex.Infrastructure/Language.cs +++ b/src/Squidex.Infrastructure/Language.cs @@ -35,7 +35,7 @@ namespace Squidex.Infrastructure } } - public static IEnumerable AllLanguages + public static IReadOnlyCollection AllLanguages { get { return AllLanguagesField.Values; } } diff --git a/src/Squidex.Infrastructure/Log/IArrayWriter.cs b/src/Squidex.Infrastructure/Log/IArrayWriter.cs index 7d5c96a48..8ec8b803a 100644 --- a/src/Squidex.Infrastructure/Log/IArrayWriter.cs +++ b/src/Squidex.Infrastructure/Log/IArrayWriter.cs @@ -12,12 +12,17 @@ namespace Squidex.Infrastructure.Log public interface IArrayWriter { IArrayWriter WriteValue(string value); + IArrayWriter WriteValue(double value); + IArrayWriter WriteValue(long value); + IArrayWriter WriteValue(bool value); IArrayWriter WriteValue(TimeSpan value); + IArrayWriter WriteValue(DateTime value); + IArrayWriter WriteValue(DateTimeOffset value); IArrayWriter WriteObject(Action objectWriter); diff --git a/src/Squidex.Infrastructure/Log/IObjectWriter.cs b/src/Squidex.Infrastructure/Log/IObjectWriter.cs index 1c8ce1f95..fc133875e 100644 --- a/src/Squidex.Infrastructure/Log/IObjectWriter.cs +++ b/src/Squidex.Infrastructure/Log/IObjectWriter.cs @@ -12,15 +12,21 @@ namespace Squidex.Infrastructure.Log public interface IObjectWriter { IObjectWriter WriteProperty(string property, string value); + IObjectWriter WriteProperty(string property, double value); + IObjectWriter WriteProperty(string property, long value); + IObjectWriter WriteProperty(string property, bool value); IObjectWriter WriteProperty(string property, TimeSpan value); + IObjectWriter WriteProperty(string property, DateTime value); + IObjectWriter WriteProperty(string property, DateTimeOffset value); IObjectWriter WriteObject(string property, Action objectWriter); + IObjectWriter WriteArray(string property, Action arrayWriter); } } diff --git a/src/Squidex.Infrastructure/Log/IObjectWriterFactory.cs b/src/Squidex.Infrastructure/Log/IObjectWriterFactory.cs new file mode 100644 index 000000000..65b992ee0 --- /dev/null +++ b/src/Squidex.Infrastructure/Log/IObjectWriterFactory.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Log +{ + public interface IObjectWriterFactory + { + IObjectWriter Create(); + + void Release(IObjectWriter writer); + } +} diff --git a/src/Squidex.Infrastructure/Log/JsonLogWriter.cs b/src/Squidex.Infrastructure/Log/JsonLogWriter.cs index 7d9bdf21f..4d8012f8f 100644 --- a/src/Squidex.Infrastructure/Log/JsonLogWriter.cs +++ b/src/Squidex.Infrastructure/Log/JsonLogWriter.cs @@ -14,18 +14,37 @@ namespace Squidex.Infrastructure.Log { public sealed class JsonLogWriter : IObjectWriter, IArrayWriter { - private readonly bool extraLine; + private readonly Formatting formatting; + private readonly bool formatLine; private readonly StringWriter textWriter = new StringWriter(); - private readonly JsonWriter jsonWriter; + private JsonWriter jsonWriter; - public JsonLogWriter(Formatting formatting = Formatting.None, bool extraLine = false) + public int BufferSize { - this.extraLine = extraLine; + get { return textWriter.GetStringBuilder().Capacity; } + } + + internal JsonLogWriter(Formatting formatting, bool formatLine) + { + this.formatLine = formatLine; + this.formatting = formatting; + Start(); + } + + private void Start() + { jsonWriter = new JsonTextWriter(textWriter) { Formatting = formatting }; jsonWriter.WriteStartObject(); } + internal void Reset() + { + textWriter.GetStringBuilder().Clear(); + + Start(); + } + IArrayWriter IArrayWriter.WriteValue(string value) { jsonWriter.WriteValue(value); @@ -170,14 +189,12 @@ namespace Squidex.Infrastructure.Log { jsonWriter.WriteEndObject(); - var result = textWriter.ToString(); - - if (extraLine) + if (formatLine) { - result += Environment.NewLine; + textWriter.WriteLine(); } - return result; + return textWriter.ToString(); } } } diff --git a/src/Squidex.Infrastructure/Log/JsonLogWriterFactory.cs b/src/Squidex.Infrastructure/Log/JsonLogWriterFactory.cs new file mode 100644 index 000000000..7ff85b6ea --- /dev/null +++ b/src/Squidex.Infrastructure/Log/JsonLogWriterFactory.cs @@ -0,0 +1,61 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Concurrent; +using Newtonsoft.Json; + +namespace Squidex.Infrastructure.Log +{ + public sealed class JsonLogWriterFactory : IObjectWriterFactory + { + private const int MaxPoolSize = 10; + private const int MaxCapacity = 5000; + private readonly ConcurrentStack pool = new ConcurrentStack(); + private readonly Formatting formatting; + private readonly bool formatLine; + + public JsonLogWriterFactory(Formatting formatting = Formatting.None, bool formatLine = false) + { + this.formatting = formatting; + this.formatLine = formatLine; + } + + public static JsonLogWriterFactory Default() + { + return new JsonLogWriterFactory(); + } + + public static JsonLogWriterFactory Readable() + { + return new JsonLogWriterFactory(Formatting.Indented, true); + } + + public IObjectWriter Create() + { + if (pool.TryPop(out var writer)) + { + writer.Reset(); + } + else + { + writer = new JsonLogWriter(formatting, formatLine); + } + + return writer; + } + + public void Release(IObjectWriter writer) + { + var jsonWriter = (JsonLogWriter)writer; + + if (pool.Count < MaxPoolSize && jsonWriter.BufferSize < MaxCapacity) + { + pool.Push(jsonWriter); + } + } + } +} diff --git a/src/Squidex.Infrastructure/Log/SemanticLog.cs b/src/Squidex.Infrastructure/Log/SemanticLog.cs index 7816db42f..09293315d 100644 --- a/src/Squidex.Infrastructure/Log/SemanticLog.cs +++ b/src/Squidex.Infrastructure/Log/SemanticLog.cs @@ -13,20 +13,21 @@ namespace Squidex.Infrastructure.Log { public sealed class SemanticLog : ISemanticLog { - private readonly IEnumerable channels; - private readonly IEnumerable appenders; - private readonly Func writerFactory; + private readonly ILogChannel[] channels; + private readonly ILogAppender[] appenders; + private readonly IObjectWriterFactory writerFactory; public SemanticLog( IEnumerable channels, IEnumerable appenders, - Func writerFactory) + IObjectWriterFactory writerFactory) { Guard.NotNull(channels, nameof(channels)); Guard.NotNull(appenders, nameof(appenders)); + Guard.NotNull(writerFactory, nameof(writerFactory)); - this.channels = channels; - this.appenders = appenders; + this.channels = channels.ToArray(); + this.appenders = appenders.ToArray(); this.writerFactory = writerFactory; } @@ -38,11 +39,11 @@ namespace Squidex.Infrastructure.Log List exceptions = null; - foreach (var channel in channels) + for (var i = 0; i < channels.Length; i++) { try { - channel.Log(logLevel, formattedText); + channels[i].Log(logLevel, formattedText); } catch (Exception ex) { @@ -63,18 +64,25 @@ namespace Squidex.Infrastructure.Log private string FormatText(SemanticLogLevel logLevel, Action objectWriter) { - var writer = writerFactory(); + var writer = writerFactory.Create(); - writer.WriteProperty(nameof(logLevel), logLevel.ToString()); + try + { + writer.WriteProperty(nameof(logLevel), logLevel.ToString()); + + objectWriter(writer); - objectWriter(writer); + for (var i = 0; i < appenders.Length; i++) + { + appenders[i].Append(writer); + } - foreach (var appender in appenders) + return writer.ToString(); + } + finally { - appender.Append(writer); + writerFactory.Release(writer); } - - return writer.ToString(); } public ISemanticLog CreateScope(Action objectWriter) diff --git a/src/Squidex.Infrastructure/Security/PermissionSet.cs b/src/Squidex.Infrastructure/Security/PermissionSet.cs index a7b138927..08f702b19 100644 --- a/src/Squidex.Infrastructure/Security/PermissionSet.cs +++ b/src/Squidex.Infrastructure/Security/PermissionSet.cs @@ -14,7 +14,7 @@ namespace Squidex.Infrastructure.Security { public sealed class PermissionSet : IReadOnlyCollection { - public static readonly PermissionSet Empty = new PermissionSet(new string[0]); + public static readonly PermissionSet Empty = new PermissionSet(Array.Empty()); private readonly List permissions; private readonly Lazy display; diff --git a/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs b/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs index d07e2d7a4..3aa0e09a3 100644 --- a/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs +++ b/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; #pragma warning disable RECS0012 // 'if' statement can be re-written as 'switch' statement @@ -190,7 +191,7 @@ namespace Squidex.Infrastructure.States private EventData[] GetEventData(Envelope[] events, Guid commitId) { - return events.Select(x => eventDataFormatter.ToEventData(x, commitId, true)).ToArray(); + return events.ToArray(x => eventDataFormatter.ToEventData(x, commitId, true)); } private string GetStreamName() diff --git a/src/Squidex.Infrastructure/ValidationError.cs b/src/Squidex.Infrastructure/ValidationError.cs index 06e294aaf..2ae3c5de4 100644 --- a/src/Squidex.Infrastructure/ValidationError.cs +++ b/src/Squidex.Infrastructure/ValidationError.cs @@ -14,7 +14,7 @@ namespace Squidex.Infrastructure [Serializable] public sealed class ValidationError { - private static readonly string[] FallbackProperties = new string[0]; + private static readonly string[] FallbackProperties = Array.Empty(); private readonly string message; private readonly string[] propertyNames; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs index 7a6f1c579..dbff58573 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Squidex.Areas.Api.Controllers.Apps.Models; using Squidex.Domain.Apps.Entities.Apps.Commands; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Pipeline; using Squidex.Shared; @@ -45,7 +46,7 @@ namespace Squidex.Areas.Api.Controllers.Apps [ApiCosts(0)] public IActionResult GetClients(string app) { - var response = App.Clients.Select(ClientDto.FromKvp).ToList(); + var response = App.Clients.Select(ClientDto.FromKvp).ToArray(); Response.Headers["ETag"] = App.Version.ToString(); diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs index 8ed7a7685..cf6bee081 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs @@ -46,7 +46,7 @@ namespace Squidex.Areas.Api.Controllers.Apps [ApiCosts(0)] public IActionResult GetPatterns(string app) { - var response = App.Patterns.Select(AppPatternDto.FromKvp).OrderBy(x => x.Name).ToList(); + var response = App.Patterns.Select(AppPatternDto.FromKvp).OrderBy(x => x.Name).ToArray(); Response.Headers["ETag"] = App.Version.ToString(); diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs index 74fc6bfb4..0f3092fb4 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs @@ -13,6 +13,7 @@ using Squidex.Areas.Api.Controllers.Apps.Models; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Domain.Apps.Entities.Apps.Services; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Security; using Squidex.Pipeline; @@ -62,7 +63,7 @@ namespace Squidex.Areas.Api.Controllers.Apps var entities = await appProvider.GetUserApps(userId, userPermissions); - var response = entities.Select(a => AppDto.FromApp(a, userId, userPermissions, appPlansProvider)).ToList(); + var response = entities.ToArray(a => AppDto.FromApp(a, userId, userPermissions, appPlansProvider)); Response.Headers["ETag"] = response.ToManyEtag(); diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs index dfbeec425..f2774e4b4 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs @@ -13,6 +13,7 @@ using Newtonsoft.Json; using NodaTime; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.Services; +using Squidex.Infrastructure; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Security; using Squidex.Pipeline; @@ -80,7 +81,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models var response = SimpleMapper.Map(app, new AppDto()); - response.Permissions = permissions.Select(x => x.Id).ToArray(); + response.Permissions = permissions.ToArray(x => x.Id); response.PlanName = plans.GetPlanForApp(app)?.Name; response.PlanUpgrade = plans.GetPlanUpgradeForApp(app)?.Name; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs index 0a064ebac..62501e4c2 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs @@ -5,7 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using Squidex.Domain.Apps.Core.Apps; @@ -34,7 +34,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models /// The fallback languages. /// [Required] - public List Fallback { get; set; } + public Language[] Fallback { get; set; } /// /// Indicates if the language is the master language. @@ -48,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models public static AppLanguageDto FromCommand(AddLanguage command) { - return SimpleMapper.Map(command.Language, new AppLanguageDto { Fallback = new List() }); + return SimpleMapper.Map(command.Language, new AppLanguageDto { Fallback = Array.Empty() }); } public static AppLanguageDto[] FromApp(IAppEntity app) @@ -63,7 +63,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models { IsMaster = x == app.LanguagesConfig.Master, IsOptional = x.IsOptional, - Fallback = x.LanguageFallbacks.ToList() + Fallback = x.LanguageFallbacks.ToArray() }); } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs index a3352dd48..8292c7f0a 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs @@ -9,6 +9,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.Services; +using Squidex.Infrastructure; namespace Squidex.Areas.Api.Controllers.Apps.Models { @@ -29,7 +30,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models { var plan = plans.GetPlanForApp(app); - var contributors = app.Contributors.Select(x => new ContributorDto { ContributorId = x.Key, Role = x.Value }).ToArray(); + var contributors = app.Contributors.ToArray(x => new ContributorDto { ContributorId = x.Key, Role = x.Value }); return new ContributorsDto { Contributors = contributors, MaxContributors = plan.MaxContributors }; } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs index 4ee092e69..2c833707b 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Squidex.Domain.Apps.Core.Apps; @@ -35,7 +36,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models /// Associated list of permissions. /// [Required] - public string[] Permissions { get; set; } + public IEnumerable Permissions { get; set; } public static RoleDto FromRole(Role role, IAppEntity app) { @@ -46,7 +47,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models Name = role.Name, NumClients = app.Clients.Count(x => string.Equals(x.Value.Role, role.Name, StringComparison.OrdinalIgnoreCase)), NumContributors = app.Contributors.Count(x => string.Equals(x.Value, role.Name, StringComparison.OrdinalIgnoreCase)), - Permissions = permissions.ToIds().ToArray() + Permissions = permissions.ToIds() }; } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/UpdateLanguageDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/UpdateLanguageDto.cs index 8c6d2e707..0a470ff6c 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/UpdateLanguageDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/UpdateLanguageDto.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Infrastructure; using Squidex.Infrastructure.Reflection; @@ -27,7 +26,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models /// /// Optional fallback languages. /// - public List Fallback { get; set; } + public Language[] Fallback { get; set; } public UpdateLanguage ToCommand(Language language) { diff --git a/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs b/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs index 2f88f75f3..d69893681 100644 --- a/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc; using Orleans; using Squidex.Areas.Api.Controllers.Backups.Models; using Squidex.Domain.Apps.Entities.Backup; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Tasks; using Squidex.Pipeline; @@ -53,7 +54,7 @@ namespace Squidex.Areas.Api.Controllers.Backups var jobs = await backupGrain.GetStateAsync(); - var response = jobs.Value.Select(BackupJobDto.FromBackup).ToList(); + var response = jobs.Value.ToArray(BackupJobDto.FromBackup); return Ok(response); } diff --git a/src/Squidex/Areas/Api/Controllers/Comments/Models/CommentsDto.cs b/src/Squidex/Areas/Api/Controllers/Comments/Models/CommentsDto.cs index dceed44de..063e76234 100644 --- a/src/Squidex/Areas/Api/Controllers/Comments/Models/CommentsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Comments/Models/CommentsDto.cs @@ -17,12 +17,12 @@ namespace Squidex.Areas.Api.Controllers.Comments.Models /// /// The created comments including the updates. /// - public List CreatedComments { get; set; } + public CommentDto[] CreatedComments { get; set; } /// /// The updates comments since the last version. /// - public List UpdatedComments { get; set; } + public CommentDto[] UpdatedComments { get; set; } /// /// The deleted comments since the last version. @@ -38,8 +38,8 @@ namespace Squidex.Areas.Api.Controllers.Comments.Models { return new CommentsDto { - CreatedComments = result.CreatedComments.Select(CommentDto.FromComment).ToList(), - UpdatedComments = result.UpdatedComments.Select(CommentDto.FromComment).ToList(), + CreatedComments = result.CreatedComments.Select(CommentDto.FromComment).ToArray(), + UpdatedComments = result.UpdatedComments.Select(CommentDto.FromComment).ToArray(), DeletedComments = result.DeletedComments, Version = result.Version }; diff --git a/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs b/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs index e53ea81b5..5a5479cbc 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs @@ -18,6 +18,7 @@ using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.GraphQL; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Pipeline; using Squidex.Shared; diff --git a/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs b/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs index 0f770adff..f8a2c9d0d 100644 --- a/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs +++ b/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs @@ -35,7 +35,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers { var entities = await GetGrain().GetConsumersAsync(); - var response = entities.Value.OrderBy(x => x.Name).Select(EventConsumerDto.FromEventConsumerInfo).ToList(); + var response = entities.Value.OrderBy(x => x.Name).Select(EventConsumerDto.FromEventConsumerInfo).ToArray(); return Ok(response); } diff --git a/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs b/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs index 6a7565235..53e2fa8aa 100644 --- a/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs +++ b/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Squidex.Areas.Api.Controllers.History.Models; using Squidex.Domain.Apps.Entities.History; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Pipeline; using Squidex.Shared; @@ -48,7 +49,7 @@ namespace Squidex.Areas.Api.Controllers.History { var entities = await historyService.QueryByChannelAsync(AppId, channel, 100); - var response = entities.Select(HistoryEventDto.FromHistoryEvent).ToList(); + var response = entities.ToArray(HistoryEventDto.FromHistoryEvent); return Ok(response); } diff --git a/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs b/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs index d0750f020..8c4509e3f 100644 --- a/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs @@ -39,7 +39,7 @@ namespace Squidex.Areas.Api.Controllers.Languages [ApiPermission] public IActionResult GetLanguages() { - var response = Language.AllLanguages.Select(LanguageDto.FromLanguage).ToList(); + var response = Language.AllLanguages.Select(LanguageDto.FromLanguage).ToArray(); Response.Headers["Etag"] = "1"; diff --git a/src/Squidex/Areas/Api/Controllers/Plans/Models/AppPlansDto.cs b/src/Squidex/Areas/Api/Controllers/Plans/Models/AppPlansDto.cs index f6130ceef..95345863e 100644 --- a/src/Squidex/Areas/Api/Controllers/Plans/Models/AppPlansDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Plans/Models/AppPlansDto.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Squidex.Domain.Apps.Entities.Apps; @@ -19,7 +18,7 @@ namespace Squidex.Areas.Api.Controllers.Plans.Models /// The available plans. /// [Required] - public List Plans { get; set; } + public PlanDto[] Plans { get; set; } /// /// The current plan id. @@ -43,7 +42,7 @@ namespace Squidex.Areas.Api.Controllers.Plans.Models var response = new AppPlansDto { CurrentPlanId = planId, - Plans = plans.GetAvailablePlans().Select(PlanDto.FromPlan).ToList(), + Plans = plans.GetAvailablePlans().Select(PlanDto.FromPlan).ToArray(), PlanOwner = app.Plan?.Owner.Identifier, HasPortal = hasPortal }; diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs index 0c58dc1e9..cd75ac32b 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs @@ -33,7 +33,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Converters public RuleTriggerDto Visit(ContentChangedTrigger trigger) { - var schemas = trigger.Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchemaDto())).ToList(); + var schemas = trigger.Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchemaDto())).ToArray(); return new ContentChangedTriggerDto { Schemas = schemas, HandleAll = trigger.HandleAll }; } diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs index ef320b78d..482ac0caa 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Squidex.Domain.Apps.Entities.Rules; +using Squidex.Infrastructure; namespace Squidex.Areas.Api.Controllers.Rules.Models { diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs index aa2b70386..9aa436d5f 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs @@ -23,7 +23,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers /// The schema settings. /// [Required] - public List Schemas { get; set; } + public ContentChangedTriggerSchemaDto[] Schemas { get; set; } /// /// Determines whether the trigger should handle all content changes events. diff --git a/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs b/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs index dee4249f5..e3e0da2eb 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs @@ -101,7 +101,7 @@ namespace Squidex.Areas.Api.Controllers.Rules { var entities = await appProvider.GetRulesAsync(AppId); - var response = entities.Select(RuleDto.FromRule); + var response = entities.Select(RuleDto.FromRule).ToArray(); Response.Headers["ETag"] = response.ToManyEtag(0); diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs b/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs index f696a628f..86e5bdd96 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs @@ -13,6 +13,7 @@ using Squidex.Areas.Api.Controllers.Schemas.Models; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas.Commands; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Pipeline; using Squidex.Shared; @@ -50,7 +51,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas { var schemas = await appProvider.GetSchemasAsync(AppId); - var response = schemas.Select(SchemaDto.FromSchema).ToList(); + var response = schemas.ToArray(SchemaDto.FromSchema); Response.Headers["ETag"] = response.ToManyEtag(); diff --git a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs index 67d0295df..99065d372 100644 --- a/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc; using Squidex.Areas.Api.Controllers.Statistics.Models; using Squidex.Domain.Apps.Entities.Apps.Services; using Squidex.Domain.Apps.Entities.Assets; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.UsageTracking; using Squidex.Pipeline; @@ -92,7 +93,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics var entities = await usageTracker.QueryAsync(AppId.ToString(), fromDate.Date, toDate.Date); - var response = entities.ToDictionary(x => x.Key, x => x.Value.Select(CallsUsageDto.FromUsage).ToList()); + var response = entities.ToDictionary(x => x.Key, x => x.Value.Select(CallsUsageDto.FromUsage).ToArray()); return Ok(response); } @@ -146,7 +147,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics var entities = await assetStatsRepository.QueryAsync(AppId, fromDate.Date, toDate.Date); - var models = entities.Select(StorageUsageDto.FromStats).ToList(); + var models = entities.Select(StorageUsageDto.FromStats).ToArray(); return Ok(models); } diff --git a/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs b/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs index bf048c0ba..8a2a5a2d4 100644 --- a/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs @@ -5,8 +5,8 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; using Squidex.Infrastructure.Reflection; using Squidex.Shared.Users; @@ -42,11 +42,11 @@ namespace Squidex.Areas.Api.Controllers.Users.Models /// Additional permissions for the user. /// [Required] - public string[] Permissions { get; set; } + public IEnumerable Permissions { get; set; } public static UserDto FromUser(IUser user) { - var permissions = user.Permissions().ToIds().ToArray(); + var permissions = user.Permissions().ToIds(); return SimpleMapper.Map(user, new UserDto { DisplayName = user.DisplayName(), Permissions = permissions }); } diff --git a/src/Squidex/Areas/Frontend/Middlewares/WebpackMiddleware.cs b/src/Squidex/Areas/Frontend/Middlewares/WebpackMiddleware.cs index 83c57d810..85d2b032f 100644 --- a/src/Squidex/Areas/Frontend/Middlewares/WebpackMiddleware.cs +++ b/src/Squidex/Areas/Frontend/Middlewares/WebpackMiddleware.cs @@ -18,7 +18,7 @@ namespace Squidex.Areas.Frontend.Middlewares private const string Host = "localhost"; private const string Port = "3000"; private static readonly string[] Scripts = { "shims.js", "app.js" }; - private static readonly string[] Styles = new string[0]; + private static readonly string[] Styles = Array.Empty(); private readonly RequestDelegate next; public WebpackMiddleware(RequestDelegate next) diff --git a/src/Squidex/Config/Domain/LoggingServices.cs b/src/Squidex/Config/Domain/LoggingServices.cs index a00ad2db2..0d1631ded 100644 --- a/src/Squidex/Config/Domain/LoggingServices.cs +++ b/src/Squidex/Config/Domain/LoggingServices.cs @@ -8,7 +8,6 @@ using System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; using Squidex.Infrastructure.Log; using Squidex.Pipeline; @@ -25,11 +24,13 @@ namespace Squidex.Config.Domain { if (config.GetValue("logging:human")) { - services.AddSingletonAs(c => new Func(() => new JsonLogWriter(Formatting.Indented, true))); + services.AddSingletonAs(JsonLogWriterFactory.Readable()) + .As(); } else { - services.AddSingletonAs(c => new Func(() => new JsonLogWriter())); + services.AddSingletonAs(JsonLogWriterFactory.Default()) + .As(); } var loggingFile = config.GetValue("logging:file"); diff --git a/src/Squidex/Config/Web/WebExtensions.cs b/src/Squidex/Config/Web/WebExtensions.cs index 9886fbc73..82a71d289 100644 --- a/src/Squidex/Config/Web/WebExtensions.cs +++ b/src/Squidex/Config/Web/WebExtensions.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpOverrides; using Squidex.Infrastructure.Diagnostics; diff --git a/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs b/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs index 62aa39efe..6d0294fca 100644 --- a/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs +++ b/src/Squidex/Pipeline/ApiExceptionFilterAttribute.cs @@ -61,7 +61,7 @@ namespace Squidex.Pipeline private static IActionResult OnValidationException(ValidationException ex) { - return ErrorResult(400, new ErrorDto { Message = ex.Summary, Details = ex.Errors?.Select(e => e.Message).ToArray() }); + return ErrorResult(400, new ErrorDto { Message = ex.Summary, Details = ex.Errors?.ToArray(e => e.Message) }); } private static IActionResult ErrorResult(int statusCode, ErrorDto error) diff --git a/src/Squidex/Pipeline/ETagExtensions.cs b/src/Squidex/Pipeline/ETagExtensions.cs index 4c30e2411..074c952a3 100644 --- a/src/Squidex/Pipeline/ETagExtensions.cs +++ b/src/Squidex/Pipeline/ETagExtensions.cs @@ -5,8 +5,9 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; -using System.Linq; +using System.Text; using Squidex.Infrastructure; using Squidex.Infrastructure.Log; @@ -14,17 +15,59 @@ namespace Squidex.Pipeline { public static class ETagExtensions { - public static string ToManyEtag(this IEnumerable items, long total = 0) where T : IGenerateEtag + private static readonly int GuidLength = Guid.Empty.ToString().Length; + + public static string ToManyEtag(this IReadOnlyList items, long total = 0) where T : IGenerateEtag { using (Profiler.Trace("CalculateEtag")) { - return $"{total}_{string.Join(";", items.Select(x => $"{x.Id}{x.Version}"))}".Sha256Base64(); + var unhashed = Unhashed(items, total); + + return unhashed.Sha256Base64(); } } - public static string ToSurrogateKeys(this IEnumerable items) where T : IGenerateEtag + private static string Unhashed(IReadOnlyList items, long total) where T : IGenerateEtag { - return string.Join(" ", items.Select(x => x.Id)); + var sb = new StringBuilder((items.Count * (GuidLength + 4)) + 10); + + sb.Append(total); + sb.Append("_"); + + if (items.Count > 0) + { + sb.Append(items[0].Id.ToString()); + sb.Append(items[0].Version); + + for (var i = 1; i < items.Count; i++) + { + sb.Append(";"); + sb.Append(items[i].Id.ToString()); + sb.Append(items[i].Version); + } + } + + return sb.ToString(); + } + + public static string ToSurrogateKeys(this IReadOnlyList items) where T : IGenerateEtag + { + if (items.Count == 0) + { + return string.Empty; + } + + var sb = new StringBuilder(items.Count * (GuidLength + 1)); + + sb.Append(items[0].Id.ToString()); + + for (var i = 1; i < items.Count; i++) + { + sb.Append(" "); + sb.Append(items[i].Id.ToString()); + } + + return sb.ToString(); } public static string ToEtag(this T item) where T : IGenerateEtag diff --git a/src/Squidex/app/theme/icomoon/icons/control-Tags.svg b/src/Squidex/app/theme/icomoon/icons/control-Tags.svg new file mode 100644 index 000000000..b77cc0f7d --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/control-Tags.svg @@ -0,0 +1,75 @@ + + + +image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/FieldRegistryTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/FieldRegistryTests.cs index 597b54f8d..614ee6a65 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/FieldRegistryTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/FieldRegistryTests.cs @@ -28,12 +28,12 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas return default(T); } - public override RootField CreateRootField(long id, string name, Partitioning partitioning) + public override RootField CreateRootField(long id, string name, Partitioning partitioning, IFieldSettings settings = null) { return null; } - public override NestedField CreateNestedField(long id, string name) + public override NestedField CreateNestedField(long id, string name, IFieldSettings settings = null) { return null; } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsRests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsRests.cs index 3e530d6d9..5d4b8764d 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsRests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsRests.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Linq; using Squidex.Infrastructure.Security; using Xunit; @@ -16,7 +17,7 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public void Should_add_common_permission() { - var source = new string[0]; + var source = Array.Empty(); var result = source.Prefix("my-app"); Assert.Equal(new[] { "squidex.apps.my-app.common" }, result); diff --git a/tests/Squidex.Infrastructure.Tests/Log/JsonLogWriterTests.cs b/tests/Squidex.Infrastructure.Tests/Log/JsonLogWriterTests.cs index a0ff04d7a..069be90c7 100644 --- a/tests/Squidex.Infrastructure.Tests/Log/JsonLogWriterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Log/JsonLogWriterTests.cs @@ -13,7 +13,7 @@ namespace Squidex.Infrastructure.Log { public class JsonLogWriterTests { - private readonly IObjectWriter sut = new JsonLogWriter(); + private readonly IObjectWriter sut = JsonLogWriterFactory.Default().Create(); [Fact] public void Should_write_boolean_property() @@ -59,6 +59,7 @@ namespace Squidex.Infrastructure.Log public void Should_write_datetimeoffset_property() { var value = DateTimeOffset.UtcNow; + var result = sut.WriteProperty("property", value).ToString(); Assert.Equal($"{{\"property\":\"{value:o}\"}}", result); @@ -68,6 +69,7 @@ namespace Squidex.Infrastructure.Log public void Should_write_date_property() { var value = DateTime.UtcNow; + var result = sut.WriteProperty("property", value).ToString(); Assert.Equal($"{{\"property\":\"{value:o}\"}}", result); @@ -125,6 +127,7 @@ namespace Squidex.Infrastructure.Log public void Should_write_datetimeoffset_value() { var value = DateTimeOffset.UtcNow; + var result = sut.WriteArray("property", a => a.WriteValue(value)).ToString(); Assert.Equal($"{{\"property\":[\"{value:o}\"]}}", result); @@ -134,6 +137,7 @@ namespace Squidex.Infrastructure.Log public void Should_write_date_value() { var value = DateTime.UtcNow; + var result = sut.WriteArray("property", a => a.WriteValue(value)).ToString(); Assert.Equal($"{{\"property\":[\"{value:yyyy-MM-ddTHH:mm:ssZ}\"]}}", result); @@ -150,7 +154,7 @@ namespace Squidex.Infrastructure.Log [Fact] public void Should_write_pretty_json() { - IObjectWriter prettySut = new JsonLogWriter(Formatting.Indented); + var prettySut = new JsonLogWriterFactory(Formatting.Indented).Create(); var result = prettySut.WriteProperty("property", 1.5).ToString(); @@ -160,7 +164,7 @@ namespace Squidex.Infrastructure.Log [Fact] public void Should_write_extra_line_after_object() { - IObjectWriter prettySut = new JsonLogWriter(Formatting.None, true); + var prettySut = new JsonLogWriterFactory(Formatting.None, true).Create(); var result = prettySut.WriteProperty("property", 1.5).ToString(); diff --git a/tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs b/tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs index b08b3262d..ec9958df8 100644 --- a/tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Log/SemanticLogAdapterTests.cs @@ -38,7 +38,7 @@ namespace Squidex.Infrastructure.Log output = message; }); - log = new Lazy(() => new SemanticLog(channels, new List(), () => new JsonLogWriter())); + log = new Lazy(() => new SemanticLog(channels, new List(), JsonLogWriterFactory.Default())); sut = SemanticLogLoggerProvider.ForTesting(log.Value); } @@ -197,7 +197,7 @@ namespace Squidex.Infrastructure.Log private static string MakeTestCall(Action writer) { - IObjectWriter sut = new JsonLogWriter(); + var sut = JsonLogWriterFactory.Default().Create(); writer(sut); diff --git a/tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs b/tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs index 24593806c..7f82046ff 100644 --- a/tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs @@ -21,7 +21,7 @@ namespace Squidex.Infrastructure.Log private readonly List channels = new List(); private readonly Lazy log; private readonly ILogChannel channel = A.Fake(); - private string output; + private string output = string.Empty; public SemanticLog Log { @@ -35,10 +35,29 @@ namespace Squidex.Infrastructure.Log A.CallTo(() => channel.Log(A.Ignored, A.Ignored)) .Invokes((SemanticLogLevel level, string message) => { - output = message; + output += message; }); - log = new Lazy(() => new SemanticLog(channels, appenders, () => new JsonLogWriter())); + log = new Lazy(() => new SemanticLog(channels, appenders, JsonLogWriterFactory.Default())); + } + + [Fact] + public void Should_log_multiple_lines() + { + Log.Log(SemanticLogLevel.Error, w => w.WriteProperty("logMessage", "Msg1")); + Log.Log(SemanticLogLevel.Error, w => w.WriteProperty("logMessage", "Msg2")); + + var expected1 = + LogTest(w => w + .WriteProperty("logLevel", "Error") + .WriteProperty("logMessage", "Msg1")); + + var expected2 = + LogTest(w => w + .WriteProperty("logLevel", "Error") + .WriteProperty("logMessage", "Msg2")); + + Assert.Equal(expected1 + expected2, output); } [Fact] @@ -307,7 +326,7 @@ namespace Squidex.Infrastructure.Log A.CallTo(() => channel1.Log(A.Ignored, A.Ignored)).Throws(exception1); A.CallTo(() => channel2.Log(A.Ignored, A.Ignored)).Throws(exception2); - var sut = new SemanticLog(new[] { channel1, channel2 }, Enumerable.Empty(), () => new JsonLogWriter()); + var sut = new SemanticLog(new[] { channel1, channel2 }, Enumerable.Empty(), JsonLogWriterFactory.Default()); try { @@ -324,7 +343,7 @@ namespace Squidex.Infrastructure.Log private static string LogTest(Action writer) { - IObjectWriter sut = new JsonLogWriter(); + var sut = JsonLogWriterFactory.Default().Create(); writer(sut); From f2418b30f11ef8abb5fafda4033f359876286301 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 25 Nov 2018 09:39:41 +0100 Subject: [PATCH 08/33] Performance optimizations. Get rid of slow immutable classes. --- .../Apps/AppClients.cs | 39 +++-- .../Apps/AppContributors.cs | 14 +- .../Apps/AppPatterns.cs | 30 ++-- .../Apps/Json/AppClientsConverter.cs | 9 +- .../Apps/Json/AppContributorsConverter.cs | 4 +- .../Apps/Json/AppPatternsConverter.cs | 10 +- .../Apps/Json/RolesConverter.cs | 8 +- .../Apps/LanguageConfig.cs | 3 +- .../Apps/LanguagesConfig.cs | 17 +- .../Apps/Roles.cs | 32 ++-- .../DictionaryWrapper{TKey,TValue}.cs | 68 -------- .../Rules/Triggers/ContentChangedTrigger.cs | 4 +- .../Schemas/AssetsFieldProperties.cs | 4 +- .../Schemas/FieldCollection.cs | 29 ++-- .../Schemas/Json/JsonFieldModel.cs | 20 +++ .../Schemas/Json/JsonNestedFieldModel.cs | 5 + .../Schemas/Json/JsonSchemaModel.cs | 32 +--- .../Schemas/Json/SchemaConverter.cs | 11 +- .../Schemas/NumberFieldProperties.cs | 4 +- .../Schemas/StringFieldProperties.cs | 4 +- .../Schemas/TagsFieldProperties.cs | 4 +- .../Templates/Builders/StringFieldBuilder.cs | 4 +- .../CollectionExtensions.cs | 32 ---- .../Collections/ArrayDictionary.cs | 21 +++ .../ArrayDictionary{TKey,TValue}.cs | 163 ++++++++++++++++++ .../Collections/ReadOnlyCollection.cs | 36 ++++ .../StringExtensions.cs | 154 +++++++++++++++-- src/Squidex.Infrastructure/ValidationError.cs | 3 +- .../Triggers/ContentChangedTriggerDto.cs | 5 +- .../Models/Fields/AssetsFieldPropertiesDto.cs | 4 +- .../Models/Fields/NumberFieldPropertiesDto.cs | 4 +- .../Models/Fields/StringFieldPropertiesDto.cs | 4 +- .../Models/Fields/TagsFieldPropertiesDto.cs | 4 +- .../Config/Domain/SerializationServices.cs | 2 +- .../Model/Apps/AppClientsTests.cs | 10 +- .../Triggers/ContentChangedTriggerTests.cs | 4 +- .../ValidateContent/AssetsFieldTests.cs | 4 +- .../ValidateContent/NumberFieldTests.cs | 4 +- .../ValidateContent/StringFieldTests.cs | 4 +- .../ValidateContent/TagsFieldTests.cs | 4 +- .../TestData.cs | 6 +- .../Contents/MongoDb/MongoDbQueryTests.cs | 4 +- .../Rules/Guards/GuardRuleTests.cs | 8 +- .../Triggers/ContentChangedTriggerTests.cs | 8 +- .../Rules/RuleGrainTests.cs | 6 +- .../NumberFieldPropertiesTests.cs | 10 +- .../StringFieldPropertiesTests.cs | 10 +- .../CollectionExtensionsTests.cs | 31 ---- 48 files changed, 577 insertions(+), 323 deletions(-) delete mode 100644 src/Squidex.Domain.Apps.Core.Model/DictionaryWrapper{TKey,TValue}.cs create mode 100644 src/Squidex.Infrastructure/Collections/ArrayDictionary.cs create mode 100644 src/Squidex.Infrastructure/Collections/ArrayDictionary{TKey,TValue}.cs create mode 100644 src/Squidex.Infrastructure/Collections/ReadOnlyCollection.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs index 425c14dbf..3646682a7 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs @@ -5,49 +5,60 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; +using System; +using System.Collections.Generic; using System.Diagnostics.Contracts; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; namespace Squidex.Domain.Apps.Core.Apps { - public sealed class AppClients : DictionaryWrapper + public sealed class AppClients : ArrayDictionary { public static readonly AppClients Empty = new AppClients(); private AppClients() - : base(ImmutableDictionary.Empty) { } - public AppClients(ImmutableDictionary inner) - : base(inner) + public AppClients(KeyValuePair[] items) + : base(items) { } [Pure] - public AppClients Add(string id, AppClient client) + public AppClients Revoke(string id) { Guard.NotNullOrEmpty(id, nameof(id)); - Guard.NotNull(client, nameof(client)); - return new AppClients(Inner.Add(id, client)); + return new AppClients(Without(id)); } [Pure] - public AppClients Add(string id, string secret) + public AppClients Add(string id, AppClient client) { Guard.NotNullOrEmpty(id, nameof(id)); + Guard.NotNull(client, nameof(client)); + + if (ContainsKey(id)) + { + throw new ArgumentException("Id already exists.", nameof(id)); + } - return new AppClients(Inner.Add(id, new AppClient(id, secret, Role.Editor))); + return new AppClients(With(id, client)); } [Pure] - public AppClients Revoke(string id) + public AppClients Add(string id, string secret) { Guard.NotNullOrEmpty(id, nameof(id)); - return new AppClients(Inner.Remove(id)); + if (ContainsKey(id)) + { + throw new ArgumentException("Id already exists.", nameof(id)); + } + + return new AppClients(With(id, new AppClient(id, secret, Role.Editor))); } [Pure] @@ -60,7 +71,7 @@ namespace Squidex.Domain.Apps.Core.Apps return this; } - return new AppClients(Inner.SetItem(id, client.Rename(newName))); + return new AppClients(With(id, client.Rename(newName))); } [Pure] @@ -73,7 +84,7 @@ namespace Squidex.Domain.Apps.Core.Apps return this; } - return new AppClients(Inner.SetItem(id, client.Update(role))); + return new AppClients(With(id, client.Update(role))); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs index e3bd81ab4..ee54ae6fb 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs @@ -5,23 +5,23 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; +using System.Collections.Generic; using System.Diagnostics.Contracts; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; namespace Squidex.Domain.Apps.Core.Apps { - public sealed class AppContributors : DictionaryWrapper + public sealed class AppContributors : ArrayDictionary { public static readonly AppContributors Empty = new AppContributors(); private AppContributors() - : base(ImmutableDictionary.Empty) { } - public AppContributors(ImmutableDictionary inner) - : base(inner) + public AppContributors(KeyValuePair[] items) + : base(items) { } @@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.Apps Guard.NotNullOrEmpty(contributorId, nameof(contributorId)); Guard.NotNullOrEmpty(role, nameof(role)); - return new AppContributors(Inner.SetItem(contributorId, role)); + return new AppContributors(With(contributorId, role)); } [Pure] @@ -39,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Apps { Guard.NotNullOrEmpty(contributorId, nameof(contributorId)); - return new AppContributors(Inner.Remove(contributorId)); + return new AppContributors(Without(contributorId)); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs index e0ce032e3..cb9e13d3d 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppPatterns.cs @@ -4,39 +4,45 @@ // Copyright (c) Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== + using System; -using System.Collections.Immutable; +using System.Collections.Generic; using System.Diagnostics.Contracts; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; namespace Squidex.Domain.Apps.Core.Apps { - public sealed class AppPatterns : DictionaryWrapper + public sealed class AppPatterns : ArrayDictionary { public static readonly AppPatterns Empty = new AppPatterns(); private AppPatterns() - : base(ImmutableDictionary.Empty) { } - public AppPatterns(ImmutableDictionary inner) - : base(inner) + public AppPatterns(KeyValuePair[] items) + : base(items) { } [Pure] - public AppPatterns Add(Guid id, string name, string pattern, string message) + public AppPatterns Remove(Guid id) { - var newPattern = new AppPattern(name, pattern, message); - - return new AppPatterns(Inner.Add(id, newPattern)); + return new AppPatterns(Without(id)); } [Pure] - public AppPatterns Remove(Guid id) + public AppPatterns Add(Guid id, string name, string pattern, string message) { - return new AppPatterns(Inner.Remove(id)); + var newPattern = new AppPattern(name, pattern, message); + + if (ContainsKey(id)) + { + throw new ArgumentException("Id already exists.", nameof(id)); + } + + return new AppPatterns(With(id, newPattern)); } [Pure] @@ -50,7 +56,7 @@ namespace Squidex.Domain.Apps.Core.Apps return this; } - return new AppPatterns(Inner.SetItem(id, appPattern.Update(name, pattern, message))); + return new AppPatterns(With(id, appPattern.Update(name, pattern, message))); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs index 3da12f586..bde833f22 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using Newtonsoft.Json; using Squidex.Infrastructure.Json; @@ -31,7 +31,12 @@ namespace Squidex.Domain.Apps.Core.Apps.Json { var json = serializer.Deserialize>(reader); - return new AppClients(json.ToImmutableDictionary(x => x.Key, x => x.Value.ToClient())); + return new AppClients(json.Select(Convert).ToArray()); + } + + private static KeyValuePair Convert(KeyValuePair kvp) + { + return new KeyValuePair(kvp.Key, kvp.Value.ToClient()); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs index b3955699f..997bcfe11 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using Newtonsoft.Json; using Squidex.Infrastructure.Json; @@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.Apps.Json { var json = serializer.Deserialize>(reader); - return new AppContributors(json.ToImmutableDictionary()); + return new AppContributors(json.ToArray()); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs index 20ae7248c..34a23812e 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs @@ -4,9 +4,10 @@ // Copyright (c) Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== + using System; using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using Newtonsoft.Json; using Squidex.Infrastructure.Json; @@ -30,7 +31,12 @@ namespace Squidex.Domain.Apps.Core.Apps.Json { var json = serializer.Deserialize>(reader); - return new AppPatterns(json.ToImmutableDictionary(x => x.Key, x => x.Value.ToPattern())); + return new AppPatterns(json.Select(Convert).ToArray()); + } + + private static KeyValuePair Convert(KeyValuePair kvp) + { + return new KeyValuePair(kvp.Key, kvp.Value.ToPattern()); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs index b33285923..043c2b4af 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs @@ -10,7 +10,6 @@ using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Security; using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; namespace Squidex.Domain.Apps.Core.Apps.Json @@ -33,7 +32,12 @@ namespace Squidex.Domain.Apps.Core.Apps.Json { var json = serializer.Deserialize>(reader); - return new Roles(json.ToImmutableDictionary(x => x.Key, x => new Role(x.Key, new PermissionSet(x.Value)))); + return new Roles(json.Select(Convert).ToArray()); + } + + private static KeyValuePair Convert(KeyValuePair kvp) + { + return new KeyValuePair(kvp.Key, new Role(kvp.Key, new PermissionSet(kvp.Value))); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs index 05ce64873..ac4bffde9 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs @@ -14,7 +14,6 @@ namespace Squidex.Domain.Apps.Core.Apps { public sealed class LanguageConfig : IFieldPartitionItem { - private static readonly Language[] DefaultFallback = Array.Empty(); private readonly Language language; private readonly Language[] languageFallbacks; @@ -57,7 +56,7 @@ namespace Squidex.Domain.Apps.Core.Apps IsOptional = isOptional; this.language = language; - this.languageFallbacks = fallback ?? DefaultFallback; + this.languageFallbacks = fallback ?? Array.Empty(); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs index 51003278f..8a9d6febe 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs @@ -8,10 +8,10 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Immutable; using System.Diagnostics.Contracts; using System.Linq; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; namespace Squidex.Domain.Apps.Core.Apps { @@ -19,7 +19,7 @@ namespace Squidex.Domain.Apps.Core.Apps { public static readonly LanguagesConfig English = Build(Language.EN); - private readonly ImmutableDictionary languages; + private readonly ArrayDictionary languages; private readonly LanguageConfig master; public LanguageConfig Master @@ -47,7 +47,7 @@ namespace Squidex.Domain.Apps.Core.Apps get { return languages.Count; } } - private LanguagesConfig(ImmutableDictionary languages, LanguageConfig master, bool checkMaster = true) + private LanguagesConfig(ArrayDictionary languages, LanguageConfig master, bool checkMaster = true) { if (checkMaster) { @@ -74,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Apps { Guard.NotNull(configs, nameof(configs)); - return new LanguagesConfig(configs.ToImmutableDictionary(x => x.Language), configs.FirstOrDefault()); + return new LanguagesConfig(configs.ToArrayDictionary(x => x.Language), configs.FirstOrDefault()); } public static LanguagesConfig Build(params LanguageConfig[] configs) @@ -100,7 +100,12 @@ namespace Squidex.Domain.Apps.Core.Apps { Guard.NotNull(config, nameof(config)); - return new LanguagesConfig(languages.SetItem(config.Language, config), Master?.Language == config.Language ? config : Master); + var newLanguages = + new ArrayDictionary(languages.With(config.Language, config)); + + var newMaster = Master?.Language == config.Language ? config : Master; + + return new LanguagesConfig(newLanguages, newMaster); } [Pure] @@ -114,7 +119,7 @@ namespace Squidex.Domain.Apps.Core.Apps config.Language, config.IsOptional, config.LanguageFallbacks.Except(new[] { language }))) - .ToImmutableDictionary(x => x.Language); + .ToArrayDictionary(x => x.Language); var newMaster = newLanguages.Values.FirstOrDefault(x => x.Language == Master.Language) ?? diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs index 3c0320f10..58e7c5bfa 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs @@ -6,38 +6,44 @@ // ========================================================================== using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; +using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Diagnostics.Contracts; +using System.Linq; namespace Squidex.Domain.Apps.Core.Apps { - public sealed class Roles : DictionaryWrapper + public sealed class Roles : ArrayDictionary { public static readonly Roles Empty = new Roles(); private Roles() - : base(ImmutableDictionary.Empty) { } - public Roles(ImmutableDictionary inner) - : base(inner) + public Roles(KeyValuePair[] items) + : base(items) { } [Pure] - public Roles Add(string name) + public Roles Remove(string name) { - var newRole = new Role(name); - - return new Roles(Inner.Add(name, newRole)); + return new Roles(Without(name)); } [Pure] - public Roles Remove(string name) + public Roles Add(string name) { - return new Roles(Inner.Remove(name)); + var newRole = new Role(name); + + if (ContainsKey(name)) + { + throw new ArgumentException("Name already exists.", nameof(name)); + } + + return new Roles(With(name, newRole)); } [Pure] @@ -51,7 +57,7 @@ namespace Squidex.Domain.Apps.Core.Apps return this; } - return new Roles(Inner.SetItem(name, role.Update(permissions))); + return new Roles(With(name, role.Update(permissions))); } public static Roles CreateDefaults(string app) @@ -63,7 +69,7 @@ namespace Squidex.Domain.Apps.Core.Apps [Role.Editor] = Role.CreateEditor(app), [Role.Owner] = Role.CreateOwner(app), [Role.Reader] = Role.CreateReader(app) - }.ToImmutableDictionary()); + }.ToArray()); } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/DictionaryWrapper{TKey,TValue}.cs b/src/Squidex.Domain.Apps.Core.Model/DictionaryWrapper{TKey,TValue}.cs deleted file mode 100644 index ee96809e0..000000000 --- a/src/Squidex.Domain.Apps.Core.Model/DictionaryWrapper{TKey,TValue}.cs +++ /dev/null @@ -1,68 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System.Collections; -using System.Collections.Generic; -using System.Collections.Immutable; - -namespace Squidex.Domain.Apps.Core -{ - public abstract class DictionaryWrapper : IReadOnlyDictionary - { - private readonly ImmutableDictionary inner; - - public TValue this[TKey key] - { - get { return inner[key]; } - } - - public IEnumerable Keys - { - get { return inner.Keys; } - } - - public IEnumerable Values - { - get { return inner.Values; } - } - - public int Count - { - get { return inner.Count; } - } - - protected ImmutableDictionary Inner - { - get { return inner; } - } - - protected DictionaryWrapper(ImmutableDictionary inner) - { - this.inner = inner; - } - - public bool ContainsKey(TKey key) - { - return inner.ContainsKey(key); - } - - public bool TryGetValue(TKey key, out TValue value) - { - return inner.TryGetValue(key, out value); - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - return inner.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return inner.GetEnumerator(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTrigger.cs b/src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTrigger.cs index e62138920..a4db365a5 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTrigger.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Rules/Triggers/ContentChangedTrigger.cs @@ -5,15 +5,15 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Squidex.Infrastructure; +using System.Collections.ObjectModel; namespace Squidex.Domain.Apps.Core.Rules.Triggers { [TypeName(nameof(ContentChangedTrigger))] public sealed class ContentChangedTrigger : RuleTrigger { - public ImmutableList Schemas { get; set; } + public ReadOnlyCollection Schemas { get; set; } public bool HandleAll { get; set; } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs index 2e39adc21..0cc74af29 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs @@ -5,8 +5,8 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Squidex.Infrastructure; +using System.Collections.ObjectModel; namespace Squidex.Domain.Apps.Core.Schemas { @@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Core.Schemas public int? AspectHeight { get; set; } - public ImmutableList AllowedExtensions { get; set; } + public ReadOnlyCollection AllowedExtensions { get; set; } public override T Accept(IFieldPropertiesVisitor visitor) { diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs index e1546841d..c4c6627f1 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Diagnostics.Contracts; using System.Linq; using Squidex.Infrastructure; @@ -17,10 +16,13 @@ namespace Squidex.Domain.Apps.Core.Schemas public sealed class FieldCollection : Cloneable> where T : IField { public static readonly FieldCollection Empty = new FieldCollection(); + + private static readonly Dictionary EmptyById = new Dictionary(); + private static readonly Dictionary EmptyByString = new Dictionary(); - private ImmutableArray fieldsOrdered = ImmutableArray.Empty; - private ImmutableDictionary fieldsById; - private ImmutableDictionary fieldsByName; + private T[] fieldsOrdered; + private Dictionary fieldsById; + private Dictionary fieldsByName; public IReadOnlyList Ordered { @@ -35,11 +37,11 @@ namespace Squidex.Domain.Apps.Core.Schemas { if (fieldsOrdered.Length == 0) { - fieldsById = ImmutableDictionary.Empty; + fieldsById = EmptyById; } else { - fieldsById = fieldsOrdered.ToImmutableDictionary(x => x.Id); + fieldsById = fieldsOrdered.ToDictionary(x => x.Id); } } @@ -55,11 +57,11 @@ namespace Squidex.Domain.Apps.Core.Schemas { if (fieldsOrdered.Length == 0) { - fieldsByName = ImmutableDictionary.Empty; + fieldsByName = EmptyByString; } else { - fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); + fieldsByName = fieldsOrdered.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); } } @@ -69,13 +71,14 @@ namespace Squidex.Domain.Apps.Core.Schemas private FieldCollection() { + fieldsOrdered = Array.Empty(); } public FieldCollection(T[] fields) { Guard.NotNull(fields, nameof(fields)); - fieldsOrdered = ImmutableArray.Create(fields); + fieldsOrdered = fields; } protected override void OnCloned() @@ -94,7 +97,7 @@ namespace Squidex.Domain.Apps.Core.Schemas return Clone(clone => { - clone.fieldsOrdered = fieldsOrdered.Remove(field); + clone.fieldsOrdered = fieldsOrdered.Where(x => x.Id != fieldId).ToArray(); }); } @@ -110,7 +113,7 @@ namespace Squidex.Domain.Apps.Core.Schemas return Clone(clone => { - clone.fieldsOrdered = fieldsOrdered.OrderBy(f => ids.IndexOf(f.Id)).ToImmutableArray(); + clone.fieldsOrdered = fieldsOrdered.OrderBy(f => ids.IndexOf(f.Id)).ToArray(); }); } @@ -126,7 +129,7 @@ namespace Squidex.Domain.Apps.Core.Schemas return Clone(clone => { - clone.fieldsOrdered = clone.fieldsOrdered.Add(field); + clone.fieldsOrdered = clone.fieldsOrdered.Union(Enumerable.Repeat(field, 1)).ToArray(); }); } @@ -154,7 +157,7 @@ namespace Squidex.Domain.Apps.Core.Schemas return Clone(clone => { - clone.fieldsOrdered = clone.fieldsOrdered.Replace(field, typedField); + clone.fieldsOrdered = clone.fieldsOrdered.Select(x => ReferenceEquals(x, field) ? newField : x).ToArray(); }); } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs index ebd6f722f..d199a2497 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonFieldModel.cs @@ -6,6 +6,10 @@ // ========================================================================== using Newtonsoft.Json; +using Squidex.Infrastructure; +using System; +using System.Linq; +using P = Squidex.Domain.Apps.Core.Partitioning; namespace Squidex.Domain.Apps.Core.Schemas.Json { @@ -34,5 +38,21 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json [JsonProperty] public JsonNestedFieldModel[] Children { get; set; } + + public RootField ToField() + { + var partitioning = P.FromString(Partitioning); + + if (Properties is ArrayFieldProperties arrayProperties) + { + var nested = Children?.ToArray(n => n.ToNestedField()) ?? Array.Empty(); + + return new ArrayField(Id, Name, partitioning, nested, arrayProperties, this); + } + else + { + return Properties.CreateRootField(Id, Name, partitioning, this); + } + } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs index 50240e695..c7a42baaa 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonNestedFieldModel.cs @@ -30,5 +30,10 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json { get { return false; } } + + public NestedField ToNestedField() + { + return Properties.CreateNestedField(Id, Name, this); + } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs index 7e27ef756..4b0b9e917 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/JsonSchemaModel.cs @@ -14,8 +14,6 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json { public sealed class JsonSchemaModel { - private static readonly RootField[] Empty = Array.Empty(); - [JsonProperty] public string Name { get; set; } @@ -73,35 +71,9 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json return null; } - public Schema ToSchema(FieldRegistry registry) + public Schema ToSchema() { - var fields = Empty; - - if (Fields != null) - { - fields = Fields.ToArray(fieldModel => - { - var parititonKey = new Partitioning(fieldModel.Partitioning); - - RootField field; - - if (fieldModel.Properties is ArrayFieldProperties arrayProperties && fieldModel.Children?.Length > 0) - { - var nestedFields = fieldModel.Children.ToArray(nestedFieldModel => - { - return registry.CreateNestedField(nestedFieldModel.Id, nestedFieldModel.Name, nestedFieldModel.Properties, nestedFieldModel); - }); - - field = new ArrayField(fieldModel.Id, fieldModel.Name, parititonKey, nestedFields, arrayProperties, fieldModel); - } - else - { - field = registry.CreateRootField(fieldModel.Id, fieldModel.Name, parititonKey, fieldModel.Properties, fieldModel); - } - - return field; - }); - } + var fields = Fields.ToArray(f => f.ToField()) ?? Array.Empty(); return new Schema(Name, fields, Properties, IsPublished); } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs index 356f5bb1d..3ca34038b 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs @@ -14,15 +14,6 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json { public sealed class SchemaConverter : JsonClassConverter { - private readonly FieldRegistry fieldRegistry; - - public SchemaConverter(FieldRegistry fieldRegistry) - { - Guard.NotNull(fieldRegistry, nameof(fieldRegistry)); - - this.fieldRegistry = fieldRegistry; - } - protected override void WriteValue(JsonWriter writer, Schema value, JsonSerializer serializer) { serializer.Serialize(writer, new JsonSchemaModel(value)); @@ -30,7 +21,7 @@ namespace Squidex.Domain.Apps.Core.Schemas.Json protected override Schema ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) { - return serializer.Deserialize(reader).ToSchema(fieldRegistry); + return serializer.Deserialize(reader).ToSchema(); } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs index e16a47f28..f4df67c4d 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs @@ -5,15 +5,15 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Squidex.Infrastructure; +using System.Collections.ObjectModel; namespace Squidex.Domain.Apps.Core.Schemas { [TypeName("NumberField")] public sealed class NumberFieldProperties : FieldProperties { - public ImmutableList AllowedValues { get; set; } + public ReadOnlyCollection AllowedValues { get; set; } public double? MaxValue { get; set; } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs index eaee1f7a5..e5c6d3fd6 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs @@ -5,15 +5,15 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Squidex.Infrastructure; +using System.Collections.ObjectModel; namespace Squidex.Domain.Apps.Core.Schemas { [TypeName("StringField")] public sealed class StringFieldProperties : FieldProperties { - public ImmutableList AllowedValues { get; set; } + public ReadOnlyCollection AllowedValues { get; set; } public int? MinLength { get; set; } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs index a1c1f822e..aeaf2074a 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs @@ -6,14 +6,14 @@ // ========================================================================== using Squidex.Infrastructure; -using System.Collections.Immutable; +using System.Collections.ObjectModel; namespace Squidex.Domain.Apps.Core.Schemas { [TypeName("TagsField")] public sealed class TagsFieldProperties : FieldProperties { - public ImmutableList AllowedValues { get; set; } + public ReadOnlyCollection AllowedValues { get; set; } public int? MinItems { get; set; } diff --git a/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/StringFieldBuilder.cs b/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/StringFieldBuilder.cs index 4a798f72b..0fd4b857b 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/StringFieldBuilder.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/Templates/Builders/StringFieldBuilder.cs @@ -5,9 +5,9 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas.Commands; +using Squidex.Infrastructure.Collections; namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders { @@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates.Builders public StringFieldBuilder AsDropDown(params string[] values) { - Properties().AllowedValues = ImmutableList.Create(values); + Properties().AllowedValues = ReadOnlyCollection.Create(values); Properties().Editor = StringFieldEditor.Dropdown; return this; diff --git a/src/Squidex.Infrastructure/CollectionExtensions.cs b/src/Squidex.Infrastructure/CollectionExtensions.cs index 1d26ce8b4..442cb65a2 100644 --- a/src/Squidex.Infrastructure/CollectionExtensions.cs +++ b/src/Squidex.Infrastructure/CollectionExtensions.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; namespace Squidex.Infrastructure @@ -21,37 +20,6 @@ namespace Squidex.Infrastructure return enumerable.OrderBy(x => random.Next()).ToList(); } - public static ImmutableDictionary SetItem(this ImmutableDictionary dictionary, TKey key, Func updater) - { - if (dictionary.TryGetValue(key, out var value)) - { - var newValue = updater(value); - - if (!Equals(newValue, value)) - { - return dictionary.SetItem(key, newValue); - } - } - - return dictionary; - } - - public static bool TryGetValue(this IReadOnlyDictionary values, TKey key, out TBase item) where TValue : TBase - { - if (values.TryGetValue(key, out var value)) - { - item = value; - - return true; - } - else - { - item = default(TBase); - - return false; - } - } - public static IEnumerable OrEmpty(this IEnumerable source) { return source ?? Enumerable.Empty(); diff --git a/src/Squidex.Infrastructure/Collections/ArrayDictionary.cs b/src/Squidex.Infrastructure/Collections/ArrayDictionary.cs new file mode 100644 index 000000000..1a6f1afd2 --- /dev/null +++ b/src/Squidex.Infrastructure/Collections/ArrayDictionary.cs @@ -0,0 +1,21 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Squidex.Infrastructure.Collections +{ + public static class ArrayDictionary + { + public static ArrayDictionary ToArrayDictionary(this IEnumerable source, Func keyExtractor) + { + return new ArrayDictionary(source.Select(x => new KeyValuePair(keyExtractor(x), x)).ToArray()); + } + } +} diff --git a/src/Squidex.Infrastructure/Collections/ArrayDictionary{TKey,TValue}.cs b/src/Squidex.Infrastructure/Collections/ArrayDictionary{TKey,TValue}.cs new file mode 100644 index 000000000..30f1adc90 --- /dev/null +++ b/src/Squidex.Infrastructure/Collections/ArrayDictionary{TKey,TValue}.cs @@ -0,0 +1,163 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Squidex.Infrastructure.Collections +{ + public class ArrayDictionary : IReadOnlyDictionary + { + private readonly IEqualityComparer keyComparer; + private readonly KeyValuePair[] items; + + public TValue this[TKey key] + { + get + { + if (!TryGetValue(key, out var value)) + { + throw new KeyNotFoundException(); + } + + return value; + } + } + + public IEnumerable Keys + { + get { return items.Select(x => x.Key); } + } + + public IEnumerable Values + { + get { return items.Select(x => x.Value); } + } + + public int Count + { + get { return items.Length; } + } + + public ArrayDictionary() + : this(EqualityComparer.Default, Array.Empty>()) + { + } + + public ArrayDictionary(KeyValuePair[] items) + : this(EqualityComparer.Default, items) + { + } + + public ArrayDictionary(IEqualityComparer keyComparer, KeyValuePair[] items) + { + Guard.NotNull(items, nameof(items)); + Guard.NotNull(keyComparer, nameof(keyComparer)); + + this.items = items; + + this.keyComparer = keyComparer; + } + + public KeyValuePair[] With(TKey key, TValue value) + { + var result = new List>(Math.Max(items.Length, 1)); + + var wasReplaced = false; + + for (var i = 0; i < items.Length; i++) + { + var item = items[i]; + + if (wasReplaced || !keyComparer.Equals(item.Key, key)) + { + result.Add(item); + } + else + { + result.Add(new KeyValuePair(key, value)); + wasReplaced = true; + } + } + + if (!wasReplaced) + { + result.Add(new KeyValuePair(key, value)); + } + + return result.ToArray(); + } + + public KeyValuePair[] Without(TKey key) + { + var result = new List>(Math.Max(items.Length, 1)); + + var wasRemoved = false; + + for (var i = 0; i < items.Length; i++) + { + var item = items[i]; + + if (wasRemoved || !keyComparer.Equals(item.Key, key)) + { + result.Add(item); + } + else + { + wasRemoved = true; + } + } + + return result.ToArray(); + } + + public bool ContainsKey(TKey key) + { + for (var i = 0; i < items.Length; i++) + { + if (keyComparer.Equals(items[i].Key, key)) + { + return true; + } + } + + return false; + } + + public bool TryGetValue(TKey key, out TValue value) + { + for (var i = 0; i < items.Length; i++) + { + if (keyComparer.Equals(items[i].Key, key)) + { + value = items[i].Value; + return true; + } + } + + value = default(TValue); + return false; + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + return GetEnumerable(items).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return items.GetEnumerator(); + } + + private static IEnumerable GetEnumerable(T2[] array) + { + return array; + } + } +} diff --git a/src/Squidex.Infrastructure/Collections/ReadOnlyCollection.cs b/src/Squidex.Infrastructure/Collections/ReadOnlyCollection.cs new file mode 100644 index 000000000..83466a3a0 --- /dev/null +++ b/src/Squidex.Infrastructure/Collections/ReadOnlyCollection.cs @@ -0,0 +1,36 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Squidex.Infrastructure.Collections +{ + public static class ReadOnlyCollection + { + private static class Empties + { + public static readonly ReadOnlyCollection Collection = new ReadOnlyCollection(new List()); + } + + public static ReadOnlyCollection Create(params T[] items) + { + return new ReadOnlyCollection(items.ToList()); + } + + public static ReadOnlyCollection Empty() + { + return Empties.Collection; + } + + public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable source) + { + return new ReadOnlyCollection(source.ToList()); + } + } +} diff --git a/src/Squidex.Infrastructure/StringExtensions.cs b/src/Squidex.Infrastructure/StringExtensions.cs index 55349977a..41b23ac9e 100644 --- a/src/Squidex.Infrastructure/StringExtensions.cs +++ b/src/Squidex.Infrastructure/StringExtensions.cs @@ -15,6 +15,7 @@ namespace Squidex.Infrastructure { public static class StringExtensions { + private const char NullChar = (char)0; private static readonly Regex SlugRegex = new Regex("^[a-z0-9]+(\\-[a-z0-9]+)*$", RegexOptions.Compiled); private static readonly Regex PropertyNameRegex = new Regex("^[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*$", RegexOptions.Compiled); private static readonly Dictionary LowerCaseDiacritics; @@ -325,36 +326,97 @@ namespace Squidex.Infrastructure public static string ToPascalCase(this string value) { + if (string.IsNullOrWhiteSpace(value)) + { + return string.Empty; + } + var sb = new StringBuilder(); - foreach (var part in value.Split(new[] { '-', '_', ' ' }, StringSplitOptions.RemoveEmptyEntries)) + var last = NullChar; + var length = 0; + + for (var i = 0; i < value.Length; i++) { - if (part.Length < 2) + var c = value[i]; + + if (c == '-' || c == '_' || c == ' ') { - sb.Append(part.ToUpper()); + if (last != NullChar) + { + sb.Append(char.ToUpperInvariant(last)); + } + + last = NullChar; + length = 0; } else { - sb.Append(char.ToUpper(part[0])); - sb.Append(part.Substring(1)); + if (length > 1) + { + sb.Append(c); + } + else if (length == 0) + { + last = c; + } + else + { + sb.Append(char.ToUpperInvariant(last)); + sb.Append(c); + + last = NullChar; + } + + length++; } } + if (last != NullChar) + { + sb.Append(char.ToUpperInvariant(last)); + } + return sb.ToString(); } public static string ToKebabCase(this string value) { + if (value.Length == 0) + { + return string.Empty; + } + var sb = new StringBuilder(); - foreach (var part in value.Split(new[] { '-', '_', ' ' }, StringSplitOptions.RemoveEmptyEntries)) + var length = 0; + + for (var i = 0; i < value.Length; i++) { - if (sb.Length > 0) + var c = value[i]; + + if (c == '-' || c == '_' || c == ' ') { - sb.Append("-"); + length = 0; } + else + { + if (length > 0) + { + sb.Append(char.ToLowerInvariant(c)); + } + else + { + if (sb.Length > 0) + { + sb.Append('-'); + } + + sb.Append(char.ToLowerInvariant(c)); + } - sb.Append(part.ToLower()); + length++; + } } return sb.ToString(); @@ -362,16 +424,80 @@ namespace Squidex.Infrastructure public static string ToCamelCase(this string value) { - value = value.ToPascalCase(); + if (value.Length == 0) + { + return string.Empty; + } - if (value.Length < 2) + var sb = new StringBuilder(); + + var last = NullChar; + var length = 0; + + for (var i = 0; i < value.Length; i++) { - return value.ToLower(); + var c = value[i]; + + if (c == '-' || c == '_' || c == ' ') + { + if (last != NullChar) + { + if (sb.Length > 0) + { + sb.Append(char.ToUpperInvariant(last)); + } + else + { + sb.Append(char.ToLowerInvariant(last)); + } + } + + last = NullChar; + length = 0; + } + else + { + if (length > 1) + { + sb.Append(c); + } + else if (length == 0) + { + last = c; + } + else + { + if (sb.Length > 0) + { + sb.Append(char.ToUpperInvariant(last)); + } + else + { + sb.Append(char.ToLowerInvariant(last)); + } + + sb.Append(c); + + last = NullChar; + } + + length++; + } } - else + + if (last != NullChar) { - return char.ToLower(value[0]) + value.Substring(1); + if (sb.Length > 0) + { + sb.Append(char.ToUpperInvariant(last)); + } + else + { + sb.Append(char.ToLowerInvariant(last)); + } } + + return sb.ToString(); } public static string Slugify(this string value, ISet preserveHash = null, bool singleCharDiactric = false, char separator = '-') diff --git a/src/Squidex.Infrastructure/ValidationError.cs b/src/Squidex.Infrastructure/ValidationError.cs index 2ae3c5de4..5d0027514 100644 --- a/src/Squidex.Infrastructure/ValidationError.cs +++ b/src/Squidex.Infrastructure/ValidationError.cs @@ -14,7 +14,6 @@ namespace Squidex.Infrastructure [Serializable] public sealed class ValidationError { - private static readonly string[] FallbackProperties = Array.Empty(); private readonly string message; private readonly string[] propertyNames; @@ -34,7 +33,7 @@ namespace Squidex.Infrastructure this.message = message; - this.propertyNames = propertyNames ?? FallbackProperties; + this.propertyNames = propertyNames ?? Array.Empty(); } public ValidationError WithPrefix(string prefix) diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs index 9aa436d5f..219d42c1a 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs @@ -5,13 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Generic; -using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Linq; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules.Triggers; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers @@ -32,7 +31,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers public override RuleTrigger ToTrigger() { - var schemas = Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchema())).ToImmutableList(); + var schemas = Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchema())).ToReadOnlyCollection(); return new ContentChangedTrigger { HandleAll = HandleAll, Schemas = schemas }; } diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs index e3ce42d5c..f3bdb67bd 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs @@ -5,9 +5,9 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields @@ -81,7 +81,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields if (AllowedExtensions != null) { - result.AllowedExtensions = ImmutableList.Create(AllowedExtensions); + result.AllowedExtensions = ReadOnlyCollection.Create(AllowedExtensions); } return result; diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs index 3a255891c..4a7861b04 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs @@ -5,11 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields @@ -54,7 +54,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields if (AllowedValues != null) { - result.AllowedValues = ImmutableList.Create(AllowedValues); + result.AllowedValues = ReadOnlyCollection.Create(AllowedValues); } return result; diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs index 4451846ca..0722fec99 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs @@ -5,11 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields @@ -64,7 +64,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields if (AllowedValues != null) { - result.AllowedValues = ImmutableList.Create(AllowedValues); + result.AllowedValues = ReadOnlyCollection.Create(AllowedValues); } return result; diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs index 147309749..3a7727107 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs @@ -5,11 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using System.Collections.Immutable; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Reflection; namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields @@ -44,7 +44,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields if (AllowedValues != null) { - result.AllowedValues = ImmutableList.Create(AllowedValues); + result.AllowedValues = ReadOnlyCollection.Create(AllowedValues); } return result; diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index c52abca55..be0d316e6 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -59,7 +59,7 @@ namespace Squidex.Config.Domain new RefTokenConverter(), new RolesConverter(), new RuleConverter(), - new SchemaConverter(FieldRegistry), + new SchemaConverter(), new StringEnumConverter()); settings.NullValueHandling = NullValueHandling.Ignore; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs index 4a97de100..9f95ac4b2 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs @@ -35,13 +35,21 @@ namespace Squidex.Domain.Apps.Core.Model.Apps } [Fact] - public void Should_throw_exception_if_assigning_clients_with_same_id() + public void Should_throw_exception_if_assigning_client_with_same_id() { var clients_1 = clients_0.Add("2", "my-secret"); Assert.Throws(() => clients_1.Add("2", "my-secret")); } + [Fact] + public void Should_throw_exception_if_assigning_client_object_with_same_id() + { + var clients_1 = clients_0.Add("2", "my-secret"); + + Assert.Throws(() => clients_1.Add("2", new AppClient("my-name", "my-secret", "my-role"))); + } + [Fact] public void Should_rename_client() { diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs index 6989b814c..f24fdf033 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/Triggers/ContentChangedTriggerTests.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.Triggers; @@ -17,6 +16,7 @@ using Squidex.Domain.Apps.Events.Contents; using Squidex.Domain.Apps.Events.Rules; using Squidex.Domain.Apps.Events.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.EventSourcing; using Xunit; @@ -85,7 +85,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules.Triggers { var trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Create( + Schemas = ReadOnlyCollection.Create( new ContentChangedTriggerSchema { SendCreate = sendCreate == 1, diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs index c82f95373..36aa3c0e0 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs @@ -7,13 +7,13 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -251,7 +251,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_error_if_image_has_invalid_extension() { - var sut = Field(new AssetsFieldProperties { AllowedExtensions = ImmutableList.Create("mp4") }); + var sut = Field(new AssetsFieldProperties { AllowedExtensions = ReadOnlyCollection.Create("mp4") }); await sut.ValidateAsync(CreateValue(document.AssetId, image.AssetId), errors, ctx); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs index eac18056e..d236198f9 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs @@ -6,11 +6,11 @@ // ========================================================================== using System.Collections.Generic; -using System.Collections.Immutable; using System.Threading.Tasks; using FluentAssertions; using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -73,7 +73,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_errors_if_number_is_not_allowed() { - var sut = Field(new NumberFieldProperties { AllowedValues = ImmutableList.Create(10d) }); + var sut = Field(new NumberFieldProperties { AllowedValues = ReadOnlyCollection.Create(10d) }); await sut.ValidateAsync(CreateValue(20), errors); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs index 87dd5f4f6..46f9a17de 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs @@ -6,11 +6,11 @@ // ========================================================================== using System.Collections.Generic; -using System.Collections.Immutable; using System.Threading.Tasks; using FluentAssertions; using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -73,7 +73,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_errors_if_string_not_allowed() { - var sut = Field(new StringFieldProperties { AllowedValues = ImmutableList.Create("Foo") }); + var sut = Field(new StringFieldProperties { AllowedValues = ReadOnlyCollection.Create("Foo") }); await sut.ValidateAsync(CreateValue("Bar"), errors); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs index e8ec0795c..3b2a4d3c2 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs @@ -6,12 +6,12 @@ // ========================================================================== using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -106,7 +106,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent [Fact] public async Task Should_add_errors_if_value_contains_an_not_allowed_values() { - var sut = Field(new TagsFieldProperties { AllowedValues = ImmutableList.Create("tag-2", "tag-3") }); + var sut = Field(new TagsFieldProperties { AllowedValues = ReadOnlyCollection.Create("tag-2", "tag-3") }); await sut.ValidateAsync(CreateValue("tag-1", "tag-2", null), errors); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs index 354dfa971..6b10c3145 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Collections.Immutable; using System.Linq; using System.Reflection; using Newtonsoft.Json; @@ -16,6 +15,7 @@ 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 Xunit; @@ -44,7 +44,7 @@ namespace Squidex.Domain.Apps.Core new RefTokenConverter(), new RolesConverter(), new RuleConverter(), - new SchemaConverter(new FieldRegistry(typeNameRegistry)), + new SchemaConverter(), new StringEnumConverter()), TypeNameHandling = TypeNameHandling.Auto @@ -85,7 +85,7 @@ namespace Squidex.Domain.Apps.Core .AddReferences(109, "root-references", Partitioning.Invariant, new ReferencesFieldProperties()) .AddString(110, "root-string1", Partitioning.Invariant, - new StringFieldProperties { Label = "My String1", IsRequired = true, AllowedValues = ImmutableList.Create("a", "b") }) + new StringFieldProperties { Label = "My String1", IsRequired = true, AllowedValues = ReadOnlyCollection.Create("a", "b") }) .AddString(111, "root-string2", Partitioning.Invariant, new StringFieldProperties { Hints = "My String1" }) .AddTags(112, "root-tags", Partitioning.Language, diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs index 9307fab0f..1b2b8c81e 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/MongoDb/MongoDbQueryTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Collections.Immutable; using System.Linq; using FakeItEasy; using MongoDB.Bson.Serialization; @@ -20,6 +19,7 @@ using Squidex.Domain.Apps.Entities.MongoDb.Contents; using Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.MongoDb.Queries; using Squidex.Infrastructure.Queries; @@ -46,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.MongoDb schemaDef = new Schema("user") .AddString(1, "firstName", Partitioning.Language, - new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = ImmutableList.Create("1", "2") }) + new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = ReadOnlyCollection.Create("1", "2") }) .AddString(2, "lastName", Partitioning.Language, new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }) .AddBoolean(3, "isAdmin", Partitioning.Invariant, diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs index 8851bdc79..837387d2a 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/GuardRuleTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Collections.Immutable; using System.Threading.Tasks; using FakeItEasy; using Squidex.Domain.Apps.Core.Rules; @@ -15,6 +14,7 @@ using Squidex.Domain.Apps.Entities.Rules.Commands; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Xunit; #pragma warning disable SA1310 // Field names must not contain underscore @@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards { Trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Empty + Schemas = ReadOnlyCollection.Empty() }, Action = null }); @@ -78,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards { Trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Empty + Schemas = ReadOnlyCollection.Empty() }, Action = new TestAction { @@ -105,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards { Trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Empty + Schemas = ReadOnlyCollection.Empty() }, Action = new TestAction { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs index cee1ddb81..4e1f6af25 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Guards/Triggers/ContentChangedTriggerTests.cs @@ -6,11 +6,11 @@ // ========================================================================== using System; -using System.Collections.Immutable; using System.Threading.Tasks; using FakeItEasy; using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers @@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers var trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Create( + Schemas = ReadOnlyCollection.Create( new ContentChangedTriggerSchema() ) }; @@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers { var trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Empty + Schemas = ReadOnlyCollection.Empty() }; var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider); @@ -69,7 +69,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards.Triggers var trigger = new ContentChangedTrigger { - Schemas = ImmutableList.Create( + Schemas = ReadOnlyCollection.Create( new ContentChangedTriggerSchema() ) }; diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs index 80dd4b4d2..eae59aba9 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Collections.Immutable; using System.Threading.Tasks; using FakeItEasy; using Squidex.Domain.Apps.Core.Rules; @@ -16,6 +15,7 @@ using Squidex.Domain.Apps.Entities.Rules.State; using Squidex.Domain.Apps.Entities.TestHelpers; using Squidex.Domain.Apps.Events.Rules; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Log; using Xunit; @@ -191,7 +191,7 @@ namespace Squidex.Domain.Apps.Entities.Rules { var newTrigger = new ContentChangedTrigger { - Schemas = ImmutableList.Empty + Schemas = ReadOnlyCollection.Empty() }; var newAction = new TestAction @@ -206,7 +206,7 @@ namespace Squidex.Domain.Apps.Entities.Rules { var newTrigger = new ContentChangedTrigger { - Schemas = ImmutableList.Empty + Schemas = ReadOnlyCollection.Empty() }; var newAction = new TestAction diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/NumberFieldPropertiesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/NumberFieldPropertiesTests.cs index f9d1c303c..a017a3f51 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/NumberFieldPropertiesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/NumberFieldPropertiesTests.cs @@ -6,11 +6,11 @@ // ========================================================================== using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using FluentAssertions; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties @@ -77,7 +77,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [Fact] public void Should_add_error_if_allowed_values_and_max_value_is_specified() { - var sut = new NumberFieldProperties { MaxValue = 10, AllowedValues = ImmutableList.Create(4d) }; + var sut = new NumberFieldProperties { MaxValue = 10, AllowedValues = ReadOnlyCollection.Create(4d) }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); @@ -91,7 +91,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [Fact] public void Should_add_error_if_allowed_values_and_min_value_is_specified() { - var sut = new NumberFieldProperties { MinValue = 10, AllowedValues = ImmutableList.Create(4d) }; + var sut = new NumberFieldProperties { MinValue = 10, AllowedValues = ReadOnlyCollection.Create(4d) }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); @@ -135,7 +135,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [InlineData(NumberFieldEditor.Stars)] public void Should_add_error_if_inline_editing_is_not_allowed_for_editor(NumberFieldEditor editor) { - var sut = new NumberFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ImmutableList.Create(1.0) }; + var sut = new NumberFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ReadOnlyCollection.Create(1.0) }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); @@ -151,7 +151,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [InlineData(NumberFieldEditor.Dropdown)] public void Should_not_add_error_if_inline_editing_is_allowed_for_editor(NumberFieldEditor editor) { - var sut = new NumberFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ImmutableList.Create(1.0) }; + var sut = new NumberFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ReadOnlyCollection.Create(1.0) }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/StringFieldPropertiesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/StringFieldPropertiesTests.cs index ed5382b4e..ad6faed6a 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/StringFieldPropertiesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/StringFieldPropertiesTests.cs @@ -6,11 +6,11 @@ // ========================================================================== using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using FluentAssertions; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Collections; using Xunit; namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties @@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [Fact] public void Should_add_error_if_allowed_values_and_max_value_is_specified() { - var sut = new StringFieldProperties { MinLength = 10, AllowedValues = ImmutableList.Create("4") }; + var sut = new StringFieldProperties { MinLength = 10, AllowedValues = ReadOnlyCollection.Create("4") }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); @@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [Fact] public void Should_add_error_if_allowed_values_and_min_value_is_specified() { - var sut = new StringFieldProperties { MaxLength = 10, AllowedValues = ImmutableList.Create("4") }; + var sut = new StringFieldProperties { MaxLength = 10, AllowedValues = ReadOnlyCollection.Create("4") }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); @@ -108,7 +108,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [InlineData(StringFieldEditor.TextArea)] public void Should_add_error_if_inline_editing_is_not_allowed_for_editor(StringFieldEditor editor) { - var sut = new StringFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ImmutableList.Create("Value") }; + var sut = new StringFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ReadOnlyCollection.Create("Value") }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); @@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties [InlineData(StringFieldEditor.Slug)] public void Should_not_add_error_if_inline_editing_is_allowed_for_editor(StringFieldEditor editor) { - var sut = new StringFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ImmutableList.Create("Value") }; + var sut = new StringFieldProperties { InlineEditable = true, Editor = editor, AllowedValues = ReadOnlyCollection.Create("Value") }; var errors = FieldPropertiesValidator.Validate(sut).ToList(); diff --git a/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs b/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs index d540ff429..8a2851e74 100644 --- a/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs +++ b/tests/Squidex.Infrastructure.Tests/CollectionExtensionsTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System.Collections.Generic; -using System.Collections.Immutable; using Xunit; namespace Squidex.Infrastructure @@ -275,35 +274,5 @@ namespace Squidex.Infrastructure Assert.Equal(source, target); } - - [Fact] - public void Should_return_same_dictionary_if_item_to_replace_not_found() - { - var dict_0 = ImmutableDictionary.Empty; - var dict_1 = dict_0.SetItem(1, x => x); - - Assert.Same(dict_0, dict_1); - } - - [Fact] - public void Should_return_same_dictionary_if_replaced_item_is_same() - { - var dict_0 = ImmutableDictionary.Empty; - var dict_1 = dict_0.SetItem(1, 1); - var dict_2 = dict_1.SetItem(1, x => x); - - Assert.Same(dict_1, dict_2); - } - - [Fact] - public void Should_return_new_dictionary_if_updated_item_is_different() - { - var dict_0 = ImmutableDictionary.Empty; - var dict_1 = dict_0.SetItem(2, 2); - var dict_2 = dict_1.SetItem(2, x => 2 * x); - - Assert.NotSame(dict_1, dict_2); - Assert.Equal(4, dict_2[2]); - } } } \ No newline at end of file From ca0161543c4133526b78033c5f32e8f46dc10eca Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 25 Nov 2018 15:44:19 +0100 Subject: [PATCH 09/33] Started with json migration. --- .../Apps/Json/AppClientsConverter.cs | 2 +- .../Apps/Json/AppContributorsConverter.cs | 2 +- .../Apps/Json/AppPatternsConverter.cs | 2 +- .../Apps/Json/LanguagesConfigConverter.cs | 2 +- .../Apps/Json/RolesConverter.cs | 2 +- .../Contents/ContentData.cs | 4 +- .../Contents/ContentFieldData.cs | 22 +-- .../Rules/Json/RuleConverter.cs | 2 +- .../Rules/RuleJob.cs | 5 +- .../Schemas/Json/SchemaConverter.cs | 3 +- .../ConvertContent/ContentConverter.cs | 19 +- .../ConvertContent/ContentConverterFlat.cs | 6 +- .../ConvertContent/FieldConverters.cs | 17 +- .../ConvertContent/Value.cs | 4 +- .../ConvertContent/ValueConverters.cs | 22 +-- .../EnrichContent/ContentEnricher.cs | 11 +- .../EnrichContent/DefaultValueFactory.cs | 50 ++--- .../ContentReferencesExtensions.cs | 4 +- .../ExtractReferenceIds/ReferencesCleaner.cs | 36 ++-- .../ReferencesExtensions.cs | 27 ++- .../ReferencesExtractor.cs | 12 +- .../ValueReferencesConverter.cs | 4 +- .../EnrichedEvents/EnrichedEvent.cs | 3 - .../HandleRules/IRuleActionHandler.cs | 7 +- .../HandleRules/RuleActionHandler.cs | 26 +-- .../HandleRules/RuleEventFormatter.cs | 38 ++-- .../HandleRules/RuleService.cs | 19 +- .../ContentWrapper/ContentFieldProperty.cs | 8 +- .../Scripting/ContentWrapper/JsonMapper.cs | 94 ++++------ .../Tags/TagNormalizer.cs | 34 ++-- .../ValidateContent/ContentValidator.cs | 5 +- .../ValidateContent/JsonValueConverter.cs | 175 ++++++++++++++---- .../Validators/FieldValidator.cs | 7 +- .../Validators/ObjectValidator.cs | 2 +- .../ValidateContent/ValidatorsFactory.cs | 4 +- .../EventSourcing/Formatter.cs | 4 +- .../EventSourcing/MongoEvent.cs | 8 +- .../CQRS/Events/RabbitMqEventConsumer.cs | 12 +- .../Assets/AssetFile.cs | 2 - .../DefaultEventDataFormatter.cs | 26 +-- .../EventSourcing/EventData.cs | 6 +- .../Json/IJsonSerializer.cs | 23 +++ .../Json/JsonExtension.cs | 34 ---- .../ClaimsPrincipalConverter.cs | 2 +- .../ConverterContractResolver.cs | 2 +- .../Json/{ => Newtonsoft}/InstantConverter.cs | 2 +- .../{ => Newtonsoft}/JsonClassConverter.cs | 2 +- .../Json/Newtonsoft/JsonValueConverter.cs | 161 ++++++++++++++++ .../{ => Newtonsoft}/LanguageConverter.cs | 2 +- .../{ => Newtonsoft}/NamedGuidIdConverter.cs | 2 +- .../{ => Newtonsoft}/NamedLongIdConverter.cs | 2 +- .../NamedStringIdConverter.cs | 2 +- .../Newtonsoft/NewtonsoftJsonSerializer.cs | 60 ++++++ .../PropertiesBagConverter.cs | 2 +- .../{ => Newtonsoft}/RefTokenConverter.cs | 2 +- .../TypeNameSerializationBinder.cs | 2 +- .../Json/Objects/IJsonValue.cs | 18 ++ .../Json/Objects/JsonArray.cs | 100 ++++++++++ .../Json/Objects/JsonNull.cs | 55 ++++++ .../Json/Objects/JsonObject.cs | 129 +++++++++++++ .../Json/Objects/JsonScalar.cs | 60 ++++++ .../Json/Objects/JsonValue.cs | 114 ++++++++++++ .../Json/Objects/JsonValueType.cs | 19 ++ src/Squidex.Infrastructure/Orleans/J.cs | 6 +- src/Squidex.Infrastructure/Orleans/J{T}.cs | 20 +- .../Model/Apps/AppClientJsonTests.cs | 8 +- .../Model/Apps/AppContributorsJsonTests.cs | 6 +- .../Model/Apps/AppPatternJsonTests.cs | 8 +- .../Model/Apps/AppPlanTests.cs | 10 +- .../Model/Apps/LanguagesConfigJsonTests.cs | 10 +- .../Model/Apps/RolesJsonTests.cs | 8 +- .../Model/Contents/ContentDataTests.cs | 3 +- .../Model/Rules/RuleTests.cs | 8 +- .../Model/Schemas/SchemaTests.cs | 5 +- .../ContentConversionFlatTests.cs | 46 +++-- .../ConvertContent/ContentConversionTests.cs | 6 +- .../ConvertContent/FieldConvertersTests.cs | 90 ++++----- .../ConvertContent/ValueConvertersTests.cs | 36 ++-- .../EnrichContent/ContentEnrichmentTests.cs | 38 ++-- .../ReferenceExtractionTests.cs | 36 ++-- .../HandleRules/RuleEventFormatterTests.cs | 9 +- .../HandleRules/RuleServiceTests.cs | 17 +- .../Scripting/ContentDataObjectTests.cs | 14 +- .../Operations/Tags/TagNormalizerTests.cs | 37 ++-- .../ValidateContent/ArrayFieldTests.cs | 14 +- .../ValidateContent/AssetsFieldTests.cs | 8 +- .../ValidateContent/BooleanFieldTests.cs | 8 +- .../ValidateContent/ContentValidationTests.cs | 15 +- .../ValidateContent/DateTimeFieldTests.cs | 14 +- .../ValidateContent/GeolocationFieldTests.cs | 45 ++--- .../ValidateContent/JsonFieldTests.cs | 8 +- .../ValidateContent/NumberFieldTests.cs | 12 +- .../ValidateContent/ReferencesFieldTests.cs | 8 +- .../ValidateContent/StringFieldTests.cs | 6 +- .../ValidateContent/TagsFieldTests.cs | 8 +- .../ValidationTestExtensions.cs | 6 +- .../TestData.cs | 13 +- .../DefaultEventDataFormatterTests.cs | 14 +- .../EventSourcing/EnvelopeTests.cs | 3 +- .../Json/ClaimsPrincipalConverterTests.cs | 10 +- .../Json/InstantConverterTests.cs | 12 +- .../ConverterContractResolverTests.cs | 6 +- .../Objects/JsonValuesSerializationTests.cs | 113 +++++++++++ .../LanguageTests.cs | 9 +- .../NamedIdTests.cs | 33 ++-- .../Orleans/JsonExternalSerializerTests.cs | 6 + .../PropertiesBagTests.cs | 5 +- .../RefTokenTests.cs | 9 +- .../TestHelpers/JsonHelper.cs | 65 +++---- 109 files changed, 1649 insertions(+), 755 deletions(-) create mode 100644 src/Squidex.Infrastructure/Json/IJsonSerializer.cs delete mode 100644 src/Squidex.Infrastructure/Json/JsonExtension.cs rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/ClaimsPrincipalConverter.cs (97%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/ConverterContractResolver.cs (96%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/InstantConverter.cs (97%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/JsonClassConverter.cs (96%) create mode 100644 src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/LanguageConverter.cs (95%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/NamedGuidIdConverter.cs (96%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/NamedLongIdConverter.cs (96%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/NamedStringIdConverter.cs (96%) create mode 100644 src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/PropertiesBagConverter.cs (97%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/RefTokenConverter.cs (95%) rename src/Squidex.Infrastructure/Json/{ => Newtonsoft}/TypeNameSerializationBinder.cs (96%) create mode 100644 src/Squidex.Infrastructure/Json/Objects/IJsonValue.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonArray.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonNull.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonObject.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonValue.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonValueType.cs rename tests/Squidex.Infrastructure.Tests/Json/{ => Newtonsoft}/ConverterContractResolverTests.cs (94%) create mode 100644 tests/Squidex.Infrastructure.Tests/Json/Objects/JsonValuesSerializationTests.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs index bde833f22..ecaac12c2 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs @@ -9,7 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Domain.Apps.Core.Apps.Json { diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs index 997bcfe11..e72ecc0b0 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs @@ -9,7 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Domain.Apps.Core.Apps.Json { diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs index 34a23812e..465029571 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppPatternsConverter.cs @@ -9,7 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Domain.Apps.Core.Apps.Json { diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs index ed396589d..a229d5593 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs @@ -7,7 +7,7 @@ using System; using Newtonsoft.Json; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Domain.Apps.Core.Apps.Json { diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs index 043c2b4af..51b23d192 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/RolesConverter.cs @@ -6,7 +6,7 @@ // ========================================================================== using Newtonsoft.Json; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; using Squidex.Infrastructure.Security; using System; using System.Collections.Generic; diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs index 2ebc1d054..fcfe4813e 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs @@ -9,7 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using Squidex.Infrastructure; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.Contents { @@ -61,7 +61,7 @@ namespace Squidex.Domain.Apps.Core.Contents { var resultValue = new ContentFieldData(); - foreach (var partitionValue in fieldValue.Value.Where(x => !x.Value.IsNull())) + foreach (var partitionValue in fieldValue.Value.Where(x => x.Value.Type != JsonValueType.Null)) { resultValue[partitionValue.Key] = partitionValue.Value; } diff --git a/src/Squidex.Domain.Apps.Core.Model/Contents/ContentFieldData.cs b/src/Squidex.Domain.Apps.Core.Model/Contents/ContentFieldData.cs index 9f4cf3a75..41afa54f3 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Contents/ContentFieldData.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Contents/ContentFieldData.cs @@ -7,21 +7,24 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json.Linq; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.Contents { - public sealed class ContentFieldData : Dictionary, IEquatable + public sealed class ContentFieldData : Dictionary, IEquatable { - private static readonly JTokenEqualityComparer JTokenEqualityComparer = new JTokenEqualityComparer(); - public ContentFieldData() : base(StringComparer.OrdinalIgnoreCase) { } - public ContentFieldData AddValue(string key, JToken value) + public ContentFieldData AddValue(string key, object value) + { + return AddJsonValue(key, JsonValue.Create(value)); + } + + public ContentFieldData AddJsonValue(string key, IJsonValue value) { Guard.NotNullOrEmpty(key, nameof(key)); @@ -30,11 +33,6 @@ namespace Squidex.Domain.Apps.Core.Contents return this; } - public ContentFieldData AddValue(JToken value) - { - return AddValue(InvariantPartitioning.Instance.Master.Key, value); - } - public override bool Equals(object obj) { return Equals(obj as ContentFieldData); @@ -42,12 +40,12 @@ namespace Squidex.Domain.Apps.Core.Contents public bool Equals(ContentFieldData other) { - return other != null && (ReferenceEquals(this, other) || this.EqualsDictionary(other, EqualityComparer.Default, JTokenEqualityComparer)); + return other != null && (ReferenceEquals(this, other) || this.EqualsDictionary(other)); } public override int GetHashCode() { - return this.DictionaryHashCode(EqualityComparer.Default, JTokenEqualityComparer); + return this.DictionaryHashCode(); } } } \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Rules/Json/RuleConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Rules/Json/RuleConverter.cs index e9b8b77e4..7ffd04107 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Rules/Json/RuleConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Rules/Json/RuleConverter.cs @@ -7,7 +7,7 @@ using System; using Newtonsoft.Json; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Domain.Apps.Core.Rules.Json { diff --git a/src/Squidex.Domain.Apps.Core.Model/Rules/RuleJob.cs b/src/Squidex.Domain.Apps.Core.Model/Rules/RuleJob.cs index c83cf9626..811cd51f5 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Rules/RuleJob.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Rules/RuleJob.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using Newtonsoft.Json.Linq; using NodaTime; namespace Squidex.Domain.Apps.Core.Rules @@ -23,12 +22,12 @@ namespace Squidex.Domain.Apps.Core.Rules public string ActionName { get; set; } + public string ActionData { get; set; } + public string Description { get; set; } public Instant Created { get; set; } public Instant Expires { get; set; } - - public JObject ActionData { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs index 3ca34038b..8cd129428 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs @@ -7,8 +7,7 @@ using System; using Newtonsoft.Json; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Domain.Apps.Core.Schemas.Json { diff --git a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs index de8e250a7..8a9ba47cc 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs @@ -7,13 +7,12 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Text; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ConvertContent { @@ -41,11 +40,11 @@ namespace Squidex.Domain.Apps.Core.ConvertContent return result; } - private static void AppendText(JToken value, StringBuilder stringBuilder, int maxFieldLength, string separator, bool allowObjects) + private static void AppendText(IJsonValue value, StringBuilder stringBuilder, int maxFieldLength, string separator, bool allowObjects) { - if (value?.Type == JTokenType.String) + if (value.Type == JsonValueType.String) { - var text = ((JValue)value).ToString(CultureInfo.InvariantCulture); + var text = value.ToString(); if (text.Length <= maxFieldLength) { @@ -57,18 +56,18 @@ namespace Squidex.Domain.Apps.Core.ConvertContent stringBuilder.Append(text); } } - else if (value?.Type == JTokenType.Array) + else if (value is JsonArray array) { - foreach (var item in value) + foreach (var item in array) { AppendText(item, stringBuilder, maxFieldLength, separator, true); } } - else if (value?.Type == JTokenType.Object && allowObjects) + else if (value is JsonObject obj && allowObjects) { - foreach (JProperty property in value) + foreach (var item in obj.Values) { - AppendText(property.Value, stringBuilder, maxFieldLength, separator, true); + AppendText(item, stringBuilder, maxFieldLength, separator, true); } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverterFlat.cs b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverterFlat.cs index 5bff83392..8a6e82895 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverterFlat.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverterFlat.cs @@ -7,10 +7,10 @@ using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ConvertContent { @@ -30,7 +30,7 @@ namespace Squidex.Domain.Apps.Core.ConvertContent languagePreferences = languagePreferences.Union(languageConfig.LanguageFallbacks).ToList(); } - var result = new Dictionary(); + var result = new Dictionary(); foreach (var fieldValue in content) { @@ -38,7 +38,7 @@ namespace Squidex.Domain.Apps.Core.ConvertContent foreach (var language in languagePreferences) { - if (fieldData.TryGetValue(language, out var value) && value != null) + if (fieldData.TryGetValue(language, out var value) && value.Type != JsonValueType.Null) { result[fieldValue.Key] = value; diff --git a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs index 3ccbaf753..1052b8941 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs @@ -8,13 +8,12 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent; using Squidex.Infrastructure; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; #pragma warning disable RECS0002 // Convert anonymous method to method group @@ -44,7 +43,7 @@ namespace Squidex.Domain.Apps.Core.ConvertContent { foreach (var value in data.Values) { - if (value.IsNull()) + if (value.Type == JsonValueType.Null) { continue; } @@ -78,13 +77,13 @@ namespace Squidex.Domain.Apps.Core.ConvertContent { foreach (var partition in data) { - if (partition.Value is JArray array) + if (partition.Value is JsonArray array) { for (var i = 0; i < array.Count; i++) { var id = array[i].ToString(); - array[i] = urlGenerator.GenerateUrl(id); + array[i] = JsonValue.Create(urlGenerator.GenerateUrl(id)); } } } @@ -273,16 +272,16 @@ namespace Squidex.Domain.Apps.Core.ConvertContent foreach (var partition in data) { - if (!(partition.Value is JArray jArray)) + if (!(partition.Value is JsonArray array)) { continue; } - var newArray = new JArray(); + var newArray = JsonValue.Array(); - foreach (var item in jArray.OfType()) + foreach (var item in array.OfType()) { - var newItem = new JObject(); + var newItem = JsonValue.Object(); foreach (var kvp in item) { diff --git a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/Value.cs b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/Value.cs index 2229afdfa..a83740e60 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/Value.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/Value.cs @@ -5,12 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ConvertContent { public static class Value { - public static readonly JToken Unset = JValue.CreateUndefined(); + public static readonly IJsonValue Unset = JsonValue.Create("UNSET"); } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs index 343077c38..2db70c052 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ValueConverters.cs @@ -7,41 +7,41 @@ using System; using System.Text; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent; using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ConvertContent { - public delegate JToken ValueConverter(JToken value, IField field); + public delegate IJsonValue ValueConverter(IJsonValue value, IField field); public static class ValueConverters { - public static ValueConverter DecodeJson() + public static ValueConverter DecodeJson(IJsonSerializer jsonSerializer) { return (value, field) => { - if (!value.IsNull() && field is IField) + if (field is IField && value is JsonScalar s) { - var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(value.ToString())); + var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(s.Value)); - return JToken.Parse(decoded); + return jsonSerializer.Deserialize(decoded); } return value; }; } - public static ValueConverter EncodeJson() + public static ValueConverter EncodeJson(IJsonSerializer jsonSerializer) { return (value, field) => { - if (!value.IsNull() && field is IField) + if (value.Type != JsonValueType.Null && field is IField) { - var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(value.ToString())); + var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonSerializer.Serialize(value))); - return encoded; + return JsonValue.Create(encoded); } return value; @@ -57,7 +57,7 @@ namespace Squidex.Domain.Apps.Core.ConvertContent { return (value, field) => { - if (value.IsNull()) + if (value.Type == JsonValueType.Null) { return value; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs index 2460a2c00..22f88bb85 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs @@ -5,12 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.EnrichContent { @@ -56,7 +55,7 @@ namespace Squidex.Domain.Apps.Core.EnrichContent var defaultValue = DefaultValueFactory.CreateDefaultValue(field, SystemClock.Instance.GetCurrentInstant()); - if (field.RawProperties.IsRequired || defaultValue.IsNull()) + if (field.RawProperties.IsRequired || defaultValue.Type == JsonValueType.Null) { return; } @@ -65,13 +64,13 @@ namespace Squidex.Domain.Apps.Core.EnrichContent if (!fieldData.TryGetValue(key, out var value) || ShouldApplyDefaultValue(field, value)) { - fieldData.AddValue(key, defaultValue); + fieldData.AddJsonValue(key, defaultValue); } } - private static bool ShouldApplyDefaultValue(IField field, JToken value) + private static bool ShouldApplyDefaultValue(IField field, IJsonValue value) { - return value.IsNull() || (field is IField && value is JValue jValue && Equals(jValue.Value, string.Empty)); + return value.Type == JsonValueType.Null || (field is IField && value is JsonScalar s && string.IsNullOrEmpty(s.Value)); } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs index a4f8be960..0d05fc571 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs @@ -6,14 +6,14 @@ // ========================================================================== using System.Globalization; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.EnrichContent { - public sealed class DefaultValueFactory : IFieldVisitor + public sealed class DefaultValueFactory : IFieldVisitor { private readonly Instant now; @@ -22,71 +22,71 @@ namespace Squidex.Domain.Apps.Core.EnrichContent this.now = now; } - public static JToken CreateDefaultValue(IField field, Instant now) + public static IJsonValue CreateDefaultValue(IField field, Instant now) { Guard.NotNull(field, nameof(field)); return field.Accept(new DefaultValueFactory(now)); } - public JToken Visit(IArrayField field) + public IJsonValue Visit(IArrayField field) { - return new JArray(); + return JsonValue.Array(); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return new JArray(); + return JsonValue.Array(); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return field.Properties.DefaultValue; + return JsonValue.Create(field.Properties.DefaultValue); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return JValue.CreateNull(); + return JsonValue.Null; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return JValue.CreateNull(); + return JsonValue.Object(); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return field.Properties.DefaultValue; + return JsonValue.Create(field.Properties.DefaultValue); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return new JArray(); + return JsonValue.Array(); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return field.Properties.DefaultValue; + return JsonValue.Create(field.Properties.DefaultValue); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { - return new JArray(); + return JsonValue.Array(); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { if (field.Properties.CalculatedDefaultValue == DateTimeCalculatedDefaultValue.Now) { - return now.ToString(); + return JsonValue.Create(now.ToString()); } if (field.Properties.CalculatedDefaultValue == DateTimeCalculatedDefaultValue.Today) { - return now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); + return JsonValue.Create(now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); } - return field.Properties.DefaultValue?.ToString(); + return JsonValue.Create(field.Properties.DefaultValue?.ToString()); } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs index 9d4fddf8d..125d529f2 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ContentReferencesExtensions.cs @@ -11,7 +11,7 @@ using System.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { @@ -32,7 +32,7 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds continue; } - foreach (var partitionValue in fieldData.Where(x => !x.Value.IsNull())) + foreach (var partitionValue in fieldData.Where(x => x.Value.Type != JsonValueType.Null)) { var ids = field.ExtractReferences(partitionValue.Value); diff --git a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs index a817aba20..a7c459a13 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesCleaner.cs @@ -7,44 +7,44 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { - public sealed class ReferencesCleaner : IFieldVisitor + public sealed class ReferencesCleaner : IFieldVisitor { - private readonly JToken value; + private readonly IJsonValue value; private readonly ICollection oldReferences; - private ReferencesCleaner(JToken value, ICollection oldReferences) + private ReferencesCleaner(IJsonValue value, ICollection oldReferences) { this.value = value; this.oldReferences = oldReferences; } - public static JToken CleanReferences(IField field, JToken value, ICollection oldReferences) + public static IJsonValue CleanReferences(IField field, IJsonValue value, ICollection oldReferences) { return field.Accept(new ReferencesCleaner(value, oldReferences)); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return CleanIds(); } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { if (oldReferences.Contains(field.Properties.SchemaId)) { - return new JArray(); + return JsonValue.Array(); } return CleanIds(); } - private JToken CleanIds() + private IJsonValue CleanIds() { var ids = value.ToGuidSet(); @@ -55,45 +55,45 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds isRemoved |= ids.Remove(oldReference); } - return isRemoved ? ids.ToJToken() : value; + return isRemoved ? ids.ToJsonArray() : value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IField field) + public IJsonValue Visit(IField field) { return value; } - public JToken Visit(IArrayField field) + public IJsonValue Visit(IArrayField field) { return value; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtensions.cs b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtensions.cs index b7170f9aa..0a701501f 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtensions.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtensions.cs @@ -7,22 +7,21 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { public static class ReferencesExtensions { - public static IEnumerable ExtractReferences(this IField field, JToken value) + public static IEnumerable ExtractReferences(this IField field, IJsonValue value) { return ReferencesExtractor.ExtractReferences(field, value); } - public static JToken CleanReferences(this IField field, JToken value, ICollection oldReferences) + public static IJsonValue CleanReferences(this IField field, IJsonValue value, ICollection oldReferences) { - if (value.IsNull()) + if (value.Type == JsonValueType.Null) { return value; } @@ -30,31 +29,27 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds return ReferencesCleaner.CleanReferences(field, value, oldReferences); } - public static JToken ToJToken(this HashSet ids) + public static JsonArray ToJsonArray(this HashSet ids) { - var result = new JArray(); + var result = JsonValue.Array(); foreach (var id in ids) { - result.Add(new JValue(id)); + result.Add(JsonValue.Create(id.ToString())); } return result; } - public static HashSet ToGuidSet(this JToken value) + public static HashSet ToGuidSet(this IJsonValue value) { - if (value is JArray ids) + if (value is JsonArray array) { var result = new HashSet(); - foreach (var id in ids) + foreach (var id in array) { - if (id.Type == JTokenType.Guid) - { - result.Add((Guid)id); - } - else if (id.Type == JTokenType.String && Guid.TryParse((string)id, out var guid)) + if (id.Type == JsonValueType.String && Guid.TryParse(id.ToString(), out var guid)) { result.Add(guid); } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs index 1f661ef9c..d92b70b86 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ReferencesExtractor.cs @@ -8,21 +8,21 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { public sealed class ReferencesExtractor : IFieldVisitor> { - private readonly JToken value; + private readonly IJsonValue value; - private ReferencesExtractor(JToken value) + private ReferencesExtractor(IJsonValue value) { this.value = value; } - public static IEnumerable ExtractReferences(IField field, JToken value) + public static IEnumerable ExtractReferences(IField field, IJsonValue value) { return field.Accept(new ReferencesExtractor(value)); } @@ -31,9 +31,9 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { var result = new List(); - if (value is JArray items) + if (value is JsonArray array) { - foreach (JObject item in items) + foreach (JsonObject item in array) { foreach (var nestedField in field.Fields) { diff --git a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs index e99459cc7..384a90ccb 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ExtractReferenceIds/ValueReferencesConverter.cs @@ -8,7 +8,7 @@ using System; using System.Collections.Generic; using Squidex.Domain.Apps.Core.ConvertContent; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ExtractReferenceIds { @@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Core.ExtractReferenceIds return (value, field) => { - if (value.IsNull()) + if (value.Type == JsonValueType.Null) { return value; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs index f5d03da66..6c02810a4 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using Newtonsoft.Json; using NodaTime; using Squidex.Infrastructure; using Squidex.Shared.Users; @@ -25,10 +24,8 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents public long Version { get; set; } - [JsonIgnore] public abstract Guid AggregateId { get; } - [JsonIgnore] public IUser User { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleActionHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleActionHandler.cs index deced9228..7ca0dc581 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleActionHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/IRuleActionHandler.cs @@ -7,7 +7,6 @@ using System; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules; @@ -17,8 +16,10 @@ namespace Squidex.Domain.Apps.Core.HandleRules { Type ActionType { get; } - Task<(string Description, JObject Data)> CreateJobAsync(EnrichedEvent @event, RuleAction action); + Type DataType { get; } - Task<(string Dump, Exception Exception)> ExecuteJobAsync(JObject data); + Task<(string Description, object Data)> CreateJobAsync(EnrichedEvent @event, RuleAction action); + + Task<(string Dump, Exception Exception)> ExecuteJobAsync(object data); } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs index 0143f1956..e9632578c 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs @@ -7,7 +7,6 @@ using System; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; @@ -25,6 +24,11 @@ namespace Squidex.Domain.Apps.Core.HandleRules get { return typeof(TAction); } } + Type IRuleActionHandler.DataType + { + get { return typeof(TData); } + } + protected RuleActionHandler(RuleEventFormatter formatter) { Guard.NotNull(formatter, nameof(formatter)); @@ -33,21 +37,11 @@ namespace Squidex.Domain.Apps.Core.HandleRules } protected virtual string ToPayloadJson(T @event) - { - return formatter.ToPayload(@event).ToString(); - } - - protected virtual string ToEnvelopeJson(EnrichedEvent @event) - { - return formatter.ToEnvelope(@event).ToString(); - } - - protected virtual JObject ToPayload(T @event) { return formatter.ToPayload(@event); } - protected virtual JObject ToEnvelope(EnrichedEvent @event) + protected virtual string ToEnvelopeJson(EnrichedEvent @event) { return formatter.ToEnvelope(@event); } @@ -62,16 +56,16 @@ namespace Squidex.Domain.Apps.Core.HandleRules return formatter.Format(text, @event); } - async Task<(string Description, JObject Data)> IRuleActionHandler.CreateJobAsync(EnrichedEvent @event, RuleAction action) + async Task<(string Description, object Data)> IRuleActionHandler.CreateJobAsync(EnrichedEvent @event, RuleAction action) { var (description, data) = await CreateJobAsync(@event, (TAction)action); - return (description, JObject.FromObject(data)); + return (description, data); } - async Task<(string Dump, Exception Exception)> IRuleActionHandler.ExecuteJobAsync(JObject data) + async Task<(string Dump, Exception Exception)> IRuleActionHandler.ExecuteJobAsync(object data) { - var typedData = data.ToObject(); + var typedData = (TData)data; return await ExecuteJobAsync(typedData); } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs index 895a722ae..8f3bb8919 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs @@ -10,11 +10,11 @@ using System.Collections.Generic; using System.Globalization; using System.Text; using System.Text.RegularExpressions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; using Squidex.Shared.Users; namespace Squidex.Domain.Apps.Core.HandleRules @@ -27,15 +27,15 @@ namespace Squidex.Domain.Apps.Core.HandleRules private static readonly Regex ContentDataPlaceholderOld = new Regex(@"^CONTENT_DATA(\.([0-9A-Za-z\-_]*)){2,}", RegexOptions.Compiled); private static readonly Regex ContentDataPlaceholderNew = new Regex(@"^\{CONTENT_DATA(\.([0-9A-Za-z\-_]*)){2,}\}", RegexOptions.Compiled); private readonly List<(char[] Pattern, Func Replacer)> patterns = new List<(char[] Pattern, Func Replacer)>(); - private readonly JsonSerializer serializer; + private readonly IJsonSerializer jsonSerializer; private readonly IRuleUrlGenerator urlGenerator; - public RuleEventFormatter(JsonSerializer serializer, IRuleUrlGenerator urlGenerator) + public RuleEventFormatter(IJsonSerializer jsonSerializer, IRuleUrlGenerator urlGenerator) { - Guard.NotNull(serializer, nameof(serializer)); + Guard.NotNull(jsonSerializer, nameof(jsonSerializer)); Guard.NotNull(urlGenerator, nameof(urlGenerator)); - this.serializer = serializer; + this.jsonSerializer = jsonSerializer; this.urlGenerator = urlGenerator; AddPattern("APP_ID", AppId); @@ -55,17 +55,14 @@ namespace Squidex.Domain.Apps.Core.HandleRules patterns.Add((placeholder.ToCharArray(), generator)); } - public virtual JObject ToPayload(T @event) + public virtual string ToPayload(T @event) { - return JObject.FromObject(@event, serializer); + return jsonSerializer.Serialize(@event); } - public virtual JObject ToEnvelope(EnrichedEvent @event) + public virtual string ToEnvelope(EnrichedEvent @event) { - return new JObject( - new JProperty("type", @event.Name), - new JProperty("payload", ToPayload(@event)), - new JProperty("timestamp", @event.Timestamp.ToString())); + return jsonSerializer.Serialize(new { type = @event.Name, payload = @event, timestamp = @event.Timestamp }); } public string Format(string text, EnrichedEvent @event) @@ -264,14 +261,14 @@ namespace Squidex.Domain.Apps.Core.HandleRules for (var j = 2; j < path.Length; j++) { - if (value is JObject obj && obj.TryGetValue(path[j], out value)) + if (value is JsonObject obj && obj.TryGetValue(path[j], out value)) { continue; } - if (value is JArray arr && int.TryParse(path[j], out var idx) && idx >= 0 && idx < arr.Count) + if (value is JsonArray array && int.TryParse(path[j], out var idx) && idx >= 0 && idx < array.Count) { - value = arr[idx]; + value = array[idx]; } else { @@ -279,17 +276,12 @@ namespace Squidex.Domain.Apps.Core.HandleRules } } - if (value == null || value.Type == JTokenType.Null || value.Type == JTokenType.Undefined) + if (value == null || value.Type == JsonValueType.Null) { return Undefined; } - if (value is JValue jValue) - { - return jValue.Value.ToString(); - } - - return value.ToString(Formatting.Indented) ?? Undefined; + return value.ToString() ?? Undefined; } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs index 18329060a..e85ca990d 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs @@ -11,12 +11,12 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Events; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Core.HandleRules { @@ -26,15 +26,18 @@ namespace Squidex.Domain.Apps.Core.HandleRules private readonly Dictionary ruleTriggerHandlers; private readonly TypeNameRegistry typeNameRegistry; private readonly IEventEnricher eventEnricher; + private readonly IJsonSerializer jsonSerializer; private readonly IClock clock; public RuleService( IEnumerable ruleTriggerHandlers, IEnumerable ruleActionHandlers, IEventEnricher eventEnricher, + IJsonSerializer jsonSerializer, IClock clock, TypeNameRegistry typeNameRegistry) { + Guard.NotNull(jsonSerializer, nameof(jsonSerializer)); Guard.NotNull(ruleTriggerHandlers, nameof(ruleTriggerHandlers)); Guard.NotNull(ruleActionHandlers, nameof(ruleActionHandlers)); Guard.NotNull(typeNameRegistry, nameof(typeNameRegistry)); @@ -48,6 +51,8 @@ namespace Squidex.Domain.Apps.Core.HandleRules this.eventEnricher = eventEnricher; + this.jsonSerializer = jsonSerializer; + this.clock = clock; } @@ -104,11 +109,13 @@ namespace Squidex.Domain.Apps.Core.HandleRules var actionName = typeNameRegistry.GetName(actionType); var actionData = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action); + var json = jsonSerializer.Serialize(actionData); + var job = new RuleJob { JobId = Guid.NewGuid(), ActionName = actionName, - ActionData = actionData.Data, + ActionData = json, AggregateId = enrichedEvent.AggregateId, AppId = appEvent.AppId.Id, Created = now, @@ -120,14 +127,18 @@ namespace Squidex.Domain.Apps.Core.HandleRules return job; } - public virtual async Task<(string Dump, RuleResult Result, TimeSpan Elapsed)> InvokeAsync(string actionName, JObject job) + public virtual async Task<(string Dump, RuleResult Result, TimeSpan Elapsed)> InvokeAsync(string actionName, string job) { try { var actionType = typeNameRegistry.GetType(actionName); var actionWatch = Stopwatch.StartNew(); - var result = await ruleActionHandlers[actionType].ExecuteJobAsync(job); + var actionHandler = ruleActionHandlers[actionType]; + + var deserialized = jsonSerializer.Deserialize(job, actionHandler.DataType); + + var result = await actionHandler.ExecuteJobAsync(deserialized); actionWatch.Stop(); diff --git a/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldProperty.cs b/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldProperty.cs index 11ec3918e..ee279b40a 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldProperty.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldProperty.cs @@ -7,14 +7,14 @@ using Jint.Native; using Jint.Runtime.Descriptors; -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper { public sealed class ContentFieldProperty : PropertyDescriptor { private readonly ContentFieldObject contentField; - private JToken contentValue; + private IJsonValue contentValue; private JsValue value; private bool isChanged; @@ -38,7 +38,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper } } - public JToken ContentValue + public IJsonValue ContentValue { get { return contentValue ?? (contentValue = JsonMapper.Map(value)); } } @@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper get { return isChanged; } } - public ContentFieldProperty(ContentFieldObject contentField, JToken contentValue = null) + public ContentFieldProperty(ContentFieldObject contentField, IJsonValue contentValue = null) : base(null, true, true, true) { this.contentField = contentField; diff --git a/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs b/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs index 6ea3cd584..ec9d52054 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs @@ -9,61 +9,52 @@ using System; using Jint; using Jint.Native; using Jint.Native.Object; -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper { public static class JsonMapper { - public static JsValue Map(JToken value, Engine engine) + public static JsValue Map(IJsonValue value, Engine engine) { if (value == null) { return JsValue.Null; } - switch (value.Type) + switch (value) { - case JTokenType.Date: - case JTokenType.Guid: - case JTokenType.String: - case JTokenType.Uri: - case JTokenType.TimeSpan: - return new JsValue((string)value); - case JTokenType.Null: + case JsonNull n: return JsValue.Null; - case JTokenType.Undefined: - return JsValue.Undefined; - case JTokenType.Integer: - return new JsValue((long)value); - case JTokenType.Float: - return new JsValue((double)value); - case JTokenType.Boolean: - return new JsValue((bool)value); - case JTokenType.Object: - return FromObject(value, engine); - case JTokenType.Array: - { - var arr = (JArray)value; - - var target = new JsValue[arr.Count]; - - for (var i = 0; i < arr.Count; i++) - { - target[i] = Map(arr[i], engine); - } - - return engine.Array.Construct(target); - } + case JsonScalar s: + return new JsValue(s.Value); + case JsonScalar b: + return new JsValue(b.Value); + case JsonScalar b: + return new JsValue(b.Value); + case JsonObject obj: + return FromObject(obj, engine); + case JsonArray arr: + return FromArray(arr, engine); } throw new ArgumentException("Invalid json type.", nameof(value)); } - private static JsValue FromObject(JToken value, Engine engine) + private static JsValue FromArray(JsonArray arr, Engine engine) { - var obj = (JObject)value; + var target = new JsValue[arr.Count]; + for (var i = 0; i < arr.Count; i++) + { + target[i] = Map(arr[i], engine); + } + + return engine.Array.Construct(target); + } + + private static JsValue FromObject(JsonObject obj, Engine engine) + { var target = new ObjectInstance(engine); foreach (var property in obj) @@ -74,69 +65,64 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper return target; } - public static JToken Map(JsValue value) + public static IJsonValue Map(JsValue value) { - if (value == null || value.IsNull()) - { - return JValue.CreateNull(); - } - - if (value.IsUndefined()) + if (value == null || value.IsNull() || value.IsUndefined()) { - return JValue.CreateUndefined(); + return JsonValue.Null; } if (value.IsString()) { - return new JValue(value.AsString()); + return JsonValue.Create(value.AsString()); } if (value.IsBoolean()) { - return new JValue(value.AsBoolean()); + return JsonValue.Create(value.AsBoolean()); } if (value.IsNumber()) { - return new JValue(value.AsNumber()); + return JsonValue.Create(value.AsNumber()); } if (value.IsDate()) { - return new JValue(value.AsDate().ToDateTime()); + return JsonValue.Create(value.AsDate().ToString()); } if (value.IsRegExp()) { - return JValue.CreateString(value.AsRegExp().Value?.ToString()); + return JsonValue.Create(value.AsRegExp().Value?.ToString()); } if (value.IsArray()) { var arr = value.AsArray(); - var target = new JArray(); + var result = JsonValue.Array(); for (var i = 0; i < arr.GetLength(); i++) { - target.Add(Map(arr.Get(i.ToString()))); + result.Add(Map(arr.Get(i.ToString()))); } - return target; + return result; } if (value.IsObject()) { var obj = value.AsObject(); - var target = new JObject(); + var result = JsonValue.Object(); foreach (var kvp in obj.GetOwnProperties()) { - target[kvp.Key] = Map(kvp.Value.Value); + result[kvp.Key] = Map(kvp.Value.Value); } - return target; + return result; } throw new ArgumentException("Invalid json type.", nameof(value)); diff --git a/src/Squidex.Domain.Apps.Core.Operations/Tags/TagNormalizer.cs b/src/Squidex.Domain.Apps.Core.Operations/Tags/TagNormalizer.cs index ed9cd3f05..7ecac0baf 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Tags/TagNormalizer.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/Tags/TagNormalizer.cs @@ -8,10 +8,10 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.Tags { @@ -24,10 +24,10 @@ namespace Squidex.Domain.Apps.Core.Tags Guard.NotNull(newData, nameof(newData)); var newValues = new HashSet(); - var newArrays = new List(); + var newArrays = new List(); var oldValues = new HashSet(); - var oldArrays = new List(); + var oldArrays = new List(); GetValues(schema, newValues, newArrays, newData); @@ -46,7 +46,7 @@ namespace Squidex.Domain.Apps.Core.Tags { if (normalized.TryGetValue(array[i].ToString(), out var result)) { - array[i] = result; + array[i] = JsonValue.Create(result); } } } @@ -59,7 +59,7 @@ namespace Squidex.Domain.Apps.Core.Tags Guard.NotNull(schema, nameof(schema)); var tagsValues = new HashSet(); - var tagsArrays = new List(); + var tagsArrays = new List(); GetValues(schema, tagsValues, tagsArrays, datas); @@ -73,14 +73,14 @@ namespace Squidex.Domain.Apps.Core.Tags { if (denormalized.TryGetValue(array[i].ToString(), out var result)) { - array[i] = result; + array[i] = JsonValue.Create(result); } } } } } - private static void GetValues(Schema schema, HashSet values, List arrays, params NamedContentData[] datas) + private static void GetValues(Schema schema, HashSet values, List arrays, params NamedContentData[] datas) { foreach (var field in schema.Fields) { @@ -109,14 +109,12 @@ namespace Squidex.Domain.Apps.Core.Tags { foreach (var partition in fieldData) { - if (partition.Value is JArray jArray) + if (partition.Value is JsonArray array) { - foreach (var value in jArray) + foreach (var value in array) { - if (value.Type == JTokenType.Object) + if (value is JsonObject nestedObject) { - var nestedObject = (JObject)value; - if (nestedObject.TryGetValue(nestedField.Name, out var nestedValue)) { ExtractTags(nestedValue, values, arrays); @@ -133,19 +131,19 @@ namespace Squidex.Domain.Apps.Core.Tags } } - private static void ExtractTags(JToken token, ISet values, ICollection arrays) + private static void ExtractTags(IJsonValue value, ISet values, ICollection arrays) { - if (token is JArray jArray) + if (value is JsonArray array) { - foreach (var value in jArray) + foreach (var item in array) { - if (value.Type == JTokenType.String) + if (item.Type == JsonValueType.String) { - values.Add(value.ToString()); + values.Add(item.ToString()); } } - arrays.Add(jArray); + arrays.Add(array); } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidator.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidator.cs index 38517df83..ab089b5d7 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidator.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidator.cs @@ -9,11 +9,11 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent.Validators; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; #pragma warning disable SA1028, IDE0004 // Code must not contain trailing whitespace @@ -22,7 +22,6 @@ namespace Squidex.Domain.Apps.Core.ValidateContent public sealed class ContentValidator { private static readonly ContentFieldData DefaultFieldData = new ContentFieldData(); - private static readonly JToken DefaultValue = JValue.CreateNull(); private readonly Schema schema; private readonly PartitionResolver partitionResolver; private readonly ValidationContext context; @@ -96,7 +95,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent var type = isLanguage ? "language" : "invariant value"; - return new ObjectValidator(fieldsValidators, isPartial, type, DefaultValue); + return new ObjectValidator(fieldsValidators, isPartial, type, JsonValue.Null); } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs index a43f8a095..397ed286f 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/JsonValueConverter.cs @@ -7,45 +7,80 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json.Linq; using NodaTime.Text; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ValidateContent { public sealed class JsonValueConverter : IFieldVisitor { - private readonly JToken value; + private readonly IJsonValue value; - private JsonValueConverter(JToken value) + private JsonValueConverter(IJsonValue value) { this.value = value; } - public static object ConvertValue(IField field, JToken json) + public static object ConvertValue(IField field, IJsonValue json) { return field.Accept(new JsonValueConverter(json)); } public object Visit(IArrayField field) { - return value.ToObject>(); + return ConvertToObjectList(); } public object Visit(IField field) { - return value.ToObject>(); + return ConvertToGuidList(); + } + + public object Visit(IField field) + { + return ConvertToGuidList(); + } + + public object Visit(IField field) + { + return ConvertToStringList(); } public object Visit(IField field) { - return (bool?)value; + if (value is JsonScalar b) + { + return b.Value; + } + + throw new InvalidCastException("Invalid json type, expected boolean."); + } + + public object Visit(IField field) + { + if (value is JsonScalar b) + { + return b.Value; + } + + throw new InvalidCastException("Invalid json type, expected number."); + } + + public object Visit(IField field) + { + if (value is JsonScalar b) + { + return b.Value; + } + + throw new InvalidCastException("Invalid json type, expected string."); } public object Visit(IField field) { - if (value.Type == JTokenType.String) + if (value.Type == JsonValueType.String) { var parseResult = InstantPattern.General.Parse(value.ToString()); @@ -62,31 +97,49 @@ namespace Squidex.Domain.Apps.Core.ValidateContent public object Visit(IField field) { - var geolocation = (JObject)value; - - foreach (var property in geolocation.Properties()) + if (value is JsonObject geolocation) { - if (!string.Equals(property.Name, "latitude", StringComparison.OrdinalIgnoreCase) && - !string.Equals(property.Name, "longitude", StringComparison.OrdinalIgnoreCase)) + foreach (var propertyName in geolocation.Keys) { - throw new InvalidCastException("Geolocation can only have latitude and longitude property."); + if (!string.Equals(propertyName, "latitude", StringComparison.OrdinalIgnoreCase) && + !string.Equals(propertyName, "longitude", StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidCastException("Geolocation can only have latitude and longitude property."); + } } - } - var lat = (double)geolocation["latitude"]; - var lon = (double)geolocation["longitude"]; + if (geolocation.TryGetValue("latitude", out var latValue) && latValue is JsonScalar latNumber) + { + var lat = latNumber.Value; - if (!lat.IsBetween(-90, 90)) - { - throw new InvalidCastException("Latitude must be between -90 and 90."); - } + if (!lat.IsBetween(-90, 90)) + { + throw new InvalidCastException("Latitude must be between -90 and 90."); + } + } + else + { + throw new InvalidCastException("Invalid json type, expected latitude/longitude object."); + } - if (!lon.IsBetween(-180, 180)) - { - throw new InvalidCastException("Longitude must be between -180 and 180."); + if (geolocation.TryGetValue("longitude", out var lonValue) && lonValue is JsonScalar lonNumber) + { + var lon = lonNumber.Value; + + if (!lon.IsBetween(-180, 180)) + { + throw new InvalidCastException("Longitude must be between -180 and 180."); + } + } + else + { + throw new InvalidCastException("Invalid json type, expected latitude/longitude object."); + } + + return value; } - return value; + throw new InvalidCastException("Invalid json type, expected latitude/longitude object."); } public object Visit(IField field) @@ -94,24 +147,76 @@ namespace Squidex.Domain.Apps.Core.ValidateContent return value; } - public object Visit(IField field) + private object ConvertToGuidList() { - return (double?)value; - } + if (value is JsonArray array) + { + var result = new List(); - public object Visit(IField field) - { - return value.ToObject>(); + foreach (var item in array) + { + if (item is JsonScalar s && Guid.TryParse(s.Value, out var guid)) + { + result.Add(guid); + } + else + { + throw new InvalidCastException("Invalid json type, expected array of guid strings."); + } + } + + return result; + } + + throw new InvalidCastException("Invalid json type, expected array of guid strings."); } - public object Visit(IField field) + private object ConvertToStringList() { - return value.ToString(); + if (value is JsonArray array) + { + var result = new List(); + + foreach (var item in array) + { + if (item is JsonScalar s) + { + result.Add(s.Value); + } + else + { + throw new InvalidCastException("Invalid json type, expected array of strings."); + } + } + + return result; + } + + throw new InvalidCastException("Invalid json type, expected array of strings."); } - public object Visit(IField field) + private object ConvertToObjectList() { - return value.ToObject>(); + if (value is JsonArray array) + { + var result = new List(); + + foreach (var item in array) + { + if (item is JsonObject obj) + { + result.Add(obj); + } + else + { + throw new InvalidCastException("Invalid json type, expected array of objects."); + } + } + + return result; + } + + throw new InvalidCastException("Invalid json type, expected array of objects."); } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/FieldValidator.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/FieldValidator.cs index 97471857e..40bf1a89d 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/FieldValidator.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/FieldValidator.cs @@ -7,9 +7,8 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ValidateContent.Validators { @@ -30,9 +29,9 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators { object typedValue = null; - if (value is JToken jToken) + if (value is IJsonValue jsonValue) { - typedValue = jToken.IsNull() ? null : JsonValueConverter.ConvertValue(field, jToken); + typedValue = jsonValue.Type == JsonValueType.Null ? null : JsonValueConverter.ConvertValue(field, jsonValue); } var tasks = new List(); diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs index 6dd8a9c28..429962996 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ObjectValidator.cs @@ -27,7 +27,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators public async Task ValidateAsync(object value, ValidationContext context, AddError addError) { - if (value is IDictionary values) + if (value is IReadOnlyDictionary values) { foreach (var fieldData in values) { diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs index fc104e7e5..3a40a2b61 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs @@ -8,11 +8,11 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent.Validators; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.ValidateContent { @@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent nestedSchema[nestedField.Name] = (false, new FieldValidator(nestedField.Accept(this).ToArray(), nestedField)); } - yield return new CollectionItemValidator(new ObjectValidator(nestedSchema, false, "field", JValue.CreateNull())); + yield return new CollectionItemValidator(new ObjectValidator(nestedSchema, false, "field", JsonValue.Null)); } public IEnumerable Visit(IField field) diff --git a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs index c28abf358..6fdfaa288 100644 --- a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs +++ b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs @@ -32,8 +32,8 @@ namespace Squidex.Infrastructure.EventSourcing public static EventStoreData Write(EventData eventData) { - var body = Encoding.UTF8.GetBytes(eventData.Payload.ToString()); - var meta = Encoding.UTF8.GetBytes(eventData.Metadata.ToString()); + var body = Encoding.UTF8.GetBytes(eventData.Payload); + var meta = Encoding.UTF8.GetBytes(eventData.Metadata); return new EventStoreData(Guid.NewGuid(), eventData.Type, true, body, meta); } diff --git a/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs b/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs index 395fa594f..8748ba8b1 100644 --- a/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs +++ b/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs @@ -5,8 +5,8 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; -using Newtonsoft.Json.Linq; using Squidex.Infrastructure.MongoDb; namespace Squidex.Infrastructure.EventSourcing @@ -23,16 +23,16 @@ namespace Squidex.Infrastructure.EventSourcing [BsonElement] [BsonRequired] - public JToken Metadata { get; set; } + public BsonDocument Metadata { get; set; } public static MongoEvent FromEventData(EventData data) { - return new MongoEvent { Type = data.Type, Metadata = data.Metadata, Payload = data.Payload.ToString() }; + return new MongoEvent { Type = data.Type, Metadata = BsonDocument.Parse(data.Payload), Payload = data.Payload }; } public EventData ToEventData() { - return new EventData { Type = Type, Metadata = Metadata, Payload = JObject.Parse(Payload) }; + return new EventData { Type = Type, Metadata = Metadata.ToJson().ToString(), Payload = Payload }; } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs b/src/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs index 238698bda..b378743c1 100644 --- a/src/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs +++ b/src/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs @@ -9,16 +9,16 @@ using System; using System.Text; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json; using RabbitMQ.Client; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Tasks; namespace Squidex.Infrastructure.CQRS.Events { public sealed class RabbitMqEventConsumer : DisposableObjectBase, IInitializable, IEventConsumer { - private readonly JsonSerializerSettings serializerSettings; + private readonly IJsonSerializer jsonSerializer; private readonly string eventPublisherName; private readonly string exchange; private readonly string eventsFilter; @@ -36,12 +36,12 @@ namespace Squidex.Infrastructure.CQRS.Events get { return eventsFilter; } } - public RabbitMqEventConsumer(JsonSerializerSettings serializerSettings, string eventPublisherName, string uri, string exchange, string eventsFilter) + public RabbitMqEventConsumer(IJsonSerializer jsonSerializer, string eventPublisherName, string uri, string exchange, string eventsFilter) { Guard.NotNullOrEmpty(uri, nameof(uri)); Guard.NotNullOrEmpty(eventPublisherName, nameof(eventPublisherName)); Guard.NotNullOrEmpty(exchange, nameof(exchange)); - Guard.NotNull(serializerSettings, nameof(serializerSettings)); + Guard.NotNull(jsonSerializer, nameof(jsonSerializer)); connectionFactory = new ConnectionFactory { Uri = new Uri(uri, UriKind.Absolute) }; connection = new Lazy(connectionFactory.CreateConnection); @@ -49,8 +49,8 @@ namespace Squidex.Infrastructure.CQRS.Events this.exchange = exchange; this.eventsFilter = eventsFilter; + this.jsonSerializer = jsonSerializer; this.eventPublisherName = eventPublisherName; - this.serializerSettings = serializerSettings; } protected override void DisposeObject(bool disposing) @@ -88,7 +88,7 @@ namespace Squidex.Infrastructure.CQRS.Events public Task On(Envelope @event) { - var jsonString = JsonConvert.SerializeObject(@event, serializerSettings); + var jsonString = jsonSerializer.Serialize(@event); var jsonBytes = Encoding.UTF8.GetBytes(jsonString); channel.Value.BasicPublish(exchange, string.Empty, null, jsonBytes); diff --git a/src/Squidex.Infrastructure/Assets/AssetFile.cs b/src/Squidex.Infrastructure/Assets/AssetFile.cs index bbaa0917d..4f5ef010f 100644 --- a/src/Squidex.Infrastructure/Assets/AssetFile.cs +++ b/src/Squidex.Infrastructure/Assets/AssetFile.cs @@ -7,7 +7,6 @@ using System; using System.IO; -using Newtonsoft.Json; namespace Squidex.Infrastructure.Assets { @@ -21,7 +20,6 @@ namespace Squidex.Infrastructure.Assets public long FileSize { get; } - [JsonConstructor] public AssetFile(string fileName, string mimeType, long fileSize, Func openAction) { Guard.NotNullOrEmpty(fileName, nameof(fileName)); diff --git a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs index 98b7919b1..22735b68d 100644 --- a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs @@ -6,38 +6,38 @@ // ========================================================================== using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json; namespace Squidex.Infrastructure.EventSourcing { public class DefaultEventDataFormatter : IEventDataFormatter { - private readonly JsonSerializer serializer; + private readonly IJsonSerializer serializer; private readonly TypeNameRegistry typeNameRegistry; - public DefaultEventDataFormatter(TypeNameRegistry typeNameRegistry, JsonSerializer serializer = null) + public DefaultEventDataFormatter(TypeNameRegistry typeNameRegistry, IJsonSerializer serializer) { Guard.NotNull(typeNameRegistry, nameof(typeNameRegistry)); + Guard.NotNull(serializer, nameof(serializer)); this.typeNameRegistry = typeNameRegistry; - this.serializer = serializer ?? JsonSerializer.CreateDefault(); + this.serializer = serializer; } public Envelope Parse(EventData eventData, bool migrate = true) { var eventType = typeNameRegistry.GetType(eventData.Type); - var headers = eventData.Metadata.ToObject(serializer); - var content = eventData.Payload.ToObject(eventType, serializer) as IEvent; + var eventHeaders = serializer.Deserialize(eventData.Metadata); + var eventContent = serializer.Deserialize(eventData.Payload, eventType); - if (migrate && content is IMigratedEvent migratedEvent) + if (migrate && eventContent is IMigratedEvent migratedEvent) { - content = migratedEvent.Migrate(); + eventContent = migratedEvent.Migrate(); } - var envelope = new Envelope(content, headers); + var envelope = new Envelope(eventContent, eventHeaders); return envelope; } @@ -55,10 +55,10 @@ namespace Squidex.Infrastructure.EventSourcing envelope.SetCommitId(commitId); - var headers = JToken.FromObject(envelope.Headers, serializer); - var content = JToken.FromObject(envelope.Payload, serializer); + var eventHeaders = serializer.Serialize(envelope.Headers); + var eventContent = serializer.Serialize(envelope.Payload); - return new EventData { Type = eventType, Payload = content, Metadata = headers }; + return new EventData { Type = eventType, Payload = eventContent, Metadata = eventHeaders }; } } } diff --git a/src/Squidex.Infrastructure/EventSourcing/EventData.cs b/src/Squidex.Infrastructure/EventSourcing/EventData.cs index 739ea8068..a3d82188f 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EventData.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EventData.cs @@ -5,15 +5,13 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json.Linq; - namespace Squidex.Infrastructure.EventSourcing { public class EventData { - public JToken Payload { get; set; } + public string Payload { get; set; } - public JToken Metadata { get; set; } + public string Metadata { get; set; } public string Type { get; set; } } diff --git a/src/Squidex.Infrastructure/Json/IJsonSerializer.cs b/src/Squidex.Infrastructure/Json/IJsonSerializer.cs new file mode 100644 index 000000000..e42fb9ea3 --- /dev/null +++ b/src/Squidex.Infrastructure/Json/IJsonSerializer.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.IO; + +namespace Squidex.Infrastructure.Json +{ + public interface IJsonSerializer + { + string Serialize(T value); + + void Serialize(T value, Stream stream); + + T Deserialize(string value, Type actualType = null); + + T Deserialize(Stream stream, Type actualType = null); + } +} diff --git a/src/Squidex.Infrastructure/Json/JsonExtension.cs b/src/Squidex.Infrastructure/Json/JsonExtension.cs deleted file mode 100644 index 23d8cea4c..000000000 --- a/src/Squidex.Infrastructure/Json/JsonExtension.cs +++ /dev/null @@ -1,34 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using Newtonsoft.Json.Linq; - -namespace Squidex.Infrastructure.Json -{ - public static class JsonExtension - { - public static bool IsNull(this JToken token) - { - if (token == null) - { - return true; - } - - if (token.Type == JTokenType.Null) - { - return true; - } - - if (token is JValue value) - { - return value.Value == null; - } - - return false; - } - } -} diff --git a/src/Squidex.Infrastructure/Json/ClaimsPrincipalConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/ClaimsPrincipalConverter.cs similarity index 97% rename from src/Squidex.Infrastructure/Json/ClaimsPrincipalConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/ClaimsPrincipalConverter.cs index c183e6424..bde9e0013 100644 --- a/src/Squidex.Infrastructure/Json/ClaimsPrincipalConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/ClaimsPrincipalConverter.cs @@ -10,7 +10,7 @@ using System.Linq; using System.Security.Claims; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class ClaimsPrincipalConverter : JsonClassConverter { diff --git a/src/Squidex.Infrastructure/Json/ConverterContractResolver.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs similarity index 96% rename from src/Squidex.Infrastructure/Json/ConverterContractResolver.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs index 55609ed0d..e626d5e1d 100644 --- a/src/Squidex.Infrastructure/Json/ConverterContractResolver.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs @@ -9,7 +9,7 @@ using System; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class ConverterContractResolver : CamelCasePropertyNamesContractResolver { diff --git a/src/Squidex.Infrastructure/Json/InstantConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs similarity index 97% rename from src/Squidex.Infrastructure/Json/InstantConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs index deca1ee95..463d24411 100644 --- a/src/Squidex.Infrastructure/Json/InstantConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json; using NodaTime; using NodaTime.Text; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class InstantConverter : JsonConverter { diff --git a/src/Squidex.Infrastructure/Json/JsonClassConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs similarity index 96% rename from src/Squidex.Infrastructure/Json/JsonClassConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs index 954e472dd..078bd451e 100644 --- a/src/Squidex.Infrastructure/Json/JsonClassConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs @@ -8,7 +8,7 @@ using System; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public abstract class JsonClassConverter : JsonConverter where T : class { diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs new file mode 100644 index 000000000..949a3a90c --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -0,0 +1,161 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Globalization; +using System.Linq; +using Newtonsoft.Json; +using Squidex.Infrastructure.Json.Objects; + +namespace Squidex.Infrastructure.Json.Newtonsoft +{ + public sealed class JsonValueConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return typeof(IJsonValue).IsAssignableFrom(objectType); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return ReadJson(reader); + } + + private IJsonValue ReadJson(JsonReader reader) + { + switch (reader.TokenType) + { + case JsonToken.Comment: + reader.Read(); + break; + case JsonToken.StartObject: + { + var result = JsonValue.Object(); + + while (reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.PropertyName: + var propertyName = reader.Value.ToString(); + + if (!reader.Read()) + { + throw new JsonSerializationException("Unexpected end when reading Object."); + } + + var value = ReadJson(reader); + + result[propertyName] = value; + break; + case JsonToken.EndObject: + return result; + } + } + + throw new JsonSerializationException("Unexpected end when reading Object."); + } + + case JsonToken.StartArray: + { + var result = JsonValue.Array(); + + while (reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Comment: + break; + default: + var value = ReadJson(reader); + + result.Add(value); + break; + case JsonToken.EndArray: + return result; + } + } + + throw new JsonSerializationException("Unexpected end when reading Object."); + } + + case JsonToken.Integer: + return JsonValue.Create((long)reader.Value); + case JsonToken.Float: + return JsonValue.Create((double)reader.Value); + case JsonToken.Boolean: + return JsonValue.Create((bool)reader.Value); + case JsonToken.Date: + return JsonValue.Create(((DateTime)reader.Value).ToString("yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture)); + case JsonToken.String: + return JsonValue.Create(reader.Value.ToString()); + case JsonToken.Null: + case JsonToken.Undefined: + return JsonValue.Null; + } + + throw new NotSupportedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + return; + } + + WriteJson(writer, (IJsonValue)value); + } + + private void WriteJson(JsonWriter writer, IJsonValue value) + { + switch (value) + { + case JsonNull n: + writer.WriteNull(); + break; + case JsonScalar s: + writer.WriteValue(s.Value); + break; + case JsonScalar s: + writer.WriteValue(s.Value); + break; + case JsonScalar s: + writer.WriteValue(s.Value); + break; + case JsonArray array: + { + writer.WriteStartArray(); + + foreach (var item in array) + { + WriteJson(writer, item); + } + + writer.WriteEndArray(); + break; + } + + case JsonObject obj: + { + writer.WriteStartObject(); + + foreach (var kvp in obj) + { + writer.WritePropertyName(kvp.Key); + + WriteJson(writer, kvp.Value); + } + + writer.WriteEndObject(); + break; + } + } + } + } +} diff --git a/src/Squidex.Infrastructure/Json/LanguageConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/LanguageConverter.cs similarity index 95% rename from src/Squidex.Infrastructure/Json/LanguageConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/LanguageConverter.cs index c2c11ac78..11d45a037 100644 --- a/src/Squidex.Infrastructure/Json/LanguageConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/LanguageConverter.cs @@ -8,7 +8,7 @@ using System; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class LanguageConverter : JsonClassConverter { diff --git a/src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs similarity index 96% rename from src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs index 1695a96f9..f40e50481 100644 --- a/src/Squidex.Infrastructure/Json/NamedGuidIdConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs @@ -8,7 +8,7 @@ using System; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class NamedGuidIdConverter : JsonClassConverter> { diff --git a/src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs similarity index 96% rename from src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs index cc85acd9b..b90415b71 100644 --- a/src/Squidex.Infrastructure/Json/NamedLongIdConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs @@ -8,7 +8,7 @@ using System; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class NamedLongIdConverter : JsonClassConverter> { diff --git a/src/Squidex.Infrastructure/Json/NamedStringIdConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs similarity index 96% rename from src/Squidex.Infrastructure/Json/NamedStringIdConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs index 3076ef02c..78f39fb1f 100644 --- a/src/Squidex.Infrastructure/Json/NamedStringIdConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs @@ -9,7 +9,7 @@ using System; using System.Linq; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class NamedStringIdConverter : JsonClassConverter> { diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs new file mode 100644 index 000000000..a9a045ed3 --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs @@ -0,0 +1,60 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.IO; +using Newtonsoft.Json; + +namespace Squidex.Infrastructure.Json.Newtonsoft +{ + public sealed class NewtonsoftJsonSerializer : IJsonSerializer + { + private readonly JsonSerializerSettings settings; + private readonly JsonSerializer serializer; + + public NewtonsoftJsonSerializer(JsonSerializerSettings settings) + { + Guard.NotNull(settings, nameof(settings)); + + this.settings = settings; + + serializer = JsonSerializer.Create(settings); + } + + public T Deserialize(string value, Type actualType = null) + { + actualType = actualType ?? typeof(T); + + return (T)JsonConvert.DeserializeObject(value, actualType, settings); + } + + public T Deserialize(Stream stream, Type actualType = null) + { + using (var streamReader = new StreamReader(stream)) + { + actualType = actualType ?? typeof(T); + + return (T)serializer.Deserialize(streamReader, actualType); + } + } + + public string Serialize(T value) + { + return JsonConvert.SerializeObject(value, settings); + } + + public void Serialize(T value, Stream stream) + { + using (var writer = new StreamWriter(stream)) + { + serializer.Serialize(writer, value); + + writer.Flush(); + } + } + } +} diff --git a/src/Squidex.Infrastructure/Json/PropertiesBagConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs similarity index 97% rename from src/Squidex.Infrastructure/Json/PropertiesBagConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs index f42642fb0..27bda90ae 100644 --- a/src/Squidex.Infrastructure/Json/PropertiesBagConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json; using NodaTime; using NodaTime.Extensions; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class PropertiesBagConverter : JsonClassConverter where T : PropertiesBag, new() { diff --git a/src/Squidex.Infrastructure/Json/RefTokenConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs similarity index 95% rename from src/Squidex.Infrastructure/Json/RefTokenConverter.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs index 1e2576faa..9f12baacc 100644 --- a/src/Squidex.Infrastructure/Json/RefTokenConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs @@ -8,7 +8,7 @@ using System; using Newtonsoft.Json; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class RefTokenConverter : JsonClassConverter { diff --git a/src/Squidex.Infrastructure/Json/TypeNameSerializationBinder.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/TypeNameSerializationBinder.cs similarity index 96% rename from src/Squidex.Infrastructure/Json/TypeNameSerializationBinder.cs rename to src/Squidex.Infrastructure/Json/Newtonsoft/TypeNameSerializationBinder.cs index 303bd51a0..8e5d41dc2 100644 --- a/src/Squidex.Infrastructure/Json/TypeNameSerializationBinder.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/TypeNameSerializationBinder.cs @@ -8,7 +8,7 @@ using System; using Newtonsoft.Json.Serialization; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public class TypeNameSerializationBinder : DefaultSerializationBinder { diff --git a/src/Squidex.Infrastructure/Json/Objects/IJsonValue.cs b/src/Squidex.Infrastructure/Json/Objects/IJsonValue.cs new file mode 100644 index 000000000..743cf4a2a --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/IJsonValue.cs @@ -0,0 +1,18 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure.Json.Objects +{ + public interface IJsonValue : IEquatable + { + JsonValueType Type { get; } + + string ToJsonString(); + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs b/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs new file mode 100644 index 000000000..00880e34a --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs @@ -0,0 +1,100 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonArray : Collection, IJsonValue, IEquatable + { + public JsonValueType Type + { + get { return JsonValueType.Array; } + } + + public JsonArray() + { + } + + public JsonArray(IList values) + : base(values) + { + } + + public JsonArray(params object[] values) + : base(values?.Select(JsonValue.Create).ToList()) + { + } + + protected override void InsertItem(int index, IJsonValue item) + { + Guard.NotNull(item, nameof(item)); + + base.InsertItem(index, item); + } + + protected override void SetItem(int index, IJsonValue item) + { + Guard.NotNull(item, nameof(item)); + + base.SetItem(index, item); + } + + public override bool Equals(object obj) + { + return Equals(obj as JsonArray); + } + + public bool Equals(IJsonValue other) + { + return Equals(other as JsonArray); + } + + public bool Equals(JsonArray array) + { + if (array == null || array.Count != Count) + { + return false; + } + + for (var i = 0; i < Count; i++) + { + if (!this[i].Equals(array[i])) + { + return false; + } + } + + return true; + } + + public override int GetHashCode() + { + var hashCode = 0; + + for (var i = 0; i < Count; i++) + { + hashCode = (hashCode * 23) + this[i].GetHashCode(); + } + + return hashCode; + } + + public string ToJsonString() + { + return ToString(); + } + + public override string ToString() + { + return $"[{string.Join(", ", this)}]"; + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonNull.cs b/src/Squidex.Infrastructure/Json/Objects/JsonNull.cs new file mode 100644 index 000000000..884462b3c --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonNull.cs @@ -0,0 +1,55 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonNull : IJsonValue, IEquatable + { + public static readonly JsonNull Null = new JsonNull(); + + public JsonValueType Type + { + get { return JsonValueType.Null; } + } + + private JsonNull() + { + } + + public override bool Equals(object obj) + { + return Equals(obj as JsonNull); + } + + public bool Equals(IJsonValue other) + { + return Equals(other as JsonNull); + } + + public bool Equals(JsonNull other) + { + return other != null; + } + + public override int GetHashCode() + { + return 0; + } + + public string ToJsonString() + { + return ToString(); + } + + public override string ToString() + { + return "null"; + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs new file mode 100644 index 000000000..fe70c43ff --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs @@ -0,0 +1,129 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonObject : IReadOnlyDictionary, IJsonValue, IEquatable + { + private readonly Dictionary inner = new Dictionary(); + + public IJsonValue this[string key] + { + get + { + return inner[key]; + } + set + { + Guard.NotNullOrEmpty(key, nameof(key)); + Guard.NotNull(value, nameof(value)); + + inner[key] = value; + } + } + + public IEnumerable Keys + { + get { return inner.Keys; } + } + + public IEnumerable Values + { + get { return inner.Values; } + } + + public int Count + { + get { return inner.Count; } + } + + public JsonValueType Type + { + get { return JsonValueType.Array; } + } + + public JsonObject Add(string key, object value) + { + return Add(key, JsonValue.Create(value)); + } + + public JsonObject Add(string key, IJsonValue value) + { + Guard.NotNullOrEmpty(key, nameof(key)); + Guard.NotNull(value, nameof(value)); + + inner.Add(key, value); + + return this; + } + + public void Clear() + { + inner.Clear(); + } + + public bool Remove(string key) + { + return inner.Remove(key); + } + + public bool ContainsKey(string key) + { + return inner.ContainsKey(key); + } + + public bool TryGetValue(string key, out IJsonValue value) + { + return inner.TryGetValue(key, out value); + } + + public IEnumerator> GetEnumerator() + { + return inner.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return inner.GetEnumerator(); + } + + public override bool Equals(object obj) + { + return Equals(obj as JsonObject); + } + + public bool Equals(IJsonValue other) + { + return Equals(other as JsonObject); + } + + public bool Equals(JsonObject other) + { + return other != null && inner.EqualsDictionary(other.inner); + } + + public override int GetHashCode() + { + return inner.DictionaryHashCode(); + } + + public string ToJsonString() + { + return ToString(); + } + + public override string ToString() + { + return $"{{{string.Join(", ", this.Select(x => $"\"{x.Key}\"={x.Value}\""))}}}"; + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs b/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs new file mode 100644 index 000000000..0689f7ecd --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs @@ -0,0 +1,60 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonScalar : IJsonValue, IEquatable> + { + private readonly T value; + + public JsonValueType Type { get; } + + public T Value + { + get { return value; } + } + + internal JsonScalar(JsonValueType type, T value) + { + Type = type; + + this.value = value; + } + + public override bool Equals(object obj) + { + return Equals(obj as JsonScalar); + } + + public bool Equals(IJsonValue other) + { + return Equals(other as JsonScalar); + } + + public bool Equals(JsonScalar other) + { + return other != null && other.Type == Type && Equals(other.value, value); + } + + public override int GetHashCode() + { + return value.GetHashCode(); + } + + public string ToJsonString() + { + return Type == JsonValueType.String ? $"\"{value}\"" : ToString(); + } + + public override string ToString() + { + return value.ToString(); + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs new file mode 100644 index 000000000..06c3325b8 --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs @@ -0,0 +1,114 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; + +namespace Squidex.Infrastructure.Json.Objects +{ + public static class JsonValue + { + public static readonly JsonScalar Empty = new JsonScalar(JsonValueType.String, string.Empty); + + public static readonly JsonScalar True = new JsonScalar(JsonValueType.Boolean, true); + public static readonly JsonScalar False = new JsonScalar(JsonValueType.Boolean, false); + + public static readonly JsonNull Null = JsonNull.Null; + + public static JsonArray Array() + { + return new JsonArray(); + } + + public static JsonArray Array(params object[] values) + { + return new JsonArray(values); + } + + public static JsonObject Object() + { + return new JsonObject(); + } + + public static IJsonValue Create(object value) + { + if (value == null) + { + return Null; + } + + if (value is IJsonValue v) + { + return v; + } + + switch (value) + { + case string s: + return Create(s); + case bool b: + return Create(b); + case float f: + return Create(f); + case double d: + return Create(d); + case int i: + return Create(i); + case long l: + return Create(l); + } + + throw new ArgumentException("Invalid json type"); + } + + public static IJsonValue Create(bool value) + { + return value ? True : False; + } + + public static IJsonValue Create(double value) + { + Guard.ValidNumber(value, nameof(value)); + + return new JsonScalar(JsonValueType.Number, value); + } + + public static IJsonValue Create(double? value) + { + if (value == null) + { + return Null; + } + + return Create(value.Value); + } + + public static IJsonValue Create(bool? value) + { + if (value == null) + { + return Null; + } + + return Create(value.Value); + } + + public static IJsonValue Create(string value) + { + if (value == null) + { + return Null; + } + + if (value.Length == 0) + { + return Empty; + } + + return new JsonScalar(JsonValueType.String, value); + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonValueType.cs b/src/Squidex.Infrastructure/Json/Objects/JsonValueType.cs new file mode 100644 index 000000000..8b4a13022 --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonValueType.cs @@ -0,0 +1,19 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Json.Objects +{ + public enum JsonValueType + { + Array, + Boolean, + Null, + Number, + Object, + String + } +} diff --git a/src/Squidex.Infrastructure/Orleans/J.cs b/src/Squidex.Infrastructure/Orleans/J.cs index 9f89f09d6..aee59a82d 100644 --- a/src/Squidex.Infrastructure/Orleans/J.cs +++ b/src/Squidex.Infrastructure/Orleans/J.cs @@ -6,13 +6,15 @@ // ========================================================================== using System.Threading.Tasks; -using Newtonsoft.Json; +using Squidex.Infrastructure.Json; + +#pragma warning disable SA1401 // Fields must be private namespace Squidex.Infrastructure.Orleans { public static class J { - internal static readonly JsonSerializer DefaultSerializer = JsonSerializer.CreateDefault(); + public static IJsonSerializer DefaultSerializer; public static J AsJ(this T value) { diff --git a/src/Squidex.Infrastructure/Orleans/J{T}.cs b/src/Squidex.Infrastructure/Orleans/J{T}.cs index e39b12664..bfef10aac 100644 --- a/src/Squidex.Infrastructure/Orleans/J{T}.cs +++ b/src/Squidex.Infrastructure/Orleans/J{T}.cs @@ -6,13 +6,12 @@ // ========================================================================== using System; -using System.IO; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; using Orleans.CodeGeneration; using Orleans.Concurrency; using Orleans.Serialization; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; namespace Squidex.Infrastructure.Orleans @@ -22,7 +21,6 @@ namespace Squidex.Infrastructure.Orleans { public T Value { get; } - [JsonConstructor] public J(T value) { Value = value; @@ -63,12 +61,7 @@ namespace Squidex.Infrastructure.Orleans var stream = new StreamWriterWrapper(context.StreamWriter); - using (var writer = new JsonTextWriter(new StreamWriter(stream))) - { - jsonSerializer.Serialize(writer, input); - - writer.Flush(); - } + jsonSerializer.Serialize(input, stream); } } @@ -81,18 +74,15 @@ namespace Squidex.Infrastructure.Orleans var stream = new StreamReaderWrapper(context.StreamReader); - using (var reader = new JsonTextReader(new StreamReader(stream))) - { - return jsonSerializer.Deserialize(reader, expected); - } + return jsonSerializer.Deserialize(stream, expected); } } - private static JsonSerializer GetSerializer(ISerializerContext context) + private static IJsonSerializer GetSerializer(ISerializerContext context) { try { - return context?.ServiceProvider?.GetService() ?? J.DefaultSerializer; + return context?.ServiceProvider?.GetService() ?? J.DefaultSerializer; } catch { diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientJsonTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientJsonTests.cs index 5a3d8cb6d..5a2ac24a7 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientJsonTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientJsonTests.cs @@ -6,8 +6,6 @@ // ========================================================================== using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Xunit; @@ -15,8 +13,6 @@ namespace Squidex.Domain.Apps.Core.Model.Apps { public class AppClientJsonTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - [Fact] public void Should_serialize_and_deserialize() { @@ -34,9 +30,9 @@ namespace Squidex.Domain.Apps.Core.Model.Apps clients = clients.Revoke("4"); - var appClients = JToken.FromObject(clients, serializer).ToObject(serializer); + var serialized = clients.SerializeAndDeserialize(); - appClients.Should().BeEquivalentTo(clients); + serialized.Should().BeEquivalentTo(clients); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsJsonTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsJsonTests.cs index 2f42622f7..d8f86cde3 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsJsonTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsJsonTests.cs @@ -6,8 +6,6 @@ // ========================================================================== using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Xunit; @@ -15,8 +13,6 @@ namespace Squidex.Domain.Apps.Core.Model.Apps { public class AppContributorsJsonTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - [Fact] public void Should_serialize_and_deserialize() { @@ -26,7 +22,7 @@ namespace Squidex.Domain.Apps.Core.Model.Apps contributors = contributors.Assign("2", Role.Editor); contributors = contributors.Assign("3", Role.Owner); - var serialized = JToken.FromObject(contributors, serializer).ToObject(serializer); + var serialized = contributors.SerializeAndDeserialize(); serialized.Should().BeEquivalentTo(contributors); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternJsonTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternJsonTests.cs index 4a3739352..9ffe845bc 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternJsonTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternJsonTests.cs @@ -7,8 +7,6 @@ using System; using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Xunit; @@ -16,8 +14,6 @@ namespace Squidex.Domain.Apps.Core.Model.Apps { public class AppPatternJsonTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - [Fact] public void Should_serialize_and_deserialize() { @@ -35,9 +31,9 @@ namespace Squidex.Domain.Apps.Core.Model.Apps patterns = patterns.Remove(guid1); - var appPatterns = JToken.FromObject(patterns, serializer).ToObject(serializer); + var serialized = patterns.SerializeAndDeserialize(); - appPatterns.Should().BeEquivalentTo(patterns); + serialized.Should().BeEquivalentTo(patterns); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs index 4cf183ab3..35588c136 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs @@ -6,8 +6,6 @@ // ========================================================================== using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Squidex.Infrastructure; using Xunit; @@ -16,16 +14,14 @@ namespace Squidex.Domain.Apps.Core.Model.Apps { public class AppPlanTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - [Fact] public void Should_serialize_and_deserialize() { - var sut = new AppPlan(new RefToken("user", "Me"), "free"); + var plan = new AppPlan(new RefToken("user", "Me"), "free"); - var serialized = JToken.FromObject(sut, serializer).ToObject(serializer); + var serialized = plan.SerializeAndDeserialize(); - serialized.Should().BeEquivalentTo(sut); + serialized.Should().BeEquivalentTo(plan); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs index c0e36b181..0e5f6c51d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs @@ -7,8 +7,6 @@ using System.Linq; using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Squidex.Infrastructure; using Xunit; @@ -17,20 +15,18 @@ namespace Squidex.Domain.Apps.Core.Model.Apps { public class LanguagesConfigJsonTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - [Fact] public void Should_serialize_and_deserialize() { - var sut = LanguagesConfig.Build( + var languages = LanguagesConfig.Build( new LanguageConfig(Language.EN), new LanguageConfig(Language.DE, true, Language.EN), new LanguageConfig(Language.IT, false, Language.DE)) .MakeMaster(Language.IT); - var serialized = JToken.FromObject(sut, serializer).ToObject(serializer); + var serialized = languages.SerializeAndDeserialize(); - serialized.Should().BeEquivalentTo(sut); + serialized.Should().BeEquivalentTo(languages); Assert.Same(serialized.FirstOrDefault(x => x.Key == "it"), serialized.Master); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesJsonTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesJsonTests.cs index 82b47099a..d79477f0a 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesJsonTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesJsonTests.cs @@ -6,8 +6,6 @@ // ========================================================================== using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Xunit; @@ -15,16 +13,14 @@ namespace Squidex.Domain.Apps.Core.Model.Apps { public class RolesJsonTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - [Fact] public void Should_serialize_and_deserialize() { var sut = Roles.CreateDefaults("my-app"); - var serialized = JToken.FromObject(sut, serializer).ToObject(serializer); + var roles = sut.SerializeAndDeserialize(); - serialized.Should().BeEquivalentTo(sut); + roles.Should().BeEquivalentTo(sut); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs index 3c0356896..fe4b91dc5 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs @@ -6,6 +6,7 @@ // ========================================================================== using Squidex.Domain.Apps.Core.Contents; +using Squidex.Infrastructure.Json.Objects; using Xunit; #pragma warning disable xUnit2013 // Do not use equality check to check for collection size. @@ -23,7 +24,7 @@ namespace Squidex.Domain.Apps.Core.Model.Contents .AddField("field2", new ContentFieldData() .AddValue("en", 2) - .AddValue("it", null)); + .AddValue("it", JsonValue.Null)); var actual = input.ToCleaned(); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs index 5a1cd96f3..70d28c50b 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs @@ -9,8 +9,6 @@ using System; using System.Collections.Generic; using System.Linq; using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Core.Rules.Triggers; using Xunit; @@ -21,8 +19,6 @@ namespace Squidex.Domain.Apps.Core.Model.Rules { public class RuleTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); - public static readonly List Triggers = typeof(Rule).Assembly.GetTypes() .Where(x => x.BaseType == typeof(RuleTrigger)) @@ -123,9 +119,9 @@ namespace Squidex.Domain.Apps.Core.Model.Rules { var rule_1 = rule_0.Disable(); - var appClients = JToken.FromObject(rule_1, serializer).ToObject(serializer); + var serialized = rule_1.SerializeAndDeserialize(); - appClients.Should().BeEquivalentTo(rule_1); + serialized.Should().BeEquivalentTo(rule_1); } [Theory] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs index 8dacfd80a..1f8073699 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs @@ -9,8 +9,6 @@ using System; using System.Collections.Generic; using System.Linq; using FluentAssertions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Xunit; @@ -20,7 +18,6 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas { public class SchemaTests { - private readonly JsonSerializer serializer = TestData.DefaultSerializer(); private readonly Schema schema_0 = new Schema("my-schema"); [Fact] @@ -282,7 +279,7 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas public void Should_serialize_and_deserialize_schema() { var schemaSource = TestData.MixedSchema(); - var schemaTarget = JToken.FromObject(schemaSource, serializer).ToObject(serializer); + var schemaTarget = schemaSource.SerializeAndDeserialize(); schemaTarget.Should().BeEquivalentTo(schemaSource); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionFlatTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionFlatTests.cs index 54e71a9b9..0429afaab 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionFlatTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionFlatTests.cs @@ -6,11 +6,11 @@ // ========================================================================== using System.Collections.Generic; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; using Xunit; #pragma warning disable xUnit2013 // Do not use equality check to check for collection size. @@ -44,7 +44,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent .AddValue("en", 2)) .AddField("field2", new ContentFieldData() - .AddValue("de", null) + .AddValue("de", JsonValue.Null) .AddValue("en", 4)) .AddField("field3", new ContentFieldData() @@ -57,10 +57,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = new Dictionary { - { "field1", new ContentFieldData().AddValue("de", 1).AddValue("en", 2) }, - { "field2", new ContentFieldData().AddValue("de", null).AddValue("en", 4) }, - { "field3", (JValue)6 }, - { "field4", (JValue)7 } + { + "field1", + new ContentFieldData() + .AddValue("de", 1) + .AddValue("en", 2) + }, + { + "field2", + new ContentFieldData() + .AddValue("de", JsonValue.Null) + .AddValue("en", 4) + }, + { "field3", JsonValue.Create(6) }, + { "field4", JsonValue.Create(7) } }; Assert.True(expected.EqualsDictionary(output)); @@ -77,7 +87,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent .AddValue("en", 2)) .AddField("field2", new ContentFieldData() - .AddValue("de", null) + .AddValue("de", JsonValue.Null) .AddValue("en", 4)) .AddField("field3", new ContentFieldData() @@ -91,13 +101,13 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new LanguageConfig(Language.EN), new LanguageConfig(Language.DE, false, Language.EN)); - var output = (Dictionary)data.ToFlatLanguageModel(fallbackConfig, new List { Language.DE }); + var output = (Dictionary)data.ToFlatLanguageModel(fallbackConfig, new List { Language.DE }); - var expected = new Dictionary + var expected = new Dictionary { - { "field1", 1 }, - { "field2", 4 }, - { "field3", 6 } + { "field1", JsonValue.Create(1) }, + { "field2", JsonValue.Create(4) }, + { "field3", JsonValue.Create(6) } }; Assert.True(expected.EqualsDictionary(output)); @@ -114,7 +124,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent .AddValue("en", 2)) .AddField("field2", new ContentFieldData() - .AddValue("de", null) + .AddValue("de", JsonValue.Null) .AddValue("en", 4)) .AddField("field3", new ContentFieldData() @@ -123,13 +133,13 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new ContentFieldData() .AddValue("it", 7)); - var output = (Dictionary)data.ToFlatLanguageModel(languagesConfig, new List { Language.DE, Language.EN }); + var output = (Dictionary)data.ToFlatLanguageModel(languagesConfig, new List { Language.DE, Language.EN }); - var expected = new Dictionary + var expected = new Dictionary { - { "field1", 1 }, - { "field2", 4 }, - { "field3", 6 } + { "field1", JsonValue.Create(1) }, + { "field2", JsonValue.Create(4) }, + { "field3", JsonValue.Create(6) } }; Assert.True(expected.EqualsDictionary(output)); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs index 2415089c4..43700a84c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs @@ -5,10 +5,10 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ConvertContent @@ -174,7 +174,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new NamedContentData() .AddField("field1", new ContentFieldData() - .AddValue("en", new JArray("hello", "loved"))) + .AddValue("en", new JsonArray("hello", "loved"))) .AddField("field2", new ContentFieldData() .AddValue("iv", "world")); @@ -191,7 +191,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new NamedContentData() .AddField("field1", new ContentFieldData() - .AddValue("en", new JArray(new JObject(new JProperty("p1", "hello"))))) + .AddValue("en", new JsonArray(JsonValue.Object().Add("p1", "hello")))) .AddField("field2", new ContentFieldData() .AddValue("iv", "world")); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs index 58417c0c9..d5b96a58d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs @@ -8,12 +8,13 @@ using System.Collections.Generic; using System.Linq; using FakeItEasy; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; 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; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ConvertContent @@ -21,6 +22,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent public class FieldConvertersTests { private readonly IAssetUrlGenerator assetUrlGenerator = A.Fake(); + private readonly IJsonSerializer serializer = TestData.DefaultSerializer(); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.EN, Language.DE); private readonly RootField jsonField = Fields.Json(1, "1", Partitioning.Invariant); private readonly RootField stringLanguageField = Fields.String(1, "1", Partitioning.Language); @@ -42,7 +44,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var input = new ContentFieldData() - .AddValue("iv", new JObject()); + .AddValue("iv", JsonValue.Object()); var actual = FieldConverters.ForValues((f, i) => Value.Unset)(input, stringInvariantField); @@ -56,9 +58,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var input = new ContentFieldData() - .AddValue("iv", new JObject()); + .AddValue("iv", JsonValue.Object()); - var actual = FieldConverters.ForValues(ValueConverters.EncodeJson())(input, jsonField); + var actual = FieldConverters.ForValues(ValueConverters.EncodeJson(serializer))(input, jsonField); var expected = new ContentFieldData() @@ -73,20 +75,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("field1", 100), - new JProperty("field2", 200), - new JProperty("invalid", 300)))); + new JsonArray( + JsonValue.Object() + .Add("field1", 100) + .Add("field2", 200) + .Add("invalid", 300))); var actual = FieldConverters.ForNestedName2Id(ValueConverters.ExcludeHidden())(input, arrayField); var expected = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("1", 100)))); + new JsonArray( + JsonValue.Object() + .Add("1", 100))); Assert.Equal(expected, actual); } @@ -97,20 +99,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("field1", 100), - new JProperty("field2", 200), - new JProperty("invalid", 300)))); + new JsonArray( + JsonValue.Object() + .Add("field1", 100) + .Add("field2", 200) + .Add("invalid", 300))); var actual = FieldConverters.ForNestedName2Name(ValueConverters.ExcludeHidden())(input, arrayField); var expected = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("field1", 100)))); + new JsonArray( + JsonValue.Object() + .Add("field1", 100))); Assert.Equal(expected, actual); } @@ -121,20 +123,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("1", 100), - new JProperty("2", 200), - new JProperty("99", 300)))); + new JsonArray( + JsonValue.Object() + .Add("1", 100) + .Add("2", 200) + .Add("99", 300))); var actual = FieldConverters.ForNestedId2Id(ValueConverters.ExcludeHidden())(input, arrayField); var expected = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("1", 100)))); + new JsonArray( + JsonValue.Object() + .Add("1", 100))); Assert.Equal(expected, actual); } @@ -145,20 +147,20 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("1", 100), - new JProperty("2", 200), - new JProperty("99", 300)))); + new JsonArray( + JsonValue.Object() + .Add("1", 100) + .Add("2", 200) + .Add("99", 300))); var actual = FieldConverters.ForNestedId2Name(ValueConverters.ExcludeHidden())(input, arrayField); var expected = new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("field1", 100)))); + new JsonArray( + JsonValue.Object() + .Add("field1", 100))); Assert.Equal(expected, actual); } @@ -422,11 +424,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JArray("1", "2")); + .AddValue("iv", new JsonArray("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JArray("url/to/1", "url/to/2")); + .AddValue("iv", new JsonArray("url/to/1", "url/to/2")); var rtesult = FieldConverters.ResolveAssetUrls(new HashSet(new[] { "1" }), assetUrlGenerator)(source, assetsField); @@ -438,11 +440,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JArray("1", "2")); + .AddValue("iv", new JsonArray("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JArray("url/to/1", "url/to/2")); + .AddValue("iv", new JsonArray("url/to/1", "url/to/2")); var rtesult = FieldConverters.ResolveAssetUrls(new HashSet(new[] { "*" }), assetUrlGenerator)(source, assetsField); @@ -454,11 +456,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JArray("1", "2")); + .AddValue("iv", new JsonArray("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JArray("1", "2")); + .AddValue("iv", new JsonArray("1", "2")); var rtesult = FieldConverters.ResolveAssetUrls(new HashSet(new[] { "2" }), assetUrlGenerator)(source, assetsField); @@ -470,11 +472,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JArray("1", "2")); + .AddValue("iv", new JsonArray("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JArray("1", "2")); + .AddValue("iv", new JsonArray("1", "2")); var rtesult = FieldConverters.ResolveAssetUrls(null, assetUrlGenerator)(source, assetsField); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs index e5cd27572..ada3f0861 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs @@ -5,9 +5,10 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ConvertContent @@ -17,23 +18,24 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent private readonly RootField stringField = Fields.String(1, "1", Partitioning.Invariant); private readonly RootField jsonField = Fields.Json(1, "1", Partitioning.Invariant); private readonly RootField numberField = Fields.Number(1, "1", Partitioning.Invariant); + private readonly IJsonSerializer jsonSerializer = TestData.DefaultSerializer(); [Fact] public void Should_encode_json_value() { - var source = new JObject(); + var source = JsonValue.Object(); - var result = ValueConverters.EncodeJson()(source, jsonField); + var result = ValueConverters.EncodeJson(jsonSerializer)(source, jsonField); - Assert.Equal("e30=", result); + Assert.Equal(JsonValue.Create("e30="), result); } [Fact] public void Should_return_same_value_if_encoding_null_value() { - var source = JValue.CreateNull(); + var source = JsonValue.Null; - var result = ValueConverters.EncodeJson()(source, jsonField); + var result = ValueConverters.EncodeJson(jsonSerializer)(source, jsonField); Assert.Same(source, result); } @@ -41,9 +43,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent [Fact] public void Should_return_same_value_if_encoding_non_json_field() { - var source = (JToken)"NO-JSON"; + var source = JsonValue.Create("NO-JSON"); - var result = ValueConverters.EncodeJson()(source, stringField); + var result = ValueConverters.EncodeJson(jsonSerializer)(source, stringField); Assert.Same(source, result); } @@ -51,19 +53,19 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent [Fact] public void Should_decode_json_values() { - var source = "e30="; + var source = JsonValue.Create("e30="); - var result = ValueConverters.DecodeJson()(source, jsonField); + var result = ValueConverters.DecodeJson(jsonSerializer)(source, jsonField); - Assert.Equal(new JObject(), result); + Assert.Equal(JsonValue.Object(), result); } [Fact] public void Should_return_same_value_if_decoding_null_value() { - var source = JValue.CreateNull(); + var source = JsonValue.Null; - var result = ValueConverters.DecodeJson()(source, jsonField); + var result = ValueConverters.DecodeJson(jsonSerializer)(source, jsonField); Assert.Same(source, result); } @@ -71,9 +73,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent [Fact] public void Should_return_same_value_if_decoding_non_json_field() { - var source = JValue.CreateNull(); + var source = JsonValue.Null; - var result = ValueConverters.EncodeJson()(source, stringField); + var result = ValueConverters.EncodeJson(jsonSerializer)(source, stringField); Assert.Same(source, result); } @@ -81,7 +83,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent [Fact] public void Should_return_unset_if_field_hidden() { - var source = 123; + var source = JsonValue.Create(123); var result = ValueConverters.ExcludeHidden()(source, stringField.Hide()); @@ -91,7 +93,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent [Fact] public void Should_return_unset_if_field_has_wrong_type() { - var source = "invalid"; + var source = JsonValue.Create("invalid"); var result = ValueConverters.ExcludeChangedTypes()(source, numberField); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs index 8c35f5e19..fff6720c4 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs @@ -6,13 +6,13 @@ // ========================================================================== using System; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.EnrichContent; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; using Xunit; #pragma warning disable xUnit2004 // Do not use equality check to test for boolean conditions @@ -53,14 +53,14 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent data.Enrich(schema, languagesConfig.ToResolver()); - Assert.Equal(456, (int)data["my-number"]["iv"]); + Assert.Equal(456, ((JsonScalar)data["my-number"]["iv"]).Value); - Assert.Equal("de-string", (string)data["my-string"]["de"]); - Assert.Equal("en-string", (string)data["my-string"]["en"]); + Assert.Equal("de-string", data["my-string"]["de"].ToString()); + Assert.Equal("en-string", data["my-string"]["en"].ToString()); - Assert.Equal(Now.ToString(), (string)data["my-datetime"]["iv"]); + Assert.Equal(Now.ToString(), data["my-datetime"]["iv"].ToString()); - Assert.True((bool)data["my-boolean"]["iv"]); + Assert.True(((JsonScalar)data["my-boolean"]["iv"]).Value); } [Fact] @@ -77,8 +77,8 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent data.Enrich(schema, languagesConfig.ToResolver()); - Assert.Equal("en-string", (string)data["my-string"]["de"]); - Assert.Equal("en-string", (string)data["my-string"]["en"]); + Assert.Equal("en-string", data["my-string"]["de"].ToString()); + Assert.Equal("en-string", data["my-string"]["en"].ToString()); } [Fact] @@ -88,7 +88,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.Assets(1, "1", Partitioning.Invariant, new AssetsFieldProperties()); - Assert.Equal(new JArray(), DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Array(), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -98,7 +98,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.Boolean(1, "1", Partitioning.Invariant, new BooleanFieldProperties { DefaultValue = true }); - Assert.Equal(true, DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.True, DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -108,7 +108,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.DateTime(1, "1", Partitioning.Invariant, new DateTimeFieldProperties { DefaultValue = FutureDays(15) }); - Assert.Equal(FutureDays(15).ToString(), DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Create(FutureDays(15).ToString()), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -118,7 +118,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.DateTime(1, "1", Partitioning.Invariant, new DateTimeFieldProperties { CalculatedDefaultValue = DateTimeCalculatedDefaultValue.Today }); - Assert.Equal("2017-10-12", DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Create("2017-10-12"), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -128,7 +128,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.DateTime(1, "1", Partitioning.Invariant, new DateTimeFieldProperties { CalculatedDefaultValue = DateTimeCalculatedDefaultValue.Now }); - Assert.Equal("2017-10-12T16:30:10Z", DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Create("2017-10-12T16:30:10Z"), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -138,7 +138,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.Json(1, "1", Partitioning.Invariant, new JsonFieldProperties()); - Assert.Equal(new JObject(), DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Object(), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -148,7 +148,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.Geolocation(1, "1", Partitioning.Invariant, new GeolocationFieldProperties()); - Assert.Equal(JValue.CreateNull(), DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Null, DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -158,7 +158,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.Number(1, "1", Partitioning.Invariant, new NumberFieldProperties { DefaultValue = 12 }); - Assert.Equal(12, DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Create(12), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -168,7 +168,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.References(1, "1", Partitioning.Invariant, new ReferencesFieldProperties()); - Assert.Equal(new JArray(), DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Array(), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -178,7 +178,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.String(1, "1", Partitioning.Invariant, new StringFieldProperties { DefaultValue = "default" }); - Assert.Equal("default", DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Create("default"), DefaultValueFactory.CreateDefaultValue(field, Now)); } [Fact] @@ -188,7 +188,7 @@ namespace Squidex.Domain.Apps.Core.Operations.EnrichContent Fields.Tags(1, "1", Partitioning.Invariant, new TagsFieldProperties()); - Assert.Equal(new JArray(), DefaultValueFactory.CreateDefaultValue(field, Now)); + Assert.Equal(JsonValue.Array(), DefaultValueFactory.CreateDefaultValue(field, Now)); } private static Instant FutureDays(int days) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs index 1d83fcd1f..684035e91 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs @@ -7,12 +7,12 @@ using System; using System.Linq; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.ExtractReferenceIds; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; using Xunit; #pragma warning disable xUnit2013 // Do not use equality check to check for collection size. @@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds new IdContentData() .AddField(5, new ContentFieldData() - .AddValue("iv", new JArray(id1.ToString(), id2.ToString()))); + .AddValue("iv", JsonValue.Array(id1.ToString(), id2.ToString()))); var ids = input.GetReferencedIds(schema).ToArray(); @@ -66,16 +66,16 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds new IdContentData() .AddField(5, new ContentFieldData() - .AddValue("iv", new JArray(id1.ToString(), id2.ToString()))); + .AddValue("iv", JsonValue.Array(id1.ToString(), id2.ToString()))); var converter = FieldConverters.ForValues(ValueReferencesConverter.CleanReferences(new[] { id2 })); var actual = input.ConvertId2Id(schema, converter); - var cleanedValue = (JArray)actual[5]["iv"]; + var cleanedValue = (JsonArray)actual[5]["iv"]; Assert.Equal(1, cleanedValue.Count); - Assert.Equal(id1.ToString(), cleanedValue[0]); + Assert.Equal(id1.ToString(), cleanedValue[0].ToString()); } [Fact] @@ -106,7 +106,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds { var sut = Fields.Assets(1, "my-asset", Partitioning.Invariant); - var result = sut.ExtractReferences("invalid").ToArray(); + var result = sut.ExtractReferences(JsonValue.Create("invalid")).ToArray(); Assert.Empty(result); } @@ -116,7 +116,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds { var sut = Fields.String(1, "my-string", Partitioning.Invariant); - var result = sut.ExtractReferences("invalid").ToArray(); + var result = sut.ExtractReferences(JsonValue.Create("invalid")).ToArray(); Assert.Empty(result); } @@ -126,9 +126,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds { var sut = Fields.Assets(1, "my-asset", Partitioning.Invariant); - var result = sut.CleanReferences(null, null); + var result = sut.CleanReferences(JsonValue.Null, null); - Assert.Null(result); + Assert.Equal(JsonValue.Null, result); } [Fact] @@ -170,9 +170,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds new ReferencesFieldProperties { SchemaId = schemaId })); var value = - new JArray( - new JObject( - new JProperty("my-refs", CreateValue(id1, id2)))); + JsonValue.Array( + JsonValue.Object() + .Add("my-refs", CreateValue(id1, id2))); var result = sut.ExtractReferences(value).ToArray(); @@ -199,7 +199,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds var sut = Fields.References(1, "my-refs", Partitioning.Invariant, new ReferencesFieldProperties { SchemaId = schemaId }); - var result = sut.ExtractReferences(null).ToArray(); + var result = sut.ExtractReferences(JsonValue.Null).ToArray(); Assert.Equal(new[] { schemaId }, result); } @@ -210,7 +210,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds var sut = Fields.References(1, "my-refs", Partitioning.Invariant, new ReferencesFieldProperties { SchemaId = schemaId }); - var result = sut.ExtractReferences("invalid").ToArray(); + var result = sut.ExtractReferences(JsonValue.Create("invalid")).ToArray(); Assert.Equal(new[] { schemaId }, result); } @@ -220,9 +220,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds { var sut = Fields.References(1, "my-refs", Partitioning.Invariant); - var result = sut.CleanReferences(null, null); + var result = sut.CleanReferences(JsonValue.Null, null); - Assert.Null(result); + Assert.Equal(JsonValue.Null, result); } [Fact] @@ -267,9 +267,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ExtractReferenceIds Assert.Same(token, result); } - private static JToken CreateValue(params Guid[] ids) + private static IJsonValue CreateValue(params Guid[] ids) { - return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids.OfType().ToArray()); + return ids == null ? (IJsonValue)JsonValue.Null : JsonValue.Array(ids.Select(x => (object)x.ToString()).ToArray()); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs index 7cdb92b62..bee39a8eb 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs @@ -16,6 +16,7 @@ using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; using Squidex.Shared.Identity; using Squidex.Shared.Users; using Xunit; @@ -24,7 +25,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { public class RuleEventFormatterTests { - private readonly JsonSerializer serializer = JsonSerializer.CreateDefault(); + private readonly IJsonSerializer serializer = TestData.DefaultSerializer(); private readonly IUser user = A.Fake(); private readonly IRuleUrlGenerator urlGenerator = A.Fake(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); @@ -48,7 +49,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { var result = sut.ToPayload(new { Value = 1 }); - Assert.True(result is JObject); + Assert.True(result is string); } [Fact] @@ -58,7 +59,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules var result = sut.ToPayload(@event); - Assert.True(result is JObject); + Assert.True(result is string); } [Fact] @@ -68,7 +69,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules var result = sut.ToEnvelope(@event); - Assert.Equal("MyEventName", result["type"]); + Assert.Contains("MyEventName", result); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs index f21de9c6b..5b2d5b77b 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs @@ -8,7 +8,6 @@ using System; using System.Threading.Tasks; using FakeItEasy; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; @@ -18,6 +17,7 @@ using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Xunit; #pragma warning disable xUnit2009 // Do not use boolean check to check for string equality @@ -28,6 +28,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { private readonly IRuleTriggerHandler ruleTriggerHandler = A.Fake(); private readonly IRuleActionHandler ruleActionHandler = A.Fake(); + private readonly IJsonSerializer serializer = TestData.DefaultSerializer(); private readonly IEventEnricher eventEnricher = A.Fake(); private readonly IClock clock = A.Fake(); private readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); @@ -67,7 +68,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules A.CallTo(() => ruleTriggerHandler.TriggerType) .Returns(typeof(ContentChangedTrigger)); - sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, clock, typeNameRegistry); + sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, serializer, clock, typeNameRegistry); } [Fact] @@ -129,7 +130,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules ruleEnvelope.SetTimestamp(now.Minus(Duration.FromDays(3))); - var actionData = new JObject(); + var actionData = "{}"; var actionDescription = "MyDescription"; A.CallTo(() => clock.GetCurrentInstant()) @@ -159,7 +160,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules ruleEnvelope.SetTimestamp(now); var actionName = "ValidAction"; - var actionData = new JObject(); + var actionData = "{}"; var actionDescription = "MyDescription"; A.CallTo(() => clock.GetCurrentInstant()) @@ -188,7 +189,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_return_succeeded_job_with_full_dump_when_handler_returns_no_exception() { - var ruleJob = new JObject(); + var ruleJob = "{}"; var actionDump = "MyDump"; @@ -206,7 +207,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_return_failed_job_with_full_dump_when_handler_returns_exception() { - var ruleJob = new JObject(); + var ruleJob = "{}"; var actionDump = "MyDump"; @@ -224,7 +225,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_return_timedout_job_with_full_dump_when_exception_from_handler_indicates_timeout() { - var ruleJob = new JObject(); + var ruleJob = "{}"; var actionDump = "MyDump"; @@ -243,7 +244,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_create_exception_details_when_job_to_execute_failed() { - var ruleJob = new JObject(); + var ruleJob = "{}"; var ruleError = new InvalidOperationException(); A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob)) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs index 592e0765e..488c32b9f 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs @@ -7,9 +7,9 @@ using Jint; using Jint.Runtime; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Scripting.ContentWrapper; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.Scripting @@ -155,13 +155,13 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting new NamedContentData() .AddField("number", new ContentFieldData() - .AddValue("iv", new JArray(1.0, 2.0))); + .AddValue("iv", new JsonArray(1.0, 2.0))); var expected = new NamedContentData() .AddField("number", new ContentFieldData() - .AddValue("iv", new JArray(1.0, 4.0, 5.0))); + .AddValue("iv", new JsonArray(1.0, 4.0, 5.0))); var result = ExecuteScript(original, @"data.number.iv = [data.number.iv[0], data.number.iv[1] + 2, 5]"); @@ -175,13 +175,13 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting new NamedContentData() .AddField("number", new ContentFieldData() - .AddValue("iv", new JObject(new JProperty("lat", 1.0)))); + .AddValue("iv", JsonValue.Object().Add("lat", 1.0))); var expected = new NamedContentData() .AddField("number", new ContentFieldData() - .AddValue("iv", new JObject(new JProperty("lat", 1.0), new JProperty("lon", 4.0)))); + .AddValue("iv", JsonValue.Object().Add("lat", 1.0).Add("lon", 4.0))); var result = ExecuteScript(original, @"data.number.iv = { lat: data.number.iv.lat, lon: data.number.iv.lat + 3 }"); @@ -265,7 +265,7 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting new NamedContentData() .AddField("obj", new ContentFieldData() - .AddValue("iv", new JObject(new JProperty("readonly", 1)))); + .AddValue("iv", JsonValue.Object().Add("readonly", 1))); Assert.Throws(() => ExecuteScript(original, "data.obj.iv.invalid = 1")); Assert.Throws(() => ExecuteScript(original, "data.obj.iv.readonly = 2")); @@ -278,7 +278,7 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting new NamedContentData() .AddField("obj", new ContentFieldData() - .AddValue("iv", new JArray())); + .AddValue("iv", new JsonArray())); ExecuteScript(original, "data.obj.iv[0] = 1"); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Tags/TagNormalizerTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Tags/TagNormalizerTests.cs index 7f0843ee2..6dfc8dba0 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Tags/TagNormalizerTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Tags/TagNormalizerTests.cs @@ -9,17 +9,16 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using FakeItEasy; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Tags; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.Tags { public class TagNormalizerTests { - private static readonly JTokenEqualityComparer JTokenEqualityComparer = new JTokenEqualityComparer(); private readonly ITagService tagService = A.Fake(); private readonly Guid appId = Guid.NewGuid(); private readonly Guid schemaId = Guid.NewGuid(); @@ -56,8 +55,8 @@ namespace Squidex.Domain.Apps.Core.Operations.Tags await tagService.NormalizeAsync(appId, schemaId, schema, newData, oldData); - Assert.Equal(new JArray("id2_1", "id2_2"), newData["tags2"]["iv"], JTokenEqualityComparer); - Assert.Equal(new JArray("id4"), newData["array"]["iv"][0]["nestedTags2"], JTokenEqualityComparer); + Assert.Equal(JsonValue.Array("id2_1", "id2_2"), newData["tags2"]["iv"]); + Assert.Equal(JsonValue.Array("id4"), GetNestedTags(newData)); } [Fact] @@ -77,8 +76,8 @@ namespace Squidex.Domain.Apps.Core.Operations.Tags await tagService.NormalizeAsync(appId, schemaId, schema, newData, null); - Assert.Equal(new JArray("id2_1", "id2_2"), newData["tags2"]["iv"], JTokenEqualityComparer); - Assert.Equal(new JArray("id4"), newData["array"]["iv"][0]["nestedTags2"], JTokenEqualityComparer); + Assert.Equal(JsonValue.Array("id2_1", "id2_2"), newData["tags2"]["iv"]); + Assert.Equal(JsonValue.Array("id4"), GetNestedTags(newData)); } [Fact] @@ -98,8 +97,16 @@ namespace Squidex.Domain.Apps.Core.Operations.Tags await tagService.NormalizeAsync(appId, schemaId, schema, newData, null); - Assert.Equal(new JArray("name2_1", "name2_2"), newData["tags2"]["iv"], JTokenEqualityComparer); - Assert.Equal(new JArray("name4"), newData["array"]["iv"][0]["nestedTags2"], JTokenEqualityComparer); + Assert.Equal(JsonValue.Array("name2_1", "name2_2"), newData["tags2"]["iv"]); + Assert.Equal(JsonValue.Array("name4"), GetNestedTags(newData)); + } + + private IJsonValue GetNestedTags(NamedContentData newData) + { + var array = (JsonArray)newData["array"]["iv"]; + var arrayItem = (JsonObject)array[0]; + + return arrayItem["nestedTags2"]; } private static NamedContentData GenerateData(string prefix) @@ -107,21 +114,21 @@ namespace Squidex.Domain.Apps.Core.Operations.Tags return new NamedContentData() .AddField("tags1", new ContentFieldData() - .AddValue("iv", new JArray($"{prefix}1"))) + .AddValue("iv", JsonValue.Array($"{prefix}1"))) .AddField("tags2", new ContentFieldData() - .AddValue("iv", new JArray($"{prefix}2_1", $"{prefix}2_2"))) + .AddValue("iv", JsonValue.Array($"{prefix}2_1", $"{prefix}2_2"))) .AddField("string", new ContentFieldData() .AddValue("iv", $"{prefix}stringValue")) .AddField("array", new ContentFieldData() .AddValue("iv", - new JArray( - new JObject( - new JProperty("nestedTags1", new JArray($"{prefix}3")), - new JProperty("nestedTags2", new JArray($"{prefix}4")), - new JProperty("string", $"{prefix}nestedStringValue"))))); + JsonValue.Array( + JsonValue.Object() + .Add("nestedTags1", JsonValue.Array($"{prefix}3")) + .Add("nestedTags2", JsonValue.Array($"{prefix}4")) + .Add("string", $"{prefix}nestedStringValue")))); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs index 44ee87e03..05897ce5c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs @@ -9,8 +9,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -32,7 +32,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new ArrayFieldProperties()); - await sut.ValidateAsync(CreateValue(new JObject()), errors, ValidationTestExtensions.ValidContext); + await sut.ValidateAsync(CreateValue(JsonValue.Object()), errors, ValidationTestExtensions.ValidContext); Assert.Empty(errors); } @@ -74,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new ArrayFieldProperties()); - await sut.ValidateAsync("invalid", errors); + await sut.ValidateAsync(JsonValue.Create("invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -85,7 +85,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new ArrayFieldProperties { MinItems = 3 }); - await sut.ValidateAsync(CreateValue(new JObject(), new JObject()), errors); + await sut.ValidateAsync(CreateValue(JsonValue.Object(), JsonValue.Object()), errors); errors.Should().BeEquivalentTo( new[] { "Must have at least 3 item(s)." }); @@ -96,15 +96,15 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new ArrayFieldProperties { MaxItems = 1 }); - await sut.ValidateAsync(CreateValue(new JObject(), new JObject()), errors); + await sut.ValidateAsync(CreateValue(JsonValue.Object(), JsonValue.Object()), errors); errors.Should().BeEquivalentTo( new[] { "Must have not more than 1 item(s)." }); } - private static JToken CreateValue(params JObject[] ids) + private static IJsonValue CreateValue(params JsonObject[] ids) { - return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids.OfType().ToArray()); + return ids == null ? (IJsonValue)JsonValue.Null : JsonValue.Array(ids.OfType().ToArray()); } private static RootField Field(ArrayFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs index 36aa3c0e0..7268df598 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs @@ -10,10 +10,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent; using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -119,7 +119,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new AssetsFieldProperties()); - await sut.ValidateAsync("invalid", errors); + await sut.ValidateAsync(JsonValue.Create("invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -263,9 +263,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent }); } - private static JToken CreateValue(params Guid[] ids) + private static IJsonValue CreateValue(params Guid[] ids) { - return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids.OfType().ToArray()); + return ids == null ? (IJsonValue)JsonValue.Null : JsonValue.Array(ids.Select(x => (object)x.ToString()).ToArray()); } private static RootField Field(AssetsFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs index 537f8d9a7..0d9d708c1 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs @@ -8,8 +8,8 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -62,15 +62,15 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new BooleanFieldProperties()); - await sut.ValidateAsync(CreateValue("Invalid"), errors); + await sut.ValidateAsync(JsonValue.Create("Invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); } - private static JValue CreateValue(object v) + private static IJsonValue CreateValue(bool? v) { - return new JValue(v); + return JsonValue.Create(v); } private static RootField Field(BooleanFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs index 441810ec7..8d6893cdd 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs @@ -8,12 +8,12 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -52,7 +52,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new NamedContentData() .AddField("my-field", new ContentFieldData() - .AddValue(1000)); + .AddValue("iv", 1000)); await data.ValidateAsync(context, schema, languagesConfig.ToResolver(), errors); @@ -214,7 +214,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new NamedContentData() .AddField("my-field", new ContentFieldData() - .AddValue(1000)); + .AddValue("iv", 1000)); await data.ValidatePartialAsync(context, schema, languagesConfig.ToResolver(), errors); @@ -329,10 +329,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new NamedContentData() .AddField("my-field", new ContentFieldData() - .AddValue("iv", new JArray( - new JObject(), - new JObject(new JProperty("my-nested", 1)), - new JObject()))); + .AddValue("iv", + JsonValue.Array( + JsonValue.Object(), + JsonValue.Object().Add("my-nested", 1), + JsonValue.Object()))); await data.ValidatePartialAsync(context, schema, languagesConfig.ToResolver(), errors); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs index ac74d57ad..f2df2df3d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs @@ -9,9 +9,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -33,7 +33,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new DateTimeFieldProperties()); - await sut.ValidateAsync(CreateValue(null), errors); + await sut.ValidateAsync(JsonValue.Null, errors); Assert.Empty(errors); } @@ -43,7 +43,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new DateTimeFieldProperties { IsRequired = true }); - await sut.ValidateAsync(CreateValue(null), errors); + await sut.ValidateAsync(JsonValue.Null, errors); errors.Should().BeEquivalentTo( new[] { "Field is required." }); @@ -76,7 +76,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new DateTimeFieldProperties()); - await sut.ValidateAsync(CreateValue("Invalid"), errors); + await sut.ValidateAsync(JsonValue.Create("Invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -87,7 +87,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new DateTimeFieldProperties()); - await sut.ValidateAsync(CreateValue(123), errors); + await sut.ValidateAsync(JsonValue.Create(123), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -98,9 +98,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent return Instant.FromDateTimeUtc(DateTime.UtcNow.Date.AddDays(days)); } - private static JValue CreateValue(object v) + private static IJsonValue CreateValue(Instant v) { - return v is Instant ? new JValue(v.ToString()) : new JValue(v); + return JsonValue.Create(v.ToString()); } private static RootField Field(DateTimeFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs index c19149e6b..cfff1afef 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs @@ -8,8 +8,8 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new GeolocationFieldProperties()); - await sut.ValidateAsync(CreateValue(JValue.CreateNull()), errors); + await sut.ValidateAsync(JsonValue.Null, errors); Assert.Empty(errors); } @@ -41,11 +41,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new GeolocationFieldProperties()); - var geolocation = new JObject( - new JProperty("latitude", 0), - new JProperty("longitude", 0)); + var geolocation = JsonValue.Object() + .Add("latitude", 0) + .Add("longitude", 0); - await sut.ValidateAsync(CreateValue(geolocation), errors); + await sut.ValidateAsync(geolocation, errors); Assert.Empty(errors); } @@ -55,11 +55,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); - var geolocation = new JObject( - new JProperty("latitude", 200), - new JProperty("longitude", 0)); + var geolocation = JsonValue.Object() + .Add("latitude", 200) + .Add("longitude", 0); - await sut.ValidateAsync(CreateValue(geolocation), errors); + await sut.ValidateAsync(geolocation, errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -70,11 +70,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); - var geolocation = new JObject( - new JProperty("latitude", 0), - new JProperty("longitude", 200)); + var geolocation = JsonValue.Object() + .Add("latitude", 0) + .Add("longitude", 200); - await sut.ValidateAsync(CreateValue(geolocation), errors); + await sut.ValidateAsync(geolocation, errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -85,12 +85,12 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); - var geolocation = new JObject( - new JProperty("invalid", 0), - new JProperty("latitude", 0), - new JProperty("longitude", 0)); + var geolocation = JsonValue.Object() + .Add("invalid", 0) + .Add("latitude", 0) + .Add("longitude", 0); - await sut.ValidateAsync(CreateValue(geolocation), errors); + await sut.ValidateAsync(geolocation, errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -101,17 +101,12 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); - await sut.ValidateAsync(CreateValue(JValue.CreateNull()), errors); + await sut.ValidateAsync(JsonValue.Null, errors); errors.Should().BeEquivalentTo( new[] { "Field is required." }); } - private static JToken CreateValue(JToken v) - { - return v; - } - private static RootField Field(GeolocationFieldProperties properties) { return Fields.Geolocation(1, "my-geolocation", Partitioning.Invariant, properties); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs index b6cb06f80..16cba1e50 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs @@ -8,8 +8,8 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new JsonFieldProperties()); - await sut.ValidateAsync(CreateValue(new JValue(1)), errors); + await sut.ValidateAsync(CreateValue(JsonValue.Create(1)), errors); Assert.Empty(errors); } @@ -41,13 +41,13 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new JsonFieldProperties { IsRequired = true }); - await sut.ValidateAsync(CreateValue(JValue.CreateNull()), errors); + await sut.ValidateAsync(CreateValue(JsonValue.Null), errors); errors.Should().BeEquivalentTo( new[] { "Field is required." }); } - private static JValue CreateValue(JValue v) + private static IJsonValue CreateValue(IJsonValue v) { return v; } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs index d236198f9..617032bf6 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs @@ -8,9 +8,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -32,7 +32,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new NumberFieldProperties()); - await sut.ValidateAsync(CreateValue(null), errors); + await sut.ValidateAsync(JsonValue.Null, errors); Assert.Empty(errors); } @@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new NumberFieldProperties { IsRequired = true }); - await sut.ValidateAsync(CreateValue(null), errors); + await sut.ValidateAsync(JsonValue.Null, errors); errors.Should().BeEquivalentTo( new[] { "Field is required." }); @@ -86,15 +86,15 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new NumberFieldProperties()); - await sut.ValidateAsync(CreateValue("Invalid"), errors); + await sut.ValidateAsync(JsonValue.Create("Invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); } - private static JValue CreateValue(object v) + private static IJsonValue CreateValue(double v) { - return new JValue(v); + return JsonValue.Create(v); } private static RootField Field(NumberFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs index 768b781bc..48301f83e 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs @@ -10,8 +10,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -76,7 +76,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new ReferencesFieldProperties()); - await sut.ValidateAsync("invalid", errors); + await sut.ValidateAsync(JsonValue.Create("invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -117,9 +117,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new[] { $"Contains invalid reference '{referenceId}'." }); } - private static JToken CreateValue(params Guid[] ids) + private static IJsonValue CreateValue(params Guid[] ids) { - return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids.OfType().ToArray()); + return ids == null ? (IJsonValue)JsonValue.Null : JsonValue.Array(ids.Select(x => (object)x.ToString()).ToArray()); } private static RootField Field(ReferencesFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs index 46f9a17de..56d9169e7 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs @@ -8,9 +8,9 @@ using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -103,9 +103,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new[] { "Custom Error Message." }); } - private static JValue CreateValue(object v) + private static IJsonValue CreateValue(string v) { - return new JValue(v); + return JsonValue.Create(v); } private static RootField Field(StringFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs index 3b2a4d3c2..23988ca4f 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs @@ -9,9 +9,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FluentAssertions; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent @@ -75,7 +75,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new TagsFieldProperties()); - await sut.ValidateAsync("invalid", errors); + await sut.ValidateAsync(JsonValue.Create("invalid"), errors); errors.Should().BeEquivalentTo( new[] { "Not a valid value." }); @@ -114,9 +114,9 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new[] { "[1]: Not an allowed value." }); } - private static JToken CreateValue(params string[] ids) + private static IJsonValue CreateValue(params string[] ids) { - return ids == null ? JValue.CreateNull() : (JToken)new JArray(ids.OfType().ToArray()); + return ids == null ? (IJsonValue)JsonValue.Null : JsonValue.Array(ids.OfType().ToArray()); } private static RootField Field(TagsFieldProperties properties) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs index 3b1e1c454..ba1d0d2ca 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs @@ -9,10 +9,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.ValidateContent; using Squidex.Domain.Apps.Core.ValidateContent.Validators; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { @@ -37,14 +37,14 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent CreateFormatter(errors)); } - public static Task ValidateAsync(this IField field, JToken value, IList errors, ValidationContext context = null) + public static Task ValidateAsync(this IField field, IJsonValue value, IList errors, ValidationContext context = null) { return new FieldValidator(ValidatorsFactory.CreateValidators(field).ToArray(), field).ValidateAsync(value, CreateContext(context), CreateFormatter(errors)); } - public static Task ValidateOptionalAsync(this IField field, JToken value, IList errors, ValidationContext context = null) + public static Task ValidateOptionalAsync(this IField field, IJsonValue value, IList errors, ValidationContext context = null) { return new FieldValidator(ValidatorsFactory.CreateValidators(field).ToArray(), field).ValidateAsync(value, CreateContext(context).Optional(true), diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs index 6b10c3145..530bc3a74 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs @@ -17,13 +17,14 @@ using Squidex.Domain.Apps.Core.Schemas.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.Collections; using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; using Xunit; namespace Squidex.Domain.Apps.Core { public static class TestData { - public static JsonSerializer DefaultSerializer() + public static IJsonSerializer DefaultSerializer() { var typeNameRegistry = new TypeNameRegistry(); @@ -35,6 +36,7 @@ namespace Squidex.Domain.Apps.Core new AppClientsConverter(), new AppContributorsConverter(), new AppPatternsConverter(), + new ClaimsPrincipalConverter(), new InstantConverter(), new LanguageConverter(), new LanguagesConfigConverter(), @@ -50,7 +52,7 @@ namespace Squidex.Domain.Apps.Core TypeNameHandling = TypeNameHandling.Auto }; - return JsonSerializer.Create(serializerSettings); + return new NewtonsoftJsonSerializer(serializerSettings); } public static Schema MixedSchema() @@ -100,6 +102,13 @@ namespace Squidex.Domain.Apps.Core return schema; } + public static T SerializeAndDeserialize(this T value) + { + var serializer = DefaultSerializer(); + + return serializer.Deserialize(serializer.Serialize(value)); + } + public static void TestFreeze(IFreezable freezable) { var sut = new AssetsFieldProperties(); diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs index aef438ac2..1dad34b54 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs @@ -7,9 +7,7 @@ using System; using System.Linq; -using Newtonsoft.Json; using NodaTime; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.TestHelpers; using Xunit; @@ -27,18 +25,16 @@ namespace Squidex.Infrastructure.EventSourcing } } - private readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); - private readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); private readonly DefaultEventDataFormatter sut; public DefaultEventDataFormatterTests() { - serializerSettings.Converters.Add(new PropertiesBagConverter()); + var typeNameRegistry = + new TypeNameRegistry() + .Map(typeof(MyEvent), "Event") + .Map(typeof(MyOldEvent), "OldEvent"); - typeNameRegistry.Map(typeof(MyEvent), "Event"); - typeNameRegistry.Map(typeof(MyOldEvent), "OldEvent"); - - sut = new DefaultEventDataFormatter(typeNameRegistry, JsonSerializer.Create(serializerSettings)); + sut = new DefaultEventDataFormatter(typeNameRegistry, JsonHelper.DefaultSerializer(typeNameRegistry)); } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeTests.cs index 804d57f14..f9d3a75e5 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeTests.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.TestHelpers; using Xunit; @@ -23,7 +22,7 @@ namespace Squidex.Infrastructure.EventSourcing { var value = new Envelope(new MyEvent { Value = 1 }); - var deserialized = value.SerializeAndDeserializeAndReturn(new PropertiesBagConverter()); + var deserialized = value.SerializeAndDeserialize(); Assert.Equal(1, deserialized.To().Payload.Value); } diff --git a/tests/Squidex.Infrastructure.Tests/Json/ClaimsPrincipalConverterTests.cs b/tests/Squidex.Infrastructure.Tests/Json/ClaimsPrincipalConverterTests.cs index 6abf98d8a..76e65659e 100644 --- a/tests/Squidex.Infrastructure.Tests/Json/ClaimsPrincipalConverterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Json/ClaimsPrincipalConverterTests.cs @@ -36,10 +36,10 @@ namespace Squidex.Infrastructure.Json "Google") }); - var result = value.SerializeAndDeserializeAndReturn(new ClaimsPrincipalConverter()); + var serialized = value.SerializeAndDeserialize(); - Assert.Equal(value.Identities.ElementAt(0).AuthenticationType, result.Identities.ElementAt(0).AuthenticationType); - Assert.Equal(value.Identities.ElementAt(1).AuthenticationType, result.Identities.ElementAt(1).AuthenticationType); + Assert.Equal(value.Identities.ElementAt(0).AuthenticationType, serialized.Identities.ElementAt(0).AuthenticationType); + Assert.Equal(value.Identities.ElementAt(1).AuthenticationType, serialized.Identities.ElementAt(1).AuthenticationType); } [Fact] @@ -47,7 +47,9 @@ namespace Squidex.Infrastructure.Json { ClaimsPrincipal value = null; - value.SerializeAndDeserialize(new ClaimsPrincipalConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Null(value); } } } diff --git a/tests/Squidex.Infrastructure.Tests/Json/InstantConverterTests.cs b/tests/Squidex.Infrastructure.Tests/Json/InstantConverterTests.cs index b207d365a..aba2d8269 100644 --- a/tests/Squidex.Infrastructure.Tests/Json/InstantConverterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Json/InstantConverterTests.cs @@ -19,7 +19,9 @@ namespace Squidex.Infrastructure.Json { var value = Instant.FromDateTimeUtc(DateTime.UtcNow.Date); - value.SerializeAndDeserialize(new InstantConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -27,7 +29,9 @@ namespace Squidex.Infrastructure.Json { Instant? value = Instant.FromDateTimeUtc(DateTime.UtcNow.Date); - value.SerializeAndDeserialize(new InstantConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -35,7 +39,9 @@ namespace Squidex.Infrastructure.Json { Instant? value = null; - value.SerializeAndDeserialize(new InstantConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } } } diff --git a/tests/Squidex.Infrastructure.Tests/Json/ConverterContractResolverTests.cs b/tests/Squidex.Infrastructure.Tests/Json/Newtonsoft/ConverterContractResolverTests.cs similarity index 94% rename from tests/Squidex.Infrastructure.Tests/Json/ConverterContractResolverTests.cs rename to tests/Squidex.Infrastructure.Tests/Json/Newtonsoft/ConverterContractResolverTests.cs index d96f8a780..4ea3d7c0f 100644 --- a/tests/Squidex.Infrastructure.Tests/Json/ConverterContractResolverTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Json/Newtonsoft/ConverterContractResolverTests.cs @@ -11,7 +11,7 @@ using NodaTime; using Squidex.Infrastructure.TestHelpers; using Xunit; -namespace Squidex.Infrastructure.Json +namespace Squidex.Infrastructure.Json.Newtonsoft { public class ConverterContractResolverTests { @@ -77,7 +77,9 @@ namespace Squidex.Infrastructure.Json { var value = Instant.FromDateTimeUtc(DateTime.UtcNow.Date); - value.SerializeAndDeserialize(new ConverterContractResolver(new InstantConverter())); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } } } diff --git a/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonValuesSerializationTests.cs b/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonValuesSerializationTests.cs new file mode 100644 index 000000000..08150c3a8 --- /dev/null +++ b/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonValuesSerializationTests.cs @@ -0,0 +1,113 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Infrastructure.TestHelpers; +using Xunit; + +namespace Squidex.Infrastructure.Json.Objects +{ + public class JsonValuesSerializationTests + { + [Fact] + public void Should_deserialize_integer() + { + var serialized = JsonHelper.Deserialize(123); + + Assert.Equal(JsonValue.Create(123), serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_null() + { + var value = JsonValue.Null; + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_date() + { + var value = JsonValue.Create("2008-09-15T15:53:00"); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_string() + { + var value = JsonValue.Create("my-string"); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_boolean() + { + var value = JsonValue.Create(true); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_number() + { + var value = JsonValue.Create(123); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_array() + { + var value = JsonValue.Array(1, 2); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_object() + { + var value = + JsonValue.Object() + .Add("1", 1) + .Add("2", 1); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + + [Fact] + public void Should_serialize_and_deserialize_complex_object() + { + var value = + JsonValue.Object() + .Add("1", + JsonValue.Array( + JsonValue.Object().Add("1_1", 11), + JsonValue.Object().Add("1_2", 12))) + .Add("2", + JsonValue.Object().Add("2_1", 11)); + + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); + } + } +} diff --git a/tests/Squidex.Infrastructure.Tests/LanguageTests.cs b/tests/Squidex.Infrastructure.Tests/LanguageTests.cs index cddf49510..f57e30fe7 100644 --- a/tests/Squidex.Infrastructure.Tests/LanguageTests.cs +++ b/tests/Squidex.Infrastructure.Tests/LanguageTests.cs @@ -7,7 +7,6 @@ using System; using System.Linq; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.TestHelpers; using Xunit; @@ -125,7 +124,9 @@ namespace Squidex.Infrastructure { Language value = null; - value.SerializeAndDeserialize(new LanguageConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -133,7 +134,9 @@ namespace Squidex.Infrastructure { var value = Language.DE; - value.SerializeAndDeserialize(new LanguageConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } } } diff --git a/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs b/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs index 09a9d1548..bdf62cae4 100644 --- a/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs +++ b/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.TestHelpers; using Xunit; @@ -91,7 +90,9 @@ namespace Squidex.Infrastructure { NamedId value = null; - value.SerializeAndDeserialize(new NamedGuidIdConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -99,7 +100,9 @@ namespace Squidex.Infrastructure { var value = NamedId.Of(Guid.NewGuid(), "my-name"); - value.SerializeAndDeserialize(new NamedGuidIdConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -107,7 +110,9 @@ namespace Squidex.Infrastructure { NamedId value = null; - value.SerializeAndDeserialize(new NamedLongIdConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -115,7 +120,9 @@ namespace Squidex.Infrastructure { var value = NamedId.Of(123L, "my-name"); - value.SerializeAndDeserialize(new NamedLongIdConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -123,7 +130,9 @@ namespace Squidex.Infrastructure { NamedId value = null; - value.SerializeAndDeserialize(new NamedStringIdConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -131,27 +140,27 @@ namespace Squidex.Infrastructure { var value = NamedId.Of(Guid.NewGuid().ToString(), "my-name"); - value.SerializeAndDeserialize(new NamedStringIdConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] public void Should_throw_exception_if_string_id_is_not_valid() { - JsonHelper.DoesNotDeserialize>("123", new NamedStringIdConverter()); + Assert.ThrowsAny(() => JsonHelper.Deserialize>("123")); } [Fact] public void Should_throw_exception_if_long_id_is_not_valid() { - JsonHelper.DoesNotDeserialize>("123", new NamedLongIdConverter()); - JsonHelper.DoesNotDeserialize>("invalid-long,name", new NamedLongIdConverter()); + Assert.ThrowsAny(() => JsonHelper.Deserialize>("invalid-long,name")); } [Fact] public void Should_throw_exception_if_guid_id_is_not_valid() { - JsonHelper.DoesNotDeserialize>("123", new NamedGuidIdConverter()); - JsonHelper.DoesNotDeserialize>("invalid-guid,name", new NamedGuidIdConverter()); + Assert.ThrowsAny(() => JsonHelper.Deserialize>("invalid-guid,name")); } } } diff --git a/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs b/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs index 27e06eb9d..608347c0c 100644 --- a/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs @@ -11,12 +11,18 @@ using System.Collections.Generic; using System.IO; using FakeItEasy; using Orleans.Serialization; +using Squidex.Infrastructure.TestHelpers; using Xunit; namespace Squidex.Infrastructure.Orleans { public class JsonExternalSerializerTests { + public JsonExternalSerializerTests() + { + J.DefaultSerializer = JsonHelper.DefaultSerializer(); + } + [Fact] public void Should_not_copy_null() { diff --git a/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs b/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs index d6888f058..defe9c236 100644 --- a/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs +++ b/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs @@ -10,7 +10,6 @@ using System.Globalization; using System.Linq; using Microsoft.CSharp.RuntimeBinder; using NodaTime; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.TestHelpers; using Xunit; @@ -30,7 +29,7 @@ namespace Squidex.Infrastructure [Fact] public void Should_serialize_and_deserialize_empty_bag() { - var output = bag.SerializeAndDeserializeAndReturn(new PropertiesBagConverter()); + var output = bag.SerializeAndDeserialize(); Assert.Equal(bag.Count, output.Count); } @@ -46,7 +45,7 @@ namespace Squidex.Infrastructure bag.Set("Key4", true); bag.Set("Key5", Guid.NewGuid()); - var output = bag.SerializeAndDeserializeAndReturn(new PropertiesBagConverter()); + var output = bag.SerializeAndDeserialize(); foreach (var kvp in output.Properties.Take(4)) { diff --git a/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs b/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs index b985b7a97..09620ee0f 100644 --- a/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs +++ b/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.TestHelpers; using Xunit; @@ -111,7 +110,9 @@ namespace Squidex.Infrastructure { RefToken value = null; - value.SerializeAndDeserialize(new RefTokenConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } [Fact] @@ -119,7 +120,9 @@ namespace Squidex.Infrastructure { var value = RefToken.Parse("client:client1"); - value.SerializeAndDeserialize(new RefTokenConverter()); + var serialized = value.SerializeAndDeserialize(); + + Assert.Equal(value, serialized); } } } diff --git a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs index d78a249d8..76bb82676 100644 --- a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs +++ b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs @@ -7,64 +7,59 @@ using System; using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using Xunit; +using Newtonsoft.Json.Converters; +using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Infrastructure.TestHelpers { public static class JsonHelper { - public static void SerializeAndDeserialize(this T value, IContractResolver contractResolver) + public static IJsonSerializer DefaultSerializer(TypeNameRegistry typeNameRegistry = null) { var serializerSettings = new JsonSerializerSettings { - ContractResolver = contractResolver, - NullValueHandling = NullValueHandling.Include - }; - - var result = JsonConvert.SerializeObject(Tuple.Create(value), serializerSettings); - var output = JsonConvert.DeserializeObject>(result, serializerSettings); + SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry ?? new TypeNameRegistry()), - Assert.Equal(value, output.Item1); - } + ContractResolver = new ConverterContractResolver( + new ClaimsPrincipalConverter(), + new InstantConverter(), + new JsonValueConverter(), + new LanguageConverter(), + new NamedGuidIdConverter(), + new NamedLongIdConverter(), + new NamedStringIdConverter(), + new PropertiesBagConverter(), + new PropertiesBagConverter(), + new RefTokenConverter(), + new StringEnumConverter()), - public static void SerializeAndDeserialize(this T value, JsonConverter converter) - { - var output = SerializeAndDeserializeAndReturn(value, converter); + TypeNameHandling = TypeNameHandling.Auto + }; - Assert.Equal(value, output); + return new NewtonsoftJsonSerializer(serializerSettings); } - public static T SerializeAndDeserializeAndReturn(this T value, JsonConverter converter) + public static T SerializeAndDeserialize(this T value) { - var serializerSettings = CreateSettings(converter); + var serializer = DefaultSerializer(); - var result = JsonConvert.SerializeObject(Tuple.Create(value), serializerSettings); - var output = JsonConvert.DeserializeObject>(result, serializerSettings); - - return output.Item1; + return serializer.Deserialize>(serializer.Serialize(Tuple.Create(value))).Item1; } - public static void DoesNotDeserialize(string value, JsonConverter converter) + public static T Deserialize(string value) { - var serializerSettings = CreateSettings(converter); + var serializer = DefaultSerializer(); - Assert.ThrowsAny(() => JsonConvert.DeserializeObject>($"{{ \"Item1\": \"{value}\" }}", serializerSettings)); + return serializer.Deserialize>($"{{ \"Item1\": \"{value}\" }}").Item1; } - private static JsonSerializerSettings CreateSettings(JsonConverter converter) + public static T Deserialize(object value) { - var serializerSettings = new JsonSerializerSettings(); - - if (converter != null) - { - serializerSettings.Converters.Add(converter); - } - - serializerSettings.NullValueHandling = NullValueHandling.Include; - serializerSettings.TypeNameHandling = TypeNameHandling.Auto; + var serializer = DefaultSerializer(); - return serializerSettings; + return serializer.Deserialize>($"{{ \"Item1\": {value} }}").Item1; } } } From c8e77194b79949a350e618cb2f151e85cd6a4a8b Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 25 Nov 2018 16:09:41 +0100 Subject: [PATCH 10/33] All tests green for core. --- .../HandleRules/RuleService.cs | 2 +- .../Json/Newtonsoft/JsonValueConverter.cs | 1 - .../Json/Objects/JsonObject.cs | 2 +- .../ConvertContent/FieldConvertersTests.cs | 4 +- .../ConvertContent/ValueConvertersTests.cs | 14 ++- .../HandleRules/RuleEventFormatterTests.cs | 41 ++------- .../HandleRules/RuleServiceTests.cs | 91 +++++++++---------- .../TestData.cs | 9 +- .../DefaultEventDataFormatterTests.cs | 2 +- .../Orleans/JsonExternalSerializerTests.cs | 2 +- .../TestHelpers/JsonHelper.cs | 16 ++-- 11 files changed, 74 insertions(+), 110 deletions(-) diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs index e85ca990d..8a5dbac53 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs @@ -109,7 +109,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules var actionName = typeNameRegistry.GetName(actionType); var actionData = await actionHandler.CreateJobAsync(enrichedEvent, rule.Action); - var json = jsonSerializer.Serialize(actionData); + var json = jsonSerializer.Serialize(actionData.Data); var job = new RuleJob { diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs index 949a3a90c..81825b5e1 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -7,7 +7,6 @@ using System; using System.Globalization; -using System.Linq; using Newtonsoft.Json; using Squidex.Infrastructure.Json.Objects; diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs index fe70c43ff..a2cacce74 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs @@ -123,7 +123,7 @@ namespace Squidex.Infrastructure.Json.Objects public override string ToString() { - return $"{{{string.Join(", ", this.Select(x => $"\"{x.Key}\"={x.Value}\""))}}}"; + return $"{{{string.Join(", ", this.Select(x => $"\"{x.Key}\":{x.Value.ToJsonString()}"))}}}"; } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs index d5b96a58d..0c2d23704 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs @@ -13,7 +13,6 @@ 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; using Squidex.Infrastructure.Json.Objects; using Xunit; @@ -22,7 +21,6 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent public class FieldConvertersTests { private readonly IAssetUrlGenerator assetUrlGenerator = A.Fake(); - private readonly IJsonSerializer serializer = TestData.DefaultSerializer(); private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.EN, Language.DE); private readonly RootField jsonField = Fields.Json(1, "1", Partitioning.Invariant); private readonly RootField stringLanguageField = Fields.String(1, "1", Partitioning.Language); @@ -60,7 +58,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new ContentFieldData() .AddValue("iv", JsonValue.Object()); - var actual = FieldConverters.ForValues(ValueConverters.EncodeJson(serializer))(input, jsonField); + var actual = FieldConverters.ForValues(ValueConverters.EncodeJson(TestData.DefaultSerializer))(input, jsonField); var expected = new ContentFieldData() diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs index ada3f0861..09d0c4bdc 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs @@ -7,7 +7,6 @@ using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Objects; using Xunit; @@ -18,14 +17,13 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent private readonly RootField stringField = Fields.String(1, "1", Partitioning.Invariant); private readonly RootField jsonField = Fields.Json(1, "1", Partitioning.Invariant); private readonly RootField numberField = Fields.Number(1, "1", Partitioning.Invariant); - private readonly IJsonSerializer jsonSerializer = TestData.DefaultSerializer(); [Fact] public void Should_encode_json_value() { var source = JsonValue.Object(); - var result = ValueConverters.EncodeJson(jsonSerializer)(source, jsonField); + var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, jsonField); Assert.Equal(JsonValue.Create("e30="), result); } @@ -35,7 +33,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Null; - var result = ValueConverters.EncodeJson(jsonSerializer)(source, jsonField); + var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, jsonField); Assert.Same(source, result); } @@ -45,7 +43,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Create("NO-JSON"); - var result = ValueConverters.EncodeJson(jsonSerializer)(source, stringField); + var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, stringField); Assert.Same(source, result); } @@ -55,7 +53,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Create("e30="); - var result = ValueConverters.DecodeJson(jsonSerializer)(source, jsonField); + var result = ValueConverters.DecodeJson(TestData.DefaultSerializer)(source, jsonField); Assert.Equal(JsonValue.Object(), result); } @@ -65,7 +63,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Null; - var result = ValueConverters.DecodeJson(jsonSerializer)(source, jsonField); + var result = ValueConverters.DecodeJson(TestData.DefaultSerializer)(source, jsonField); Assert.Same(source, result); } @@ -75,7 +73,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Null; - var result = ValueConverters.EncodeJson(jsonSerializer)(source, stringField); + var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, stringField); Assert.Same(source, result); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs index bee39a8eb..b2b58a49d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs @@ -9,14 +9,12 @@ using System; using System.Collections.Generic; using System.Security.Claims; using FakeItEasy; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Infrastructure; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; using Squidex.Shared.Identity; using Squidex.Shared.Users; using Xunit; @@ -25,7 +23,6 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { public class RuleEventFormatterTests { - private readonly IJsonSerializer serializer = TestData.DefaultSerializer(); private readonly IUser user = A.Fake(); private readonly IRuleUrlGenerator urlGenerator = A.Fake(); private readonly NamedId appId = NamedId.Of(Guid.NewGuid(), "my-app"); @@ -41,7 +38,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules A.CallTo(() => user.Claims) .Returns(new List { new Claim(SquidexClaimTypes.DisplayName, "me") }); - sut = new RuleEventFormatter(serializer, urlGenerator); + sut = new RuleEventFormatter(TestData.DefaultSerializer, urlGenerator); } [Fact] @@ -198,7 +195,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules new NamedContentData() .AddField("city", new ContentFieldData() - .AddValue("iv", new JArray())) + .AddValue("iv", JsonValue.Array())) }; var result = sut.Format("$CONTENT_DATA.city.de.10", @event); @@ -215,8 +212,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules new NamedContentData() .AddField("city", new ContentFieldData() - .AddValue("iv", new JObject( - new JProperty("name", "Berlin")))) + .AddValue("iv", JsonValue.Object().Add("name", "Berlin"))) }; var result = sut.Format("$CONTENT_DATA.city.de.Name", @event); @@ -267,24 +263,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules new NamedContentData() .AddField("city", new ContentFieldData() - .AddValue("iv", JValue.CreateNull())) - }; - - var result = sut.Format("$CONTENT_DATA.city.iv", @event); - - Assert.Equal("UNDEFINED", result); - } - - [Fact] - public void Should_return_undefined_when_undefined() - { - var @event = new EnrichedContentEvent - { - Data = - new NamedContentData() - .AddField("city", - new ContentFieldData() - .AddValue("iv", JValue.CreateUndefined())) + .AddValue("iv", JsonValue.Null)) }; var result = sut.Format("$CONTENT_DATA.city.iv", @event); @@ -301,13 +280,12 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules new NamedContentData() .AddField("city", new ContentFieldData() - .AddValue("iv", new JObject( - new JProperty("name", "Berlin")))) + .AddValue("iv", JsonValue.Object().Add("name", "Berlin"))) }; var result = sut.Format("$CONTENT_DATA.city.iv", @event); - Assert.Equal(JObject.FromObject(new { name = "Berlin" }).ToString(Formatting.Indented), result); + Assert.Equal("{\"name\":\"Berlin\"}", result); } [Fact] @@ -319,7 +297,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules new NamedContentData() .AddField("city", new ContentFieldData() - .AddValue("iv", new JArray( + .AddValue("iv", JsonValue.Array( "Berlin"))) }; @@ -337,8 +315,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules new NamedContentData() .AddField("city", new ContentFieldData() - .AddValue("iv", new JObject( - new JProperty("name", "Berlin")))) + .AddValue("iv", JsonValue.Object().Add("name", "Berlin"))) }; var result = sut.Format("$CONTENT_DATA.city.iv.name", @event); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs index 5b2d5b77b..35226e184 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs @@ -17,7 +17,6 @@ using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Json; using Xunit; #pragma warning disable xUnit2009 // Do not use boolean check to check for string equality @@ -28,9 +27,12 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { private readonly IRuleTriggerHandler ruleTriggerHandler = A.Fake(); private readonly IRuleActionHandler ruleActionHandler = A.Fake(); - private readonly IJsonSerializer serializer = TestData.DefaultSerializer(); private readonly IEventEnricher eventEnricher = A.Fake(); private readonly IClock clock = A.Fake(); + private readonly string actionData = "{\"value\":10}"; + private readonly string actionDump = "MyDump"; + private readonly string actionName = "ValidAction"; + private readonly string actionDescription = "MyDescription"; private readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); private readonly RuleService sut; @@ -38,12 +40,18 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { } + public sealed class InvalidAction : RuleAction + { + } + public sealed class ValidAction : RuleAction { + public int Value { get; set; } } - public sealed class InvalidAction : RuleAction + public sealed class ValidData { + public int Value { get; set; } } public sealed class InvalidTrigger : RuleTrigger @@ -57,7 +65,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules public RuleServiceTests() { typeNameRegistry.Map(typeof(ContentCreated)); - typeNameRegistry.Map(typeof(ValidAction), "ValidAction"); + typeNameRegistry.Map(typeof(ValidAction), actionName); A.CallTo(() => eventEnricher.EnrichAsync(A>.Ignored)) .Returns(new EnrichedContentEvent()); @@ -65,16 +73,30 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules A.CallTo(() => ruleActionHandler.ActionType) .Returns(typeof(ValidAction)); + A.CallTo(() => ruleActionHandler.DataType) + .Returns(typeof(ValidData)); + A.CallTo(() => ruleTriggerHandler.TriggerType) .Returns(typeof(ContentChangedTrigger)); - sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, serializer, clock, typeNameRegistry); + sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, TestData.DefaultSerializer, clock, typeNameRegistry); + } + + [Fact] + public async Task Should_not_create_if_rule_disabled() + { + var ruleConfig = ValidRule().Disable(); + var ruleEnvelope = Envelope.Create(new ContentCreated()); + + var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); + + Assert.Null(job); } [Fact] public async Task Should_not_create_job_for_invalid_event() { - var ruleConfig = new Rule(new ContentChangedTrigger(), new ValidAction()); + var ruleConfig = ValidRule(); var ruleEnvelope = Envelope.Create(new InvalidEvent()); var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); @@ -107,7 +129,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_not_create_if_not_triggered() { - var ruleConfig = new Rule(new ContentChangedTrigger(), new ValidAction()); + var ruleConfig = ValidRule(); var ruleEnvelope = Envelope.Create(new ContentCreated()); A.CallTo(() => ruleTriggerHandler.Triggers(A>.Ignored, ruleConfig.Trigger)) @@ -125,14 +147,11 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules var now = SystemClock.Instance.GetCurrentInstant(); - var ruleConfig = new Rule(new ContentChangedTrigger(), new ValidAction()); + var ruleConfig = ValidRule(); var ruleEnvelope = Envelope.Create(@event); ruleEnvelope.SetTimestamp(now.Minus(Duration.FromDays(3))); - var actionData = "{}"; - var actionDescription = "MyDescription"; - A.CallTo(() => clock.GetCurrentInstant()) .Returns(now); @@ -154,15 +173,11 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules var now = SystemClock.Instance.GetCurrentInstant(); - var ruleConfig = new Rule(new ContentChangedTrigger(), new ValidAction()); + var ruleConfig = ValidRule(); var ruleEnvelope = Envelope.Create(@event); ruleEnvelope.SetTimestamp(now); - var actionName = "ValidAction"; - var actionData = "{}"; - var actionDescription = "MyDescription"; - A.CallTo(() => clock.GetCurrentInstant()) .Returns(now); @@ -170,7 +185,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules .Returns(true); A.CallTo(() => ruleActionHandler.CreateJobAsync(A.Ignored, ruleConfig.Action)) - .Returns((actionDescription, actionData)); + .Returns((actionDescription, new ValidData { Value = 10 })); var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); @@ -189,14 +204,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_return_succeeded_job_with_full_dump_when_handler_returns_no_exception() { - var ruleJob = "{}"; - - var actionDump = "MyDump"; - - A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob)) + A.CallTo(() => ruleActionHandler.ExecuteJobAsync(A.That.Matches(x => x.Value == 10))) .Returns((actionDump, null)); - var result = await sut.InvokeAsync("ValidAction", ruleJob); + var result = await sut.InvokeAsync(actionName, actionData); Assert.Equal(RuleResult.Success, result.Result); @@ -207,14 +218,10 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_return_failed_job_with_full_dump_when_handler_returns_exception() { - var ruleJob = "{}"; - - var actionDump = "MyDump"; - - A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob)) + A.CallTo(() => ruleActionHandler.ExecuteJobAsync(A.That.Matches(x => x.Value == 10))) .Returns((actionDump, new InvalidOperationException())); - var result = await sut.InvokeAsync("ValidAction", ruleJob); + var result = await sut.InvokeAsync(actionName, actionData); Assert.Equal(RuleResult.Failed, result.Result); @@ -225,47 +232,35 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules [Fact] public async Task Should_return_timedout_job_with_full_dump_when_exception_from_handler_indicates_timeout() { - var ruleJob = "{}"; - - var actionDump = "MyDump"; - - A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob)) + A.CallTo(() => ruleActionHandler.ExecuteJobAsync(A.That.Matches(x => x.Value == 10))) .Returns((actionDump, new TimeoutException())); - var result = await sut.InvokeAsync("ValidAction", ruleJob); + var result = await sut.InvokeAsync(actionName, actionData); Assert.Equal(RuleResult.Timeout, result.Result); Assert.True(result.Elapsed >= TimeSpan.Zero); Assert.True(result.Dump.StartsWith(actionDump, StringComparison.OrdinalIgnoreCase)); + Assert.True(result.Dump.IndexOf("Action timed out.", StringComparison.OrdinalIgnoreCase) >= 0); } [Fact] public async Task Should_create_exception_details_when_job_to_execute_failed() { - var ruleJob = "{}"; var ruleError = new InvalidOperationException(); - A.CallTo(() => ruleActionHandler.ExecuteJobAsync(ruleJob)) + A.CallTo(() => ruleActionHandler.ExecuteJobAsync(A.That.Matches(x => x.Value == 10))) .Throws(ruleError); - var result = await sut.InvokeAsync("ValidAction", ruleJob); + var result = await sut.InvokeAsync(actionName, actionData); Assert.Equal((ruleError.ToString(), RuleResult.Failed, TimeSpan.Zero), result); } - [Fact] - public async Task Should_not_create_if_rule_disabled() + private static Rule ValidRule() { - var ruleConfig = new Rule(new ContentChangedTrigger(), new ValidAction()); - var ruleEnvelope = Envelope.Create(new ContentCreated()); - - ruleConfig = ruleConfig.Disable(); - - var job = await sut.CreateJobAsync(ruleConfig, ruleEnvelope); - - Assert.Null(job); + return new Rule(new ContentChangedTrigger(), new ValidAction()); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs index 530bc3a74..ca33bbd45 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs @@ -24,7 +24,9 @@ namespace Squidex.Domain.Apps.Core { public static class TestData { - public static IJsonSerializer DefaultSerializer() + public static readonly IJsonSerializer DefaultSerializer = CreateSerializer(); + + private static IJsonSerializer CreateSerializer() { var typeNameRegistry = new TypeNameRegistry(); @@ -38,6 +40,7 @@ namespace Squidex.Domain.Apps.Core new AppPatternsConverter(), new ClaimsPrincipalConverter(), new InstantConverter(), + new JsonValueConverter(), new LanguageConverter(), new LanguagesConfigConverter(), new NamedGuidIdConverter(), @@ -104,9 +107,7 @@ namespace Squidex.Domain.Apps.Core public static T SerializeAndDeserialize(this T value) { - var serializer = DefaultSerializer(); - - return serializer.Deserialize(serializer.Serialize(value)); + return DefaultSerializer.Deserialize(DefaultSerializer.Serialize(value)); } public static void TestFreeze(IFreezable freezable) diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs index 1dad34b54..212352d04 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs @@ -34,7 +34,7 @@ namespace Squidex.Infrastructure.EventSourcing .Map(typeof(MyEvent), "Event") .Map(typeof(MyOldEvent), "OldEvent"); - sut = new DefaultEventDataFormatter(typeNameRegistry, JsonHelper.DefaultSerializer(typeNameRegistry)); + sut = new DefaultEventDataFormatter(typeNameRegistry, JsonHelper.CreateSerializer(typeNameRegistry)); } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs b/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs index 608347c0c..11deb02cc 100644 --- a/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Orleans/JsonExternalSerializerTests.cs @@ -20,7 +20,7 @@ namespace Squidex.Infrastructure.Orleans { public JsonExternalSerializerTests() { - J.DefaultSerializer = JsonHelper.DefaultSerializer(); + J.DefaultSerializer = JsonHelper.DefaultSerializer; } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs index 76bb82676..9d913bdda 100644 --- a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs +++ b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs @@ -16,7 +16,9 @@ namespace Squidex.Infrastructure.TestHelpers { public static class JsonHelper { - public static IJsonSerializer DefaultSerializer(TypeNameRegistry typeNameRegistry = null) + public static readonly IJsonSerializer DefaultSerializer = CreateSerializer(); + + public static IJsonSerializer CreateSerializer(TypeNameRegistry typeNameRegistry = null) { var serializerSettings = new JsonSerializerSettings { @@ -43,23 +45,17 @@ namespace Squidex.Infrastructure.TestHelpers public static T SerializeAndDeserialize(this T value) { - var serializer = DefaultSerializer(); - - return serializer.Deserialize>(serializer.Serialize(Tuple.Create(value))).Item1; + return DefaultSerializer.Deserialize>(DefaultSerializer.Serialize(Tuple.Create(value))).Item1; } public static T Deserialize(string value) { - var serializer = DefaultSerializer(); - - return serializer.Deserialize>($"{{ \"Item1\": \"{value}\" }}").Item1; + return DefaultSerializer.Deserialize>($"{{ \"Item1\": \"{value}\" }}").Item1; } public static T Deserialize(object value) { - var serializer = DefaultSerializer(); - - return serializer.Deserialize>($"{{ \"Item1\": {value} }}").Item1; + return DefaultSerializer.Deserialize>($"{{ \"Item1\": {value} }}").Item1; } } } From 289f2747cfe006ffa7d46c6416a4aeab98d46f61 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 25 Nov 2018 19:49:13 +0100 Subject: [PATCH 11/33] All tests fixed. --- .../Actions/Algolia/AlgoliaActionHandler.cs | 4 +- .../Discourse/DiscourseActionHandler.cs | 19 ++- .../ElasticSearchActionHandler.cs | 4 +- .../Prerender/PrerenderActionHandler.cs | 9 +- .../Actions/Slack/SlackActionHandler.cs | 8 +- .../EnrichedEvents/EnrichedEvent.cs | 3 + .../HandleRules/RuleActionHandler.cs | 2 +- ...Squidex.Domain.Apps.Core.Operations.csproj | 1 - .../Contents/Extensions.cs | 13 +- .../Contents/MongoContentCollection.cs | 11 +- .../Contents/MongoContentDraftCollection.cs | 9 +- .../Contents/MongoContentEntity.cs | 7 +- .../MongoContentPublishedCollection.cs | 7 +- .../Contents/MongoContentRepository.cs | 11 +- .../MongoContentRepository_SnapshotStore.cs | 4 +- .../Apps/AppUISettingsGrain.cs | 18 +- .../Apps/BackupApps.cs | 19 ++- .../Apps/IAppUISettingsGrain.cs | 8 +- .../Apps/State/AppState.cs | 18 +- .../Assets/BackupAssets.cs | 7 +- .../Assets/State/AssetState.cs | 24 +-- .../Backup/BackupGrain.cs | 7 +- .../Backup/BackupReader.cs | 51 ++---- .../Backup/BackupWriter.cs | 32 ++-- .../Backup/GuidMapper.cs | 89 +--------- .../Backup/Helpers/Downloader.cs | 5 +- .../Backup/RestoreGrain.cs | 17 +- .../Backup/State/BackupState.cs | 4 +- .../Backup/State/BackupStateJob.cs | 14 +- .../Backup/State/RestoreState.cs | 4 +- .../Backup/State/RestoreStateJob.cs | 21 +-- .../GraphQL/GraphQLExecutionContext.cs | 13 +- .../Contents/GraphQL/Types/AllTypes.cs | 2 +- .../Contents/GraphQL/Types/AssetGraphType.cs | 4 +- .../GraphQL/Types/ContentDataGraphType.cs | 4 +- .../GraphQL/Types/ContentGraphType.cs | 4 +- .../Contents/GraphQL/Types/NestedGraphType.cs | 6 +- .../GraphQL/Types/QueryGraphTypeVisitor.cs | 4 +- .../GraphQL/Types/Utils/InstantGraphType.cs | 41 +++++ .../GraphQL/Types/Utils/InstantValue.cs | 25 +++ .../GraphQL/Types/Utils/JsonConverter.cs | 6 +- .../Contents/GraphQL/Types/Utils/JsonValue.cs | 8 +- .../Contents/State/ContentState.cs | 18 +- .../DomainObjectState.cs | 14 +- .../Rules/State/RuleState.cs | 8 +- .../Schemas/State/SchemaState.cs | 28 +-- .../SquidexHeaderExtensions.cs | 3 +- .../RedisPubSub.cs | 9 +- .../RedisSubscription.cs | 10 +- .../DefaultEventDataFormatter.cs | 6 +- .../EventSourcing/EnvelopeExtensions.cs | 11 +- .../EventSourcing/IEventDataFormatter.cs | 2 +- .../Json/IJsonSerializer.cs | 6 +- .../Json/Newtonsoft/JsonValueConverter.cs | 57 ++++--- .../Newtonsoft/NewtonsoftJsonSerializer.cs | 68 ++++++-- .../Json/Newtonsoft/PropertiesBagConverter.cs | 4 +- .../Json/Objects/JsonValue.cs | 13 ++ src/Squidex.Infrastructure/Language.cs | 2 +- src/Squidex.Infrastructure/Orleans/J{T}.cs | 2 +- src/Squidex.Infrastructure/PropertyValue.cs | 92 +++++----- .../Api/Config/Swagger/SwaggerExtensions.cs | 2 +- .../Api/Config/Swagger/SwaggerServices.cs | 2 +- .../Controllers/Apps/Models/AppCreatedDto.cs | 1 - .../Api/Controllers/Apps/Models/AppDto.cs | 1 - .../Apps/Models/AssignContributorDto.cs | 1 - .../Api/Controllers/Apps/Models/ClientDto.cs | 1 - .../Controllers/Apps/Models/ContributorDto.cs | 1 - .../Controllers/UI/Models/UpdateSettingDto.cs | 4 +- .../Areas/Api/Controllers/UI/UIController.cs | 7 +- .../Config/IdentityServerExtensions.cs | 8 +- .../Config/Domain/EventPublishersServices.cs | 4 +- .../Config/Domain/SerializationServices.cs | 5 +- src/Squidex/Config/Domain/StoreServices.cs | 3 +- .../Config/Domain/SubscriptionServices.cs | 2 +- .../Model/Rules/RuleTests.cs | 2 +- .../Model/Schemas/SchemaFieldTests.cs | 2 +- .../Model/Schemas/SchemaTests.cs | 2 +- .../ConvertContent/FieldConvertersTests.cs | 2 +- .../ConvertContent/ValueConvertersTests.cs | 12 +- .../Operations/GenerateEdmSchema/EdmTests.cs | 2 +- .../GenerateJsonSchema/JsonSchemaTests.cs | 2 +- .../HandleRules/RuleEventFormatterTests.cs | 2 +- .../HandleRules/RuleServiceTests.cs | 2 +- .../{TestData.cs => TestUtils.cs} | 9 +- .../Apps/AppUISettingsGrainTests.cs | 34 ++-- .../Backup/BackupReaderWriterTests.cs | 123 +++++++++---- .../Backup/GuidMapperTests.cs | 161 ------------------ .../Contents/ContentGrainTests.cs | 4 +- .../Contents/GraphQL/GraphQLQueriesTests.cs | 35 ++-- .../Contents/GraphQL/GraphQLTestBase.cs | 42 ++--- .../Rules/RuleDequeuerTests.cs | 5 +- .../Squidex.Domain.Apps.Entities.Tests.csproj | 1 + .../EventSourcing/EnvelopeExtensionsTests.cs | 12 +- .../Grains/EventConsumerGrainTests.cs | 6 +- .../PropertiesBagTests.cs | 44 +++-- .../States/PersistenceEventSourcingTests.cs | 4 +- tools/Migrate_01/Rebuilder.cs | 8 +- 97 files changed, 718 insertions(+), 760 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantGraphType.cs create mode 100644 src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantValue.cs rename tests/Squidex.Domain.Apps.Core.Tests/{TestData.cs => TestUtils.cs} (94%) delete mode 100644 tests/Squidex.Domain.Apps.Entities.Tests/Backup/GuidMapperTests.cs diff --git a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs index 80d7e23d1..46c31f642 100644 --- a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs @@ -56,7 +56,9 @@ namespace Squidex.Extensions.Actions.Algolia { ruleDescription = $"Add entry to Algolia index: {action.IndexName}"; - ruleJob.Content = ToPayload(contentEvent); + var json = ToJson(contentEvent); + + ruleJob.Content = JObject.Parse(json); ruleJob.Content["objectID"] = contentId; } diff --git a/extensions/Squidex.Extensions/Actions/Discourse/DiscourseActionHandler.cs b/extensions/Squidex.Extensions/Actions/Discourse/DiscourseActionHandler.cs index 22e9131a1..b0811ba17 100644 --- a/extensions/Squidex.Extensions/Actions/Discourse/DiscourseActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/Discourse/DiscourseActionHandler.cs @@ -6,10 +6,10 @@ // ========================================================================== using System; +using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; @@ -32,25 +32,28 @@ namespace Squidex.Extensions.Actions.Discourse { var url = $"{action.Url.ToString().TrimEnd('/')}/posts.json?api_key={action.ApiKey}&api_username={action.ApiUsername}"; - var json = - new JObject( - new JProperty("raw", Format(action.Text, @event)), - new JProperty("title", Format(action.Title, @event))); + var json = new Dictionary + { + ["raw"] = Format(action.Text, @event), + ["title"] = Format(action.Title, @event) + }; if (action.Topic.HasValue) { - json.Add(new JProperty("topic_id", action.Topic.Value)); + json.Add("topic_id", action.Topic.Value); } if (action.Category.HasValue) { - json.Add(new JProperty("category", action.Category.Value)); + json.Add("category", action.Category.Value); } + var requestBody = ToJson(json); + var ruleJob = new DiscourseJob { RequestUrl = url, - RequestBody = json.ToString() + RequestBody = requestBody }; var description = diff --git a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs index 78655e4fd..3688f7f75 100644 --- a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs @@ -60,7 +60,9 @@ namespace Squidex.Extensions.Actions.ElasticSearch { ruleDescription = $"Upsert to index: {action.IndexName}"; - ruleJob.Content = ToPayload(contentEvent); + var json = ToJson(contentEvent); + + ruleJob.Content = JObject.Parse(json); ruleJob.Content["objectID"] = contentId; } diff --git a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderActionHandler.cs b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderActionHandler.cs index e8c722490..40d78e4bf 100644 --- a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderActionHandler.cs @@ -9,7 +9,6 @@ using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; @@ -29,12 +28,10 @@ namespace Squidex.Extensions.Actions.Prerender { var url = Format(action.Url, @event); - var request = - new JObject( - new JProperty("prerenderToken", action.Token), - new JProperty("url", url)); + var request = new { prerenderToken = action.Token, url }; + var requestBody = ToJson(request); - return ($"Recache {url}", new PrerenderJob { RequestBody = request.ToString() }); + return ($"Recache {url}", new PrerenderJob { RequestBody = requestBody }); } protected override async Task<(string Dump, Exception Exception)> ExecuteJobAsync(PrerenderJob job) diff --git a/extensions/Squidex.Extensions/Actions/Slack/SlackActionHandler.cs b/extensions/Squidex.Extensions/Actions/Slack/SlackActionHandler.cs index aeb40f32c..3d47eaa71 100644 --- a/extensions/Squidex.Extensions/Actions/Slack/SlackActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/Slack/SlackActionHandler.cs @@ -9,8 +9,6 @@ using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Infrastructure; @@ -33,14 +31,12 @@ namespace Squidex.Extensions.Actions.Slack protected override (string Description, SlackJob Data) CreateJob(EnrichedEvent @event, SlackAction action) { - var body = - new JObject( - new JProperty("text", Format(action.Text, @event))); + var body = new { text = Format(action.Text, @event) }; var ruleJob = new SlackJob { RequestUrl = action.WebhookUrl.ToString(), - RequestBody = body.ToString(Formatting.Indented) + RequestBody = ToJson(body) }; return (Description, ruleJob); diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs index 6c02810a4..0ca18fdf1 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EnrichedEvents/EnrichedEvent.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Runtime.Serialization; using NodaTime; using Squidex.Infrastructure; using Squidex.Shared.Users; @@ -24,8 +25,10 @@ namespace Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents public long Version { get; set; } + [IgnoreDataMember] public abstract Guid AggregateId { get; } + [IgnoreDataMember] public IUser User { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs index e9632578c..7f6c4ed75 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs @@ -36,7 +36,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules this.formatter = formatter; } - protected virtual string ToPayloadJson(T @event) + protected virtual string ToJson(T @event) { return formatter.ToPayload(@event); } diff --git a/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj b/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj index 383bb37ae..c6e1c7f42 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj +++ b/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj @@ -16,7 +16,6 @@ - diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs index c3fc170a7..c677386a6 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Extensions.cs @@ -12,6 +12,7 @@ using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Core.ExtractReferenceIds; using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { @@ -22,24 +23,24 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents return data.GetReferencedIds(schema).ToList(); } - public static NamedContentData FromMongoModel(this IdContentData result, Schema schema, List deletedIds) + public static NamedContentData FromMongoModel(this IdContentData result, Schema schema, List deletedIds, IJsonSerializer serializer) { return result.ConvertId2Name(schema, FieldConverters.ForValues( - ValueConverters.DecodeJson(), + ValueConverters.DecodeJson(serializer), ValueReferencesConverter.CleanReferences(deletedIds)), FieldConverters.ForNestedId2Name( - ValueConverters.DecodeJson(), + ValueConverters.DecodeJson(serializer), ValueReferencesConverter.CleanReferences(deletedIds))); } - public static IdContentData ToMongoModel(this NamedContentData result, Schema schema) + public static IdContentData ToMongoModel(this NamedContentData result, Schema schema, IJsonSerializer serializer) { return result.ConvertName2Id(schema, FieldConverters.ForValues( - ValueConverters.EncodeJson()), + ValueConverters.EncodeJson(serializer)), FieldConverters.ForNestedName2Id( - ValueConverters.EncodeJson())); + ValueConverters.EncodeJson(serializer))); } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs index c9eec5756..799ea5aef 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs @@ -17,6 +17,7 @@ using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.Queries; @@ -26,10 +27,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { private readonly string collectionName; - public MongoContentCollection(IMongoDatabase database, string collectionName) + protected IJsonSerializer Serializer { get; } + + public MongoContentCollection(IMongoDatabase database, IJsonSerializer serializer, string collectionName) : base(database) { this.collectionName = collectionName; + + Serializer = serializer; } protected override async Task SetupCollectionAsync(IMongoCollection collection, CancellationToken ct = default(CancellationToken)) @@ -64,7 +69,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents foreach (var entity in contentItems.Result) { - entity.ParseData(schema.SchemaDef); + entity.ParseData(schema.SchemaDef, Serializer); } return ResultList.Create(contentCount.Result, contentItems.Result); @@ -96,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents foreach (var entity in contentItems.Result) { - entity.ParseData(schema.SchemaDef); + entity.ParseData(schema.SchemaDef, Serializer); } return ResultList.Create(contentCount.Result, contentItems.Result); diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs index 2c80690f7..72af5e013 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs @@ -18,6 +18,7 @@ using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.State; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.States; @@ -26,8 +27,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { internal sealed class MongoContentDraftCollection : MongoContentCollection { - public MongoContentDraftCollection(IMongoDatabase database) - : base(database, "State_Content_Draft") + public MongoContentDraftCollection(IMongoDatabase database, IJsonSerializer serializer) + : base(database, serializer, "State_Content_Draft") { } @@ -88,7 +89,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents await Collection.Find(x => x.IndexedSchemaId == schema.Id && x.Id == id && x.IsDeleted != true).Not(x => x.DataText) .FirstOrDefaultAsync(); - contentEntity?.ParseData(schema.SchemaDef); + contentEntity?.ParseData(schema.SchemaDef, Serializer); return contentEntity; } @@ -103,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { var schema = await getSchema(contentEntity.IndexedAppId, contentEntity.IndexedSchemaId); - contentEntity.ParseData(schema.SchemaDef); + contentEntity.ParseData(schema.SchemaDef, Serializer); return (SimpleMapper.Map(contentEntity, new ContentState()), contentEntity.Version); } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs index b758c7919..e19296d9a 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs @@ -14,6 +14,7 @@ using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.MongoDb; namespace Squidex.Domain.Apps.Entities.MongoDb.Contents @@ -124,13 +125,13 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents get { return dataDraft; } } - public void ParseData(Schema schema) + public void ParseData(Schema schema, IJsonSerializer serializer) { - data = DataByIds.FromMongoModel(schema, ReferencedIdsDeleted); + data = DataByIds.FromMongoModel(schema, ReferencedIdsDeleted, serializer); if (DataDraftByIds != null) { - dataDraft = DataDraftByIds.FromMongoModel(schema, ReferencedIdsDeleted); + dataDraft = DataDraftByIds.FromMongoModel(schema, ReferencedIdsDeleted, serializer); } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentPublishedCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentPublishedCollection.cs index 97ca68a3d..139869959 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentPublishedCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentPublishedCollection.cs @@ -13,14 +13,15 @@ using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.MongoDb; namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { internal sealed class MongoContentPublishedCollection : MongoContentCollection { - public MongoContentPublishedCollection(IMongoDatabase database) - : base(database, "State_Content_Published") + public MongoContentPublishedCollection(IMongoDatabase database, IJsonSerializer serializer) + : base(database, serializer, "State_Content_Published") { } @@ -42,7 +43,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents await Collection.Find(x => x.IndexedSchemaId == schema.Id && x.Id == id).Not(x => x.DataText) .FirstOrDefaultAsync(); - contentEntity?.ParseData(schema.SchemaDef); + contentEntity?.ParseData(schema.SchemaDef, Serializer); return contentEntity; } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs index 71c81e3aa..628131df7 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs @@ -17,6 +17,7 @@ using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.Repositories; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Queries; @@ -26,17 +27,21 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { private readonly IMongoDatabase database; private readonly IAppProvider appProvider; + private readonly IJsonSerializer serializer; private readonly MongoContentDraftCollection contentsDraft; private readonly MongoContentPublishedCollection contentsPublished; - public MongoContentRepository(IMongoDatabase database, IAppProvider appProvider) + public MongoContentRepository(IMongoDatabase database, IAppProvider appProvider, IJsonSerializer serializer) { Guard.NotNull(appProvider, nameof(appProvider)); + Guard.NotNull(serializer, nameof(serializer)); this.appProvider = appProvider; - contentsDraft = new MongoContentDraftCollection(database); - contentsPublished = new MongoContentPublishedCollection(database); + this.serializer = serializer; + + contentsDraft = new MongoContentDraftCollection(database, serializer); + contentsPublished = new MongoContentPublishedCollection(database, serializer); this.database = database; } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs index cd6700635..32f38e982 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs @@ -38,12 +38,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents var schema = await GetSchemaAsync(value.AppId.Id, value.SchemaId.Id); - var idData = value.Data.ToMongoModel(schema.SchemaDef); + var idData = value.Data.ToMongoModel(schema.SchemaDef, serializer); var idDraftData = idData; if (!ReferenceEquals(value.Data, value.DataDraft)) { - idDraftData = value.DataDraft?.ToMongoModel(schema.SchemaDef); + idDraftData = value.DataDraft?.ToMongoModel(schema.SchemaDef, serializer); } var content = SimpleMapper.Map(value, new MongoContentEntity diff --git a/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs b/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs index ea1e17408..e19911379 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs @@ -8,8 +8,8 @@ using System; using System.Linq; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.States; @@ -24,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Apps [CollectionName("UISettings")] public sealed class State { - public JObject Settings { get; set; } = new JObject(); + public JsonObject Settings { get; set; } = JsonValue.Object(); } public AppUISettingsGrain(IStore store) @@ -41,19 +41,19 @@ namespace Squidex.Domain.Apps.Entities.Apps return persistence.ReadAsync(); } - public Task> GetAsync() + public Task> GetAsync() { return Task.FromResult(state.Settings.AsJ()); } - public Task SetAsync(J settings) + public Task SetAsync(J settings) { state.Settings = settings; return persistence.WriteSnapshotAsync(state); } - public Task SetAsync(string path, J value) + public Task SetAsync(string path, J value) { var container = GetContainer(path, out var key); @@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Entities.Apps throw new InvalidOperationException("Path does not lead to an object."); } - container[key] = value; + container[key] = value.Value; return persistence.WriteSnapshotAsync(state); } @@ -79,7 +79,7 @@ namespace Squidex.Domain.Apps.Entities.Apps return persistence.WriteSnapshotAsync(state); } - private JObject GetContainer(string path, out string key) + private JsonObject GetContainer(string path, out string key) { Guard.NotNullOrEmpty(path, nameof(path)); @@ -95,12 +95,12 @@ namespace Squidex.Domain.Apps.Entities.Apps { if (!current.TryGetValue(segment, out var temp)) { - temp = new JObject(); + temp = JsonValue.Object(); current[segment] = temp; } - if (temp is JObject next) + if (temp is JsonObject next) { current = next; } diff --git a/src/Squidex.Domain.Apps.Entities/Apps/BackupApps.cs b/src/Squidex.Domain.Apps.Entities/Apps/BackupApps.cs index 1cc342591..6d7b8e3d6 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/BackupApps.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/BackupApps.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Orleans; using Squidex.Domain.Apps.Entities.Apps.Indexes; using Squidex.Domain.Apps.Entities.Backup; @@ -16,6 +15,8 @@ using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Apps; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Orleans; using Squidex.Shared.Users; @@ -27,6 +28,7 @@ namespace Squidex.Domain.Apps.Entities.Apps private const string SettingsFile = "Settings.json"; private readonly IGrainFactory grainFactory; private readonly IUserResolver userResolver; + private readonly IJsonSerializer serializer; private readonly IAppsByNameIndex appsByNameIndex; private readonly HashSet contributors = new HashSet(); private Dictionary usersWithEmail = new Dictionary(); @@ -36,13 +38,14 @@ namespace Squidex.Domain.Apps.Entities.Apps public override string Name { get; } = "Apps"; - public BackupApps(IGrainFactory grainFactory, IUserResolver userResolver) + public BackupApps(IGrainFactory grainFactory, IUserResolver userResolver, IJsonSerializer serializer) { Guard.NotNull(grainFactory, nameof(grainFactory)); + Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(userResolver, nameof(userResolver)); this.grainFactory = grainFactory; - + this.serializer = serializer; this.userResolver = userResolver; appsByNameIndex = grainFactory.GetGrain(SingleGrain.Id); @@ -162,14 +165,14 @@ namespace Squidex.Domain.Apps.Entities.Apps private async Task ReadUsersAsync(BackupReader reader) { - var json = await reader.ReadJsonAttachmentAsync(UsersFile); + var json = await reader.ReadJsonAttachmentAsync>(UsersFile); - usersWithEmail = json.ToObject>(); + usersWithEmail = json; } private async Task WriteUsersAsync(BackupWriter writer) { - var json = JObject.FromObject(usersWithEmail); + var json = usersWithEmail; await writer.WriteJsonAsync(UsersFile, json); } @@ -183,9 +186,9 @@ namespace Squidex.Domain.Apps.Entities.Apps private async Task ReadSettingsAsync(BackupReader reader, Guid appId) { - var json = await reader.ReadJsonAttachmentAsync(SettingsFile); + var json = await reader.ReadJsonAttachmentAsync(SettingsFile); - await grainFactory.GetGrain(appId).SetAsync((JObject)json); + await grainFactory.GetGrain(appId).SetAsync(json); } public override async Task CompleteRestoreAsync(Guid appId, BackupReader reader) diff --git a/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs b/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs index 38fde5c74..69583ff25 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/IAppUISettingsGrain.cs @@ -6,19 +6,19 @@ // ========================================================================== using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Orleans; +using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Orleans; namespace Squidex.Domain.Apps.Entities.Apps { public interface IAppUISettingsGrain : IGrainWithGuidKey { - Task> GetAsync(); + Task> GetAsync(); - Task SetAsync(string path, J value); + Task SetAsync(string path, J value); - Task SetAsync(J settings); + Task SetAsync(J settings); Task RemoveAsync(string path); } diff --git a/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs b/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs index 345a5b32c..36d8ce960 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs @@ -5,7 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; +using System.Runtime.Serialization; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Apps; @@ -19,28 +19,28 @@ namespace Squidex.Domain.Apps.Entities.Apps.State [CollectionName("Apps")] public class AppState : DomainObjectState, IAppEntity { - [JsonProperty] + [DataMember] public string Name { get; set; } - [JsonProperty] + [DataMember] public Roles Roles { get; set; } = Roles.Empty; - [JsonProperty] + [DataMember] public AppPlan Plan { get; set; } - [JsonProperty] + [DataMember] public AppClients Clients { get; set; } = AppClients.Empty; - [JsonProperty] + [DataMember] public AppPatterns Patterns { get; set; } = AppPatterns.Empty; - [JsonProperty] + [DataMember] public AppContributors Contributors { get; set; } = AppContributors.Empty; - [JsonProperty] + [DataMember] public LanguagesConfig LanguagesConfig { get; set; } = LanguagesConfig.English; - [JsonProperty] + [DataMember] public bool IsArchived { get; set; } protected void On(AppCreated @event) diff --git a/src/Squidex.Domain.Apps.Entities/Assets/BackupAssets.cs b/src/Squidex.Domain.Apps.Entities/Assets/BackupAssets.cs index d60e3070c..ebf79a790 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/BackupAssets.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/BackupAssets.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Tags; using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Entities.Assets.State; @@ -89,16 +88,16 @@ namespace Squidex.Domain.Apps.Entities.Assets private async Task RestoreTagsAsync(Guid appId, BackupReader reader) { - var tags = await reader.ReadJsonAttachmentAsync(TagsFile); + var tags = await reader.ReadJsonAttachmentAsync(TagsFile); - await tagService.RebuildTagsAsync(appId, TagGroups.Assets, tags.ToObject()); + await tagService.RebuildTagsAsync(appId, TagGroups.Assets, tags); } private async Task BackupTagsAsync(Guid appId, BackupWriter writer) { var tags = await tagService.GetExportableTagsAsync(appId, TagGroups.Assets); - await writer.WriteJsonAsync(TagsFile, JObject.FromObject(tags)); + await writer.WriteJsonAsync(TagsFile, tags); } private Task WriteAssetAsync(Guid assetId, long fileVersion, BackupWriter writer) diff --git a/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs b/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs index 44693da64..e9ebd33ec 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Runtime.Serialization; using Squidex.Domain.Apps.Core.ValidateContent; using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Assets; @@ -20,37 +20,37 @@ namespace Squidex.Domain.Apps.Entities.Assets.State { public class AssetState : DomainObjectState, IAssetEntity { - [JsonProperty] + [DataMember] public NamedId AppId { get; set; } - [JsonProperty] + [DataMember] public string FileName { get; set; } - [JsonProperty] + [DataMember] public string MimeType { get; set; } - [JsonProperty] + [DataMember] public long FileVersion { get; set; } - [JsonProperty] + [DataMember] public long FileSize { get; set; } - [JsonProperty] + [DataMember] public long TotalSize { get; set; } - [JsonProperty] + [DataMember] public bool IsImage { get; set; } - [JsonProperty] + [DataMember] public int? PixelWidth { get; set; } - [JsonProperty] + [DataMember] public int? PixelHeight { get; set; } - [JsonProperty] + [DataMember] public bool IsDeleted { get; set; } - [JsonProperty] + [DataMember] public HashSet Tags { get; set; } Guid IAssetInfo.AssetId diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs index 21067ce66..a8a660bc2 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs @@ -18,6 +18,7 @@ using Squidex.Domain.Apps.Events; using Squidex.Infrastructure; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.States; @@ -34,6 +35,7 @@ namespace Squidex.Domain.Apps.Entities.Backup private readonly IBackupArchiveLocation backupArchiveLocation; private readonly IClock clock; private readonly IEnumerable handlers; + private readonly IJsonSerializer serializer; private readonly IEventDataFormatter eventDataFormatter; private readonly IEventStore eventStore; private readonly ISemanticLog log; @@ -51,6 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Backup IEventStore eventStore, IEventDataFormatter eventDataFormatter, IEnumerable handlers, + IJsonSerializer serializer, ISemanticLog log, IStore store) { @@ -60,6 +63,7 @@ namespace Squidex.Domain.Apps.Entities.Backup Guard.NotNull(eventStore, nameof(eventStore)); Guard.NotNull(eventDataFormatter, nameof(eventDataFormatter)); Guard.NotNull(handlers, nameof(handlers)); + Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(store, nameof(store)); Guard.NotNull(log, nameof(log)); @@ -69,6 +73,7 @@ namespace Squidex.Domain.Apps.Entities.Backup this.eventStore = eventStore; this.eventDataFormatter = eventDataFormatter; this.handlers = handlers; + this.serializer = serializer; this.store = store; this.log = log; } @@ -139,7 +144,7 @@ namespace Squidex.Domain.Apps.Entities.Backup { using (var stream = await backupArchiveLocation.OpenStreamAsync(job.Id)) { - using (var writer = new BackupWriter(stream, true)) + using (var writer = new BackupWriter(serializer, stream, true)) { await eventStore.QueryAsync(async storedEvent => { diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs index 32b8faf10..b6cce2231 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs @@ -9,20 +9,19 @@ using System; using System.IO; using System.IO.Compression; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Entities.Backup.Helpers; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.States; namespace Squidex.Domain.Apps.Entities.Backup { public sealed class BackupReader : DisposableObjectBase { - private static readonly JsonSerializer Serializer = new JsonSerializer(); private readonly GuidMapper guidMapper = new GuidMapper(); private readonly ZipArchive archive; + private readonly IJsonSerializer serializer; private int readEvents; private int readAttachments; @@ -36,8 +35,12 @@ namespace Squidex.Domain.Apps.Entities.Backup get { return readAttachments; } } - public BackupReader(Stream stream) + public BackupReader(IJsonSerializer serializer, Stream stream) { + Guard.NotNull(serializer, nameof(serializer)); + + this.serializer = serializer; + archive = new ZipArchive(stream, ZipArchiveMode.Read, false); } @@ -54,7 +57,7 @@ namespace Squidex.Domain.Apps.Entities.Backup return guidMapper.OldGuid(newId); } - public async Task ReadJsonAttachmentAsync(string name) + public Task ReadJsonAttachmentAsync(string name) { Guard.NotNullOrEmpty(name, nameof(name)); @@ -65,24 +68,16 @@ namespace Squidex.Domain.Apps.Entities.Backup throw new FileNotFoundException("Cannot find attachment.", name); } - JToken result; + T result; using (var stream = attachmentEntry.Open()) { - using (var textReader = new StreamReader(stream)) - { - using (var jsonReader = new JsonTextReader(textReader)) - { - result = await JToken.ReadFromAsync(jsonReader); - - guidMapper.NewGuids(result); - } - } + result = serializer.Deserialize(stream, null, guidMapper.NewGuidOrValue); } readAttachments++; - return result; + return Task.FromResult(result); } public async Task ReadBlobAsync(string name, Func handler) @@ -105,9 +100,10 @@ namespace Squidex.Domain.Apps.Entities.Backup readAttachments++; } - public async Task ReadEventsAsync(IStreamNameResolver streamNameResolver, Func handler) + public async Task ReadEventsAsync(IStreamNameResolver streamNameResolver, IEventDataFormatter formatter, Func<(string Stream, Envelope Event), Task> handler) { Guard.NotNull(handler, nameof(handler)); + Guard.NotNull(formatter, nameof(formatter)); Guard.NotNull(streamNameResolver, nameof(streamNameResolver)); while (true) @@ -121,25 +117,12 @@ namespace Squidex.Domain.Apps.Entities.Backup using (var stream = eventEntry.Open()) { - using (var textReader = new StreamReader(stream)) - { - using (var jsonReader = new JsonTextReader(textReader)) - { - var storedEvent = Serializer.Deserialize(jsonReader); - - storedEvent.Data.Payload = guidMapper.NewGuids(storedEvent.Data.Payload); - storedEvent.Data.Metadata = guidMapper.NewGuids(storedEvent.Data.Metadata); - - var streamName = streamNameResolver.WithNewId(storedEvent.StreamName, guidMapper.NewGuidString); + var storedEvent = serializer.Deserialize(stream); - storedEvent = new StoredEvent(streamName, - storedEvent.EventPosition, - storedEvent.EventStreamNumber, - storedEvent.Data); + var eventStream = streamNameResolver.WithNewId(storedEvent.StreamName, guidMapper.NewGuidOrNull); + var eventEnvelope = formatter.Parse(storedEvent.Data, true, guidMapper.NewGuidOrValue); - await handler(storedEvent); - } - } + await handler((eventStream, eventEnvelope)); } readEvents++; diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs index fa0e793af..98363cb77 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs @@ -9,18 +9,18 @@ using System; using System.IO; using System.IO.Compression; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Entities.Backup.Helpers; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Tasks; namespace Squidex.Domain.Apps.Entities.Backup { public sealed class BackupWriter : DisposableObjectBase { - private static readonly JsonSerializer Serializer = new JsonSerializer(); private readonly ZipArchive archive; + private readonly IJsonSerializer serializer; private int writtenEvents; private int writtenAttachments; @@ -34,8 +34,12 @@ namespace Squidex.Domain.Apps.Entities.Backup get { return writtenAttachments; } } - public BackupWriter(Stream stream, bool keepOpen = false) + public BackupWriter(IJsonSerializer serializer, Stream stream, bool keepOpen = false) { + Guard.NotNull(serializer, nameof(serializer)); + + this.serializer = serializer; + archive = new ZipArchive(stream, ZipArchiveMode.Create, keepOpen); } @@ -47,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.Backup } } - public async Task WriteJsonAsync(string name, JToken value) + public Task WriteJsonAsync(string name, object value) { Guard.NotNullOrEmpty(name, nameof(name)); @@ -55,16 +59,12 @@ namespace Squidex.Domain.Apps.Entities.Backup using (var stream = attachmentEntry.Open()) { - using (var textWriter = new StreamWriter(stream)) - { - using (var jsonWriter = new JsonTextWriter(textWriter)) - { - await value.WriteToAsync(jsonWriter); - } - } + serializer.Serialize(value, stream); } writtenAttachments++; + + return TaskHelper.Done; } public async Task WriteBlobAsync(string name, Func handler) @@ -90,13 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Backup using (var stream = eventEntry.Open()) { - using (var textWriter = new StreamWriter(stream)) - { - using (var jsonWriter = new JsonTextWriter(textWriter)) - { - Serializer.Serialize(jsonWriter, storedEvent); - } - } + serializer.Serialize(storedEvent, stream); } writtenEvents++; diff --git a/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs b/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs index c0f7ac827..a2ac8973d 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs @@ -7,112 +7,39 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json.Linq; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Entities.Backup { - public sealed class GuidMapper + internal sealed class GuidMapper { private static readonly int GuidLength = Guid.Empty.ToString().Length; - private readonly List<(JObject Source, string NewKey, string OldKey)> mappings = new List<(JObject Source, string NewKey, string OldKey)>(); private readonly Dictionary oldToNewGuid = new Dictionary(); private readonly Dictionary newToOldGuid = new Dictionary(); - public Guid NewGuid(Guid oldGuid) - { - return oldToNewGuid.GetOrDefault(oldGuid); - } - public Guid OldGuid(Guid newGuid) { return newToOldGuid.GetOrDefault(newGuid); } - public string NewGuidString(string key) + public string NewGuidOrNull(string value) { - if (Guid.TryParse(key, out var guid)) + if (TryGenerateNewGuidString(value, out var result) || TryGenerateNewNamedId(value, out result)) { - return GenerateNewGuid(guid).ToString(); + return result; } return null; } - public JToken NewGuids(JToken jToken) - { - var result = NewGuidsCore(jToken); - - if (mappings.Count > 0) - { - foreach (var mapping in mappings) - { - if (mapping.Source.TryGetValue(mapping.OldKey, out var value)) - { - mapping.Source.Remove(mapping.OldKey); - mapping.Source[mapping.NewKey] = value; - } - } - - mappings.Clear(); - } - - return result; - } - - private JToken NewGuidsCore(JToken jToken) - { - switch (jToken.Type) - { - case JTokenType.String: - if (TryConvertString(jToken.ToString(), out var result)) - { - return result; - } - - break; - case JTokenType.Guid: - return GenerateNewGuid((Guid)jToken); - case JTokenType.Object: - NewGuidsCore((JObject)jToken); - break; - case JTokenType.Array: - NewGuidsCore((JArray)jToken); - break; - } - - return jToken; - } - - private void NewGuidsCore(JArray jArray) - { - for (var i = 0; i < jArray.Count; i++) - { - jArray[i] = NewGuidsCore(jArray[i]); - } - } - - private void NewGuidsCore(JObject jObject) + public string NewGuidOrValue(string value) { - foreach (var jProperty in jObject.Properties()) + if (TryGenerateNewGuidString(value, out var result) || TryGenerateNewNamedId(value, out result)) { - var newValue = NewGuidsCore(jProperty.Value); - - if (!ReferenceEquals(newValue, jProperty.Value)) - { - jProperty.Value = newValue; - } - - if (TryConvertString(jProperty.Name, out var newKey)) - { - mappings.Add((jObject, newKey, jProperty.Name)); - } + return result; } - } - private bool TryConvertString(string value, out string result) - { - return TryGenerateNewGuidString(value, out result) || TryGenerateNewNamedId(value, out result); + return value; } private bool TryGenerateNewGuidString(string value, out string result) diff --git a/src/Squidex.Domain.Apps.Entities/Backup/Helpers/Downloader.cs b/src/Squidex.Domain.Apps.Entities/Backup/Helpers/Downloader.cs index f002efa81..a567eb717 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/Helpers/Downloader.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/Helpers/Downloader.cs @@ -9,6 +9,7 @@ using System; using System.IO; using System.Net.Http; using System.Threading.Tasks; +using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Entities.Backup.Helpers { @@ -39,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Backup.Helpers } } - public static async Task OpenArchiveAsync(this IBackupArchiveLocation backupArchiveLocation, Guid id) + public static async Task OpenArchiveAsync(this IBackupArchiveLocation backupArchiveLocation, Guid id, IJsonSerializer serializer) { Stream stream = null; @@ -47,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Backup.Helpers { stream = await backupArchiveLocation.OpenStreamAsync(id); - return new BackupReader(stream); + return new BackupReader(serializer, stream); } catch (IOException) { diff --git a/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs b/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs index 0a7536d1b..4a2952e15 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs @@ -18,6 +18,7 @@ using Squidex.Domain.Apps.Events.Apps; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.States; @@ -31,6 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Backup private readonly IClock clock; private readonly ICommandBus commandBus; private readonly IEnumerable handlers; + private readonly IJsonSerializer serializer; private readonly IEventStore eventStore; private readonly IEventDataFormatter eventDataFormatter; private readonly ISemanticLog log; @@ -51,6 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Backup IEventStore eventStore, IEventDataFormatter eventDataFormatter, IEnumerable handlers, + IJsonSerializer serializer, ISemanticLog log, IStreamNameResolver streamNameResolver, IStore store) @@ -61,6 +64,7 @@ namespace Squidex.Domain.Apps.Entities.Backup Guard.NotNull(eventStore, nameof(eventStore)); Guard.NotNull(eventDataFormatter, nameof(eventDataFormatter)); Guard.NotNull(handlers, nameof(handlers)); + Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(store, nameof(store)); Guard.NotNull(streamNameResolver, nameof(streamNameResolver)); Guard.NotNull(log, nameof(log)); @@ -71,6 +75,7 @@ namespace Squidex.Domain.Apps.Entities.Backup this.eventStore = eventStore; this.eventDataFormatter = eventDataFormatter; this.handlers = handlers; + this.serializer = serializer; this.store = store; this.streamNameResolver = streamNameResolver; this.log = log; @@ -161,7 +166,7 @@ namespace Squidex.Domain.Apps.Entities.Backup await DownloadAsync(); } - using (var reader = await backupArchiveLocation.OpenArchiveAsync(CurrentJob.Id)) + using (var reader = await backupArchiveLocation.OpenArchiveAsync(CurrentJob.Id, serializer)) { using (Profiler.Trace("ReadEvents")) { @@ -273,17 +278,15 @@ namespace Squidex.Domain.Apps.Entities.Backup private async Task ReadEventsAsync(BackupReader reader) { - await reader.ReadEventsAsync(streamNameResolver, async storedEvent => + await reader.ReadEventsAsync(streamNameResolver, eventDataFormatter, async storedEvent => { - var @event = eventDataFormatter.Parse(storedEvent.Data); - - await HandleEventAsync(reader, storedEvent, @event); + await HandleEventAsync(reader, storedEvent.Stream, storedEvent.Event); }); Log("Reading events completed."); } - private async Task HandleEventAsync(BackupReader reader, StoredEvent storedEvent, Envelope @event) + private async Task HandleEventAsync(BackupReader reader, string stream, Envelope @event) { if (@event.Payload is SquidexEvent squidexEvent) { @@ -316,7 +319,7 @@ namespace Squidex.Domain.Apps.Entities.Backup var eventData = eventDataFormatter.ToEventData(@event, @event.Headers.CommitId()); var eventCommit = new List { eventData }; - await eventStore.AppendAsync(Guid.NewGuid(), storedEvent.StreamName, eventCommit); + await eventStore.AppendAsync(Guid.NewGuid(), stream, eventCommit); Log($"Read {reader.ReadEvents} events and {reader.ReadAttachments} attachments.", true); } diff --git a/src/Squidex.Domain.Apps.Entities/Backup/State/BackupState.cs b/src/Squidex.Domain.Apps.Entities/Backup/State/BackupState.cs index e75eef133..75cf87a13 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/State/BackupState.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/State/BackupState.cs @@ -6,13 +6,13 @@ // ========================================================================== using System.Collections.Generic; -using Newtonsoft.Json; +using System.Runtime.Serialization; namespace Squidex.Domain.Apps.Entities.Backup.State { public sealed class BackupState { - [JsonProperty] + [DataMember] public List Jobs { get; } = new List(); } } diff --git a/src/Squidex.Domain.Apps.Entities/Backup/State/BackupStateJob.cs b/src/Squidex.Domain.Apps.Entities/Backup/State/BackupStateJob.cs index 6da5e9dfa..209a6f1c7 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/State/BackupStateJob.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/State/BackupStateJob.cs @@ -6,29 +6,29 @@ // ========================================================================== using System; -using Newtonsoft.Json; +using System.Runtime.Serialization; using NodaTime; namespace Squidex.Domain.Apps.Entities.Backup.State { public sealed class BackupStateJob : IBackupJob { - [JsonProperty] + [DataMember] public Guid Id { get; set; } - [JsonProperty] + [DataMember] public Instant Started { get; set; } - [JsonProperty] + [DataMember] public Instant? Stopped { get; set; } - [JsonProperty] + [DataMember] public int HandledEvents { get; set; } - [JsonProperty] + [DataMember] public int HandledAssets { get; set; } - [JsonProperty] + [DataMember] public JobStatus Status { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreState.cs b/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreState.cs index d86a658fe..bbfc4db36 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreState.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreState.cs @@ -5,13 +5,13 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; +using System.Runtime.Serialization; namespace Squidex.Domain.Apps.Entities.Backup.State { public class RestoreState { - [JsonProperty] + [DataMember] public RestoreStateJob Job { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs b/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs index f3fd17042..edefb80dd 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs @@ -7,38 +7,39 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; +using System.Runtime.Serialization; using NodaTime; namespace Squidex.Domain.Apps.Entities.Backup.State { + [DataContract] public sealed class RestoreStateJob : IRestoreJob { - [JsonProperty] + [DataMember] public string AppName { get; set; } - [JsonProperty] + [DataMember] public Guid Id { get; set; } - [JsonProperty] + [DataMember] public Guid AppId { get; set; } - [JsonProperty] + [DataMember] public Uri Url { get; set; } - [JsonProperty] + [DataMember] public string NewAppName { get; set; } - [JsonProperty] + [DataMember] public Instant Started { get; set; } - [JsonProperty] + [DataMember] public Instant? Stopped { get; set; } - [JsonProperty] + [DataMember] public List Log { get; set; } = new List(); - [JsonProperty] + [DataMember] public JobStatus Status { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs index 2c1242877..d5b1316fb 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLExecutionContext.cs @@ -8,8 +8,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Entities.Assets; +using Squidex.Infrastructure.Json.Objects; + namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { public sealed class GraphQLExecutionContext : QueryExecutionContext @@ -25,29 +26,29 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL UrlGenerator = urlGenerator; } - public Task> GetReferencedAssetsAsync(JToken value) + public Task> GetReferencedAssetsAsync(IJsonValue value) { var ids = ParseIds(value); return GetReferencedAssetsAsync(ids); } - public Task> GetReferencedContentsAsync(Guid schemaId, JToken value) + public Task> GetReferencedContentsAsync(Guid schemaId, IJsonValue value) { var ids = ParseIds(value); return GetReferencedContentsAsync(schemaId, ids); } - private static ICollection ParseIds(JToken value) + private static ICollection ParseIds(IJsonValue value) { try { var result = new List(); - if (value is JArray) + if (value is JsonArray array) { - foreach (var id in value) + foreach (var id in array) { result.Add(Guid.Parse(id.ToString())); } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs index a450cf448..18b9beff3 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AllTypes.cs @@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types public static readonly IGraphType Guid = new GuidGraphType2(); - public static readonly IGraphType Date = new DateTimeGraphType(); + public static readonly IGraphType Date = new InstantGraphType(); public static readonly IGraphType Json = new JsonGraphType(); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs index 47e32ed04..c23f2c69c 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AssetGraphType.cs @@ -39,7 +39,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { Name = "created", ResolvedType = AllTypes.NonNullDate, - Resolver = Resolve(x => x.Created.ToDateTimeUtc()), + Resolver = Resolve(x => x.Created), Description = "The date and time when the asset has been created." }); @@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { Name = "lastModified", ResolvedType = AllTypes.NonNullDate, - Resolver = Resolve(x => x.LastModified.ToDateTimeUtc()), + Resolver = Resolve(x => x.LastModified), Description = "The date and time when the asset has been modified last." }); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs index cb77d343d..20358dd65 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs @@ -9,10 +9,10 @@ using System.Collections.Generic; using System.Linq; using GraphQL.Resolvers; using GraphQL.Types; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { @@ -68,7 +68,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types fieldGraphType.Description = $"The structure of the {fieldName} field of the {schemaName} content type."; - var fieldResolver = new FuncFieldResolver>(c => + var fieldResolver = new FuncFieldResolver>(c => { return c.Source.GetOrDefault(field.Name); }); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs index 40990b9ad..31f68a324 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentGraphType.cs @@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { Name = "created", ResolvedType = AllTypes.NonNullDate, - Resolver = Resolve(x => x.Created.ToDateTimeUtc()), + Resolver = Resolve(x => x.Created), Description = $"The date and time when the {schemaName} content has been created." }); @@ -58,7 +58,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { Name = "lastModified", ResolvedType = AllTypes.NonNullDate, - Resolver = Resolve(x => x.LastModified.ToDateTimeUtc()), + Resolver = Resolve(x => x.LastModified), Description = $"The date and time when the {schemaName} content has been modified last." }); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs index b0dc095d2..35c0a1b2e 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedGraphType.cs @@ -8,14 +8,14 @@ using System.Linq; using GraphQL.Resolvers; using GraphQL.Types; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { - public sealed class NestedGraphType : ObjectGraphType + public sealed class NestedGraphType : ObjectGraphType { public NestedGraphType(IGraphModel model, ISchemaEntity schema, IArrayField field) { @@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { var resolver = new FuncFieldResolver(c => { - if (((JObject)c.Source).TryGetValue(nestedField.Name, out var value)) + if (((JsonObject)c.Source).TryGetValue(nestedField.Name, out var value)) { return fieldInfo.Resolver(value, c); } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs index fa1e34514..2ed69033c 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs @@ -7,13 +7,13 @@ using System; using GraphQL.Types; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types { - public delegate object ValueResolver(JToken value, ResolveFieldContext context); + public delegate object ValueResolver(IJsonValue value, ResolveFieldContext context); public sealed class QueryGraphTypeVisitor : IFieldVisitor<(IGraphType ResolveType, ValueResolver Resolver)> { diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantGraphType.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantGraphType.cs new file mode 100644 index 000000000..2f45fe6a9 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantGraphType.cs @@ -0,0 +1,41 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using GraphQL.Language.AST; +using GraphQL.Types; +using NodaTime.Text; + +namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils +{ + public sealed class InstantGraphType : DateGraphType + { + public override object Serialize(object value) + { + return ParseValue(value); + } + + public override object ParseValue(object value) + { + return InstantPattern.General.Parse(value.ToString()).Value; + } + + public override object ParseLiteral(IValue value) + { + if (value is InstantValue timeValue) + { + return ParseValue(timeValue.Value); + } + + if (value is StringValue stringValue) + { + return ParseValue(stringValue.Value); + } + + return null; + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantValue.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantValue.cs new file mode 100644 index 000000000..1af6d2e92 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/InstantValue.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using GraphQL.Language.AST; +using NodaTime; + +namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils +{ + public sealed class InstantValue : ValueNode + { + public InstantValue(Instant value) + { + Value = value; + } + + protected override bool Equals(ValueNode node) + { + return Value.Equals(node.Value); + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonConverter.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonConverter.cs index 62bc939fb..a433a5fb3 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonConverter.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonConverter.cs @@ -7,7 +7,7 @@ using GraphQL.Language.AST; using GraphQL.Types; -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils { @@ -21,12 +21,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils public IValue Convert(object value, IGraphType type) { - return new JsonValue(value as JObject); + return new JsonValue(value as JsonObject); } public bool Matches(object value, IGraphType type) { - return value is JObject; + return value is JsonObject; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonValue.cs b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonValue.cs index 4977e33d2..01449380f 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonValue.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Utils/JsonValue.cs @@ -6,18 +6,18 @@ // ========================================================================== using GraphQL.Language.AST; -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Utils { - public sealed class JsonValue : ValueNode + public sealed class JsonValue : ValueNode { - public JsonValue(JObject value) + public JsonValue(IJsonValue value) { Value = value; } - protected override bool Equals(ValueNode node) + protected override bool Equals(ValueNode node) { return false; } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs b/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs index 15f2fc357..56936bb0a 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs @@ -6,7 +6,7 @@ // ========================================================================== using System; -using Newtonsoft.Json; +using System.Runtime.Serialization; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Contents; @@ -19,28 +19,28 @@ namespace Squidex.Domain.Apps.Entities.Contents.State { public class ContentState : DomainObjectState, IContentEntity { - [JsonProperty] + [DataMember] public NamedId AppId { get; set; } - [JsonProperty] + [DataMember] public NamedId SchemaId { get; set; } - [JsonProperty] + [DataMember] public NamedContentData Data { get; set; } - [JsonProperty] + [DataMember] public NamedContentData DataDraft { get; set; } - [JsonProperty] + [DataMember] public ScheduleJob ScheduleJob { get; set; } - [JsonProperty] + [DataMember] public bool IsPending { get; set; } - [JsonProperty] + [DataMember] public bool IsDeleted { get; set; } - [JsonProperty] + [DataMember] public Status Status { get; set; } protected void On(ContentCreated @event) diff --git a/src/Squidex.Domain.Apps.Entities/DomainObjectState.cs b/src/Squidex.Domain.Apps.Entities/DomainObjectState.cs index 13ce32acc..58b6341b5 100644 --- a/src/Squidex.Domain.Apps.Entities/DomainObjectState.cs +++ b/src/Squidex.Domain.Apps.Entities/DomainObjectState.cs @@ -6,7 +6,7 @@ // ========================================================================== using System; -using Newtonsoft.Json; +using System.Runtime.Serialization; using NodaTime; using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; @@ -24,22 +24,22 @@ namespace Squidex.Domain.Apps.Entities IUpdateableEntityWithLastModifiedBy where T : Cloneable { - [JsonProperty] + [DataMember] public Guid Id { get; set; } - [JsonProperty] + [DataMember] public RefToken CreatedBy { get; set; } - [JsonProperty] + [DataMember] public RefToken LastModifiedBy { get; set; } - [JsonProperty] + [DataMember] public Instant Created { get; set; } - [JsonProperty] + [DataMember] public Instant LastModified { get; set; } - [JsonProperty] + [DataMember] public long Version { get; set; } = EtagVersion.Empty; public T Clone() diff --git a/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs b/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs index 80da5ed16..a12f9a744 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs @@ -6,7 +6,7 @@ // ========================================================================== using System; -using Newtonsoft.Json; +using System.Runtime.Serialization; using Squidex.Domain.Apps.Core.Rules; using Squidex.Domain.Apps.Events; using Squidex.Domain.Apps.Events.Rules; @@ -20,13 +20,13 @@ namespace Squidex.Domain.Apps.Entities.Rules.State [CollectionName("Rules")] public class RuleState : DomainObjectState, IRuleEntity { - [JsonProperty] + [DataMember] public NamedId AppId { get; set; } - [JsonProperty] + [DataMember] public Rule RuleDef { get; set; } - [JsonProperty] + [DataMember] public bool IsDeleted { get; set; } protected void On(RuleCreated @event) diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs b/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs index fdec25995..59aebd11e 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs @@ -6,7 +6,7 @@ // ========================================================================== using System; -using Newtonsoft.Json; +using System.Runtime.Serialization; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Events; @@ -22,43 +22,43 @@ namespace Squidex.Domain.Apps.Entities.Schemas.State [CollectionName("Schemas")] public class SchemaState : DomainObjectState, ISchemaEntity { - [JsonProperty] + [DataMember] public NamedId AppId { get; set; } - [JsonProperty] + [DataMember] public string Name { get; set; } - [JsonProperty] + [DataMember] public string Category { get; set; } - [JsonProperty] + [DataMember] public int TotalFields { get; set; } - [JsonProperty] + [DataMember] public bool IsDeleted { get; set; } - [JsonProperty] + [DataMember] public bool IsSingleton { get; set; } - [JsonProperty] + [DataMember] public string ScriptQuery { get; set; } - [JsonProperty] + [DataMember] public string ScriptCreate { get; set; } - [JsonProperty] + [DataMember] public string ScriptUpdate { get; set; } - [JsonProperty] + [DataMember] public string ScriptDelete { get; set; } - [JsonProperty] + [DataMember] public string ScriptChange { get; set; } - [JsonProperty] + [DataMember] public Schema SchemaDef { get; set; } - [JsonIgnore] + [IgnoreDataMember] public bool IsPublished { get { return SchemaDef.IsPublished; } diff --git a/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs b/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs index 0673d3b5b..007b19de8 100644 --- a/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs +++ b/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Globalization; using Squidex.Infrastructure.EventSourcing; namespace Squidex.Domain.Apps.Events @@ -15,7 +14,7 @@ namespace Squidex.Domain.Apps.Events { public static Guid AppId(this EnvelopeHeaders headers) { - return headers[SquidexHeaders.AppId].ToGuid(CultureInfo.InvariantCulture); + return headers[SquidexHeaders.AppId].ToGuid(); } public static Envelope SetAppId(this Envelope envelope, Guid value) where T : class diff --git a/src/Squidex.Infrastructure.Redis/RedisPubSub.cs b/src/Squidex.Infrastructure.Redis/RedisPubSub.cs index ce5e9f1f0..48cdb58b0 100644 --- a/src/Squidex.Infrastructure.Redis/RedisPubSub.cs +++ b/src/Squidex.Infrastructure.Redis/RedisPubSub.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; using Squidex.Infrastructure.Tasks; using StackExchange.Redis; @@ -19,11 +20,13 @@ namespace Squidex.Infrastructure { private readonly ConcurrentDictionary subscriptions = new ConcurrentDictionary(); private readonly Lazy redisClient; + private readonly IJsonSerializer serializer; private readonly Lazy redisSubscriber; private readonly ISemanticLog log; - public RedisPubSub(Lazy redis, ISemanticLog log) + public RedisPubSub(Lazy redis, IJsonSerializer serializer, ISemanticLog log) { + Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(redis, nameof(redis)); Guard.NotNull(log, nameof(log)); @@ -31,6 +34,8 @@ namespace Squidex.Infrastructure redisClient = redis; redisSubscriber = new Lazy(() => redis.Value.GetSubscriber()); + + this.serializer = serializer; } public Task InitializeAsync(CancellationToken ct = default(CancellationToken)) @@ -61,7 +66,7 @@ namespace Squidex.Infrastructure { var typeName = typeof(T).FullName; - return (RedisSubscription)subscriptions.GetOrAdd(typeName, this, (k, c) => new RedisSubscription(c.redisSubscriber.Value, k, c.log)); + return (RedisSubscription)subscriptions.GetOrAdd(typeName, this, (k, c) => new RedisSubscription(c.redisSubscriber.Value, serializer, k, c.log)); } } } diff --git a/src/Squidex.Infrastructure.Redis/RedisSubscription.cs b/src/Squidex.Infrastructure.Redis/RedisSubscription.cs index d2e88a555..dc8c10be2 100644 --- a/src/Squidex.Infrastructure.Redis/RedisSubscription.cs +++ b/src/Squidex.Infrastructure.Redis/RedisSubscription.cs @@ -7,7 +7,7 @@ using System; using System.Reactive.Subjects; -using Newtonsoft.Json; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; using StackExchange.Redis; @@ -20,6 +20,7 @@ namespace Squidex.Infrastructure private readonly Guid selfId = Guid.NewGuid(); private readonly Subject subject = new Subject(); private readonly ISubscriber subscriber; + private readonly IJsonSerializer serializer; private readonly ISemanticLog log; private readonly string channelName; @@ -30,10 +31,11 @@ namespace Squidex.Infrastructure public Guid Sender; } - public RedisSubscription(ISubscriber subscriber, string channelName, ISemanticLog log) + public RedisSubscription(ISubscriber subscriber, IJsonSerializer serializer, string channelName, ISemanticLog log) { this.log = log; + this.serializer = serializer; this.subscriber = subscriber; this.subscriber.Subscribe(channelName, (channel, value) => HandleMessage(value)); @@ -46,7 +48,7 @@ namespace Squidex.Infrastructure { var senderId = notifySelf ? Guid.Empty : selfId; - var envelope = JsonConvert.SerializeObject(new Envelope { Sender = senderId, Payload = (T)value }); + var envelope = serializer.Serialize(new Envelope { Sender = senderId, Payload = (T)value }); subscriber.Publish(channelName, envelope); } @@ -68,7 +70,7 @@ namespace Squidex.Infrastructure return; } - var envelope = JsonConvert.DeserializeObject(value); + var envelope = serializer.Deserialize(value); if (envelope.Sender != selfId) { diff --git a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs index 22735b68d..ba6f659a8 100644 --- a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs @@ -25,12 +25,12 @@ namespace Squidex.Infrastructure.EventSourcing this.serializer = serializer; } - public Envelope Parse(EventData eventData, bool migrate = true) + public Envelope Parse(EventData eventData, bool migrate = true, Func stringConverter = null) { var eventType = typeNameRegistry.GetType(eventData.Type); - var eventHeaders = serializer.Deserialize(eventData.Metadata); - var eventContent = serializer.Deserialize(eventData.Payload, eventType); + var eventHeaders = serializer.Deserialize(eventData.Metadata, null, stringConverter); + var eventContent = serializer.Deserialize(eventData.Payload, eventType, stringConverter); if (migrate && eventContent is IMigratedEvent migratedEvent) { diff --git a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs index a1d60034c..f1dce1331 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Globalization; using NodaTime; namespace Squidex.Infrastructure.EventSourcing @@ -27,7 +26,7 @@ namespace Squidex.Infrastructure.EventSourcing public static long EventStreamNumber(this EnvelopeHeaders headers) { - return headers[CommonHeaders.EventStreamNumber].ToInt64(CultureInfo.InvariantCulture); + return headers[CommonHeaders.EventStreamNumber].ToInt64(); } public static Envelope SetEventStreamNumber(this Envelope envelope, long value) where T : class @@ -39,7 +38,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Guid CommitId(this EnvelopeHeaders headers) { - return headers[CommonHeaders.CommitId].ToGuid(CultureInfo.InvariantCulture); + return headers[CommonHeaders.CommitId].ToGuid(); } public static Envelope SetCommitId(this Envelope envelope, Guid value) where T : class @@ -51,7 +50,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Guid AggregateId(this EnvelopeHeaders headers) { - return headers[CommonHeaders.AggregateId].ToGuid(CultureInfo.InvariantCulture); + return headers[CommonHeaders.AggregateId].ToGuid(); } public static Envelope SetAggregateId(this Envelope envelope, Guid value) where T : class @@ -63,7 +62,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Guid EventId(this EnvelopeHeaders headers) { - return headers[CommonHeaders.EventId].ToGuid(CultureInfo.InvariantCulture); + return headers[CommonHeaders.EventId].ToGuid(); } public static Envelope SetEventId(this Envelope envelope, Guid value) where T : class @@ -75,7 +74,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Instant Timestamp(this EnvelopeHeaders headers) { - return headers[CommonHeaders.Timestamp].ToInstant(CultureInfo.InvariantCulture); + return headers[CommonHeaders.Timestamp].ToInstant(); } public static Envelope SetTimestamp(this Envelope envelope, Instant value) where T : class diff --git a/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs index 6cd586c84..071808fb6 100644 --- a/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs @@ -11,7 +11,7 @@ namespace Squidex.Infrastructure.EventSourcing { public interface IEventDataFormatter { - Envelope Parse(EventData eventData, bool migrate = true); + Envelope Parse(EventData eventData, bool migrate = true, Func stringConverter = null); EventData ToEventData(Envelope envelope, Guid commitId, bool migrate = true); } diff --git a/src/Squidex.Infrastructure/Json/IJsonSerializer.cs b/src/Squidex.Infrastructure/Json/IJsonSerializer.cs index e42fb9ea3..704ebaa78 100644 --- a/src/Squidex.Infrastructure/Json/IJsonSerializer.cs +++ b/src/Squidex.Infrastructure/Json/IJsonSerializer.cs @@ -12,12 +12,12 @@ namespace Squidex.Infrastructure.Json { public interface IJsonSerializer { - string Serialize(T value); + string Serialize(T value, bool intented = false); void Serialize(T value, Stream stream); - T Deserialize(string value, Type actualType = null); + T Deserialize(string value, Type actualType = null, Func stringConverter = null); - T Deserialize(Stream stream, Type actualType = null); + T Deserialize(Stream stream, Type actualType = null, Func stringConverter = null); } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs index 81825b5e1..5b31bb412 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -10,15 +10,12 @@ using System.Globalization; using Newtonsoft.Json; using Squidex.Infrastructure.Json.Objects; +#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class JsonValueConverter : JsonConverter { - public override bool CanConvert(Type objectType) - { - return typeof(IJsonValue).IsAssignableFrom(objectType); - } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return ReadJson(reader); @@ -125,36 +122,46 @@ namespace Squidex.Infrastructure.Json.Newtonsoft writer.WriteValue(s.Value); break; case JsonScalar s: - writer.WriteValue(s.Value); - break; - case JsonArray array: + + if (s.Value % 1 == 0) + { + writer.WriteValue((long)s.Value); + } + else { - writer.WriteStartArray(); + writer.WriteValue(s.Value); + } - foreach (var item in array) - { - WriteJson(writer, item); - } + break; + case JsonArray array: + writer.WriteStartArray(); - writer.WriteEndArray(); - break; + foreach (var item in array) + { + WriteJson(writer, item); } - case JsonObject obj: - { - writer.WriteStartObject(); + writer.WriteEndArray(); + break; - foreach (var kvp in obj) - { - writer.WritePropertyName(kvp.Key); + case JsonObject obj: + writer.WriteStartObject(); - WriteJson(writer, kvp.Value); - } + foreach (var kvp in obj) + { + writer.WritePropertyName(kvp.Key); - writer.WriteEndObject(); - break; + WriteJson(writer, kvp.Value); } + + writer.WriteEndObject(); + break; } } + + public override bool CanConvert(Type objectType) + { + return typeof(IJsonValue).IsAssignableFrom(objectType); + } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs index a9a045ed3..3a79cd5d5 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NewtonsoftJsonSerializer.cs @@ -16,6 +16,32 @@ namespace Squidex.Infrastructure.Json.Newtonsoft private readonly JsonSerializerSettings settings; private readonly JsonSerializer serializer; + private sealed class CustomReader : JsonTextReader + { + private readonly Func stringConverter; + + public override object Value + { + get + { + var value = base.Value; + + if (value is string s) + { + return stringConverter(s); + } + + return value; + } + } + + public CustomReader(TextReader reader, Func stringConverter) + : base(reader) + { + this.stringConverter = stringConverter; + } + } + public NewtonsoftJsonSerializer(JsonSerializerSettings settings) { Guard.NotNull(settings, nameof(settings)); @@ -25,36 +51,50 @@ namespace Squidex.Infrastructure.Json.Newtonsoft serializer = JsonSerializer.Create(settings); } - public T Deserialize(string value, Type actualType = null) + public string Serialize(T value, bool intented) { - actualType = actualType ?? typeof(T); - - return (T)JsonConvert.DeserializeObject(value, actualType, settings); + return JsonConvert.SerializeObject(value, intented ? Formatting.Indented : Formatting.None, settings); } - public T Deserialize(Stream stream, Type actualType = null) + public void Serialize(T value, Stream stream) { - using (var streamReader = new StreamReader(stream)) + using (var writer = new StreamWriter(stream)) { - actualType = actualType ?? typeof(T); + serializer.Serialize(writer, value); - return (T)serializer.Deserialize(streamReader, actualType); + writer.Flush(); } } - public string Serialize(T value) + public T Deserialize(string value, Type actualType = null, Func stringConverter = null) { - return JsonConvert.SerializeObject(value, settings); + using (var textReader = new StringReader(value)) + { + actualType = actualType ?? typeof(T); + + using (var reader = GetReader(stringConverter, textReader)) + { + return (T)serializer.Deserialize(reader, actualType); + } + } } - public void Serialize(T value, Stream stream) + public T Deserialize(Stream stream, Type actualType = null, Func stringConverter = null) { - using (var writer = new StreamWriter(stream)) + using (var textReader = new StreamReader(stream)) { - serializer.Serialize(writer, value); + actualType = actualType ?? typeof(T); - writer.Flush(); + using (var reader = GetReader(stringConverter, textReader)) + { + return (T)serializer.Deserialize(reader, actualType); + } } } + + private static JsonTextReader GetReader(Func stringConverter, TextReader textReader) + { + return stringConverter != null ? new CustomReader(textReader, stringConverter) : new JsonTextReader(textReader); + } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs index 27bda90ae..8eb624c1f 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs @@ -22,9 +22,9 @@ namespace Squidex.Infrastructure.Json.Newtonsoft { writer.WritePropertyName(kvp.Key); - if (kvp.Value.RawValue is Instant) + if (kvp.Value.RawValue is Instant instant) { - writer.WriteValue(kvp.Value.ToString()); + writer.WriteValue(instant.ToString()); } else { diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs index 06c3325b8..3fc3ae13e 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using NodaTime; namespace Squidex.Infrastructure.Json.Objects { @@ -59,6 +60,8 @@ namespace Squidex.Infrastructure.Json.Objects return Create(i); case long l: return Create(l); + case Instant i: + return Create(i); } throw new ArgumentException("Invalid json type"); @@ -76,6 +79,16 @@ namespace Squidex.Infrastructure.Json.Objects return new JsonScalar(JsonValueType.Number, value); } + public static IJsonValue Create(Instant? value) + { + if (value == null) + { + return Null; + } + + return Create(value.Value.ToString()); + } + public static IJsonValue Create(double? value) { if (value == null) diff --git a/src/Squidex.Infrastructure/Language.cs b/src/Squidex.Infrastructure/Language.cs index ba5c546b6..981d7ee47 100644 --- a/src/Squidex.Infrastructure/Language.cs +++ b/src/Squidex.Infrastructure/Language.cs @@ -18,7 +18,7 @@ namespace Squidex.Infrastructure private static Language AddLanguage(string iso2Code, string englishName) { - return AllLanguagesField.GetOrAdd(iso2Code, code => new Language(code, englishName)); + return AllLanguagesField.GetOrAdd(iso2Code, englishName, (c, n) => new Language(c, n)); } public static Language GetLanguage(string iso2Code) diff --git a/src/Squidex.Infrastructure/Orleans/J{T}.cs b/src/Squidex.Infrastructure/Orleans/J{T}.cs index bfef10aac..8946ef845 100644 --- a/src/Squidex.Infrastructure/Orleans/J{T}.cs +++ b/src/Squidex.Infrastructure/Orleans/J{T}.cs @@ -82,7 +82,7 @@ namespace Squidex.Infrastructure.Orleans { try { - return context?.ServiceProvider?.GetService() ?? J.DefaultSerializer; + return context?.ServiceProvider?.GetRequiredService() ?? J.DefaultSerializer; } catch { diff --git a/src/Squidex.Infrastructure/PropertyValue.cs b/src/Squidex.Infrastructure/PropertyValue.cs index 8187e0b7a..ddec447c6 100644 --- a/src/Squidex.Infrastructure/PropertyValue.cs +++ b/src/Squidex.Infrastructure/PropertyValue.cs @@ -18,24 +18,24 @@ namespace Squidex.Infrastructure { private readonly object rawValue; - private static readonly Dictionary> Parsers = - new Dictionary> + private static readonly Dictionary> Parsers = + new Dictionary> { - { typeof(string), (p, c) => p.ToString() }, - { typeof(bool), (p, c) => p.ToBoolean(c) }, - { typeof(bool?), (p, c) => p.ToNullableBoolean(c) }, - { typeof(float), (p, c) => p.ToSingle(c) }, - { typeof(float?), (p, c) => p.ToNullableSingle(c) }, - { typeof(double), (p, c) => p.ToDouble(c) }, - { typeof(double?), (p, c) => p.ToNullableDouble(c) }, - { typeof(int), (p, c) => p.ToInt32(c) }, - { typeof(int?), (p, c) => p.ToNullableInt32(c) }, - { typeof(long), (p, c) => p.ToInt64(c) }, - { typeof(long?), (p, c) => p.ToNullableInt64(c) }, - { typeof(Instant), (p, c) => p.ToInstant(c) }, - { typeof(Instant?), (p, c) => p.ToNullableInstant(c) }, - { typeof(Guid), (p, c) => p.ToGuid(c) }, - { typeof(Guid?), (p, c) => p.ToNullableGuid(c) } + { typeof(string), p => p.ToString() }, + { typeof(bool), p => p.ToBoolean() }, + { typeof(bool?), p => p.ToNullableBoolean() }, + { typeof(float), p => p.ToSingle() }, + { typeof(float?), p => p.ToNullableSingle() }, + { typeof(double), p => p.ToDouble() }, + { typeof(double?), p => p.ToNullableDouble() }, + { typeof(int), p => p.ToInt32() }, + { typeof(int?), p => p.ToNullableInt32() }, + { typeof(long), p => p.ToInt64() }, + { typeof(long?), p => p.ToNullableInt64() }, + { typeof(Instant), p => p.ToInstant() }, + { typeof(Instant?), p => p.ToNullableInstant() }, + { typeof(Guid), p => p.ToGuid() }, + { typeof(Guid?), p => p.ToNullableGuid() } }; public object RawValue @@ -62,7 +62,7 @@ namespace Squidex.Infrastructure return false; } - result = parser(this, CultureInfo.InvariantCulture); + result = parser(this); return true; } @@ -72,74 +72,74 @@ namespace Squidex.Infrastructure return rawValue?.ToString(); } - public bool ToBoolean(CultureInfo culture) + public bool ToBoolean() { - return ToOrParseValue(culture, ParseBoolean); + return ToOrParseValue(CultureInfo.InvariantCulture, ParseBoolean); } - public bool? ToNullableBoolean(CultureInfo culture) + public bool? ToNullableBoolean() { - return ToNullableOrParseValue(culture, ParseBoolean); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, ParseBoolean); } - public float ToSingle(CultureInfo culture) + public float ToSingle() { - return ToOrParseValue(culture, x => float.Parse(x, culture)); + return ToOrParseValue(CultureInfo.InvariantCulture, x => float.Parse(x, CultureInfo.InvariantCulture)); } - public float? ToNullableSingle(CultureInfo culture) + public float? ToNullableSingle() { - return ToNullableOrParseValue(culture, x => float.Parse(x, culture)); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => float.Parse(x, CultureInfo.InvariantCulture)); } - public double ToDouble(CultureInfo culture) + public double ToDouble() { - return ToOrParseValue(culture, x => double.Parse(x, culture)); + return ToOrParseValue(CultureInfo.InvariantCulture, x => double.Parse(x, CultureInfo.InvariantCulture)); } - public double? ToNullableDouble(CultureInfo culture) + public double? ToNullableDouble() { - return ToNullableOrParseValue(culture, x => double.Parse(x, culture)); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => double.Parse(x, CultureInfo.InvariantCulture)); } - public int ToInt32(CultureInfo culture) + public int ToInt32() { - return ToOrParseValue(culture, x => int.Parse(x, culture)); + return ToOrParseValue(CultureInfo.InvariantCulture, x => int.Parse(x, CultureInfo.InvariantCulture)); } - public int? ToNullableInt32(CultureInfo culture) + public int? ToNullableInt32() { - return ToNullableOrParseValue(culture, x => int.Parse(x, culture)); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => int.Parse(x, CultureInfo.InvariantCulture)); } - public long ToInt64(CultureInfo culture) + public long ToInt64() { - return ToOrParseValue(culture, x => long.Parse(x, culture)); + return ToOrParseValue(CultureInfo.InvariantCulture, x => long.Parse(x, CultureInfo.InvariantCulture)); } - public long? ToNullableInt64(CultureInfo culture) + public long? ToNullableInt64() { - return ToNullableOrParseValue(culture, x => long.Parse(x, culture)); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => long.Parse(x, CultureInfo.InvariantCulture)); } - public Instant ToInstant(CultureInfo culture) + public Instant ToInstant() { - return ToOrParseValue(culture, x => InstantPattern.General.Parse(x).Value); + return ToOrParseValue(CultureInfo.InvariantCulture, x => InstantPattern.General.Parse(x).Value); } - public Instant? ToNullableInstant(CultureInfo culture) + public Instant? ToNullableInstant() { - return ToNullableOrParseValue(culture, x => InstantPattern.General.Parse(x).Value); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => InstantPattern.General.Parse(x).Value); } - public Guid ToGuid(CultureInfo culture) + public Guid ToGuid() { - return ToOrParseValue(culture, Guid.Parse); + return ToOrParseValue(CultureInfo.InvariantCulture, Guid.Parse); } - public Guid? ToNullableGuid(CultureInfo culture) + public Guid? ToNullableGuid() { - return ToNullableOrParseValue(culture, Guid.Parse); + return ToNullableOrParseValue(CultureInfo.InvariantCulture, Guid.Parse); } private T? ToNullableOrParseValue(IFormatProvider culture, Func parser) where T : struct diff --git a/src/Squidex/Areas/Api/Config/Swagger/SwaggerExtensions.cs b/src/Squidex/Areas/Api/Config/Swagger/SwaggerExtensions.cs index 07e0f2c6f..96d827867 100644 --- a/src/Squidex/Areas/Api/Config/Swagger/SwaggerExtensions.cs +++ b/src/Squidex/Areas/Api/Config/Swagger/SwaggerExtensions.cs @@ -17,7 +17,7 @@ namespace Squidex.Areas.Api.Config.Swagger { public static void UseMySwagger(this IApplicationBuilder app) { - var urlOptions = app.ApplicationServices.GetService>().Value; + var urlOptions = app.ApplicationServices.GetRequiredService>().Value; app.UseSwaggerWithApiExplorer(settings => { diff --git a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs index 336025ee0..d226cc06f 100644 --- a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs +++ b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs @@ -28,7 +28,7 @@ namespace Squidex.Areas.Api.Config.Swagger { services.AddSingleton(typeof(SwaggerSettings), s => { - var urlOptions = s.GetService>().Value; + var urlOptions = s.GetRequiredService>().Value; var settings = new SwaggerSettings() .AddAssetODataParams() diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppCreatedDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppCreatedDto.cs index 792296462..38e6adae1 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppCreatedDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppCreatedDto.cs @@ -8,7 +8,6 @@ using System; using System.ComponentModel.DataAnnotations; using System.Linq; -using Newtonsoft.Json; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Entities.Apps.Services; using Squidex.Infrastructure.Commands; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs index f2774e4b4..df40cecd5 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs @@ -9,7 +9,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Newtonsoft.Json; using NodaTime; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.Services; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AssignContributorDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AssignContributorDto.cs index 0efd8885b..ad429ac14 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AssignContributorDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AssignContributorDto.cs @@ -6,7 +6,6 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; -using Newtonsoft.Json; using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Infrastructure.Reflection; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs index 4fde2f7b1..75d6b8da3 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using Newtonsoft.Json; using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Infrastructure.Reflection; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs index 0bc35ef83..42ea190e5 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs @@ -6,7 +6,6 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; -using Newtonsoft.Json; namespace Squidex.Areas.Api.Controllers.Apps.Models { diff --git a/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs b/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs index 8262de435..b6c3f5f53 100644 --- a/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs +++ b/src/Squidex/Areas/Api/Controllers/UI/Models/UpdateSettingDto.cs @@ -5,7 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Areas.Api.Controllers.UI.Models { @@ -14,6 +14,6 @@ namespace Squidex.Areas.Api.Controllers.UI.Models /// /// The value for the setting. /// - public JToken Value { get; set; } + public IJsonValue Value { get; set; } } } diff --git a/src/Squidex/Areas/Api/Controllers/UI/UIController.cs b/src/Squidex/Areas/Api/Controllers/UI/UIController.cs index 385c6e20e..d5c486d93 100644 --- a/src/Squidex/Areas/Api/Controllers/UI/UIController.cs +++ b/src/Squidex/Areas/Api/Controllers/UI/UIController.cs @@ -55,9 +55,10 @@ namespace Squidex.Areas.Api.Controllers.UI { var result = await grainFactory.GetGrain(AppId).GetAsync(); - result.Value["mapType"] = uiOptions.Map?.Type ?? "OSM"; - result.Value["mapKey"] = uiOptions.Map?.GoogleMaps?.Key; - result.Value["supportTwitterAction"] = twitterOptions.IsConfigured(); + result.Value.Add("mapType", uiOptions.Map?.Type ?? "OSM"); + result.Value.Add("mapKey", uiOptions.Map?.GoogleMaps?.Key); + + result.Value.Add("supportTwitterAction", twitterOptions.IsConfigured()); return Ok(result.Value); } diff --git a/src/Squidex/Areas/IdentityServer/Config/IdentityServerExtensions.cs b/src/Squidex/Areas/IdentityServer/Config/IdentityServerExtensions.cs index f7bc37b51..7ea0f39dc 100644 --- a/src/Squidex/Areas/IdentityServer/Config/IdentityServerExtensions.cs +++ b/src/Squidex/Areas/IdentityServer/Config/IdentityServerExtensions.cs @@ -31,12 +31,12 @@ namespace Squidex.Areas.IdentityServer.Config public static IServiceProvider UseMyAdmin(this IServiceProvider services) { - var options = services.GetService>().Value; + var options = services.GetRequiredService>().Value; - var userManager = services.GetService>(); - var userFactory = services.GetService(); + var userManager = services.GetRequiredService>(); + var userFactory = services.GetRequiredService(); - var log = services.GetService(); + var log = services.GetRequiredService(); if (options.IsAdminConfigured()) { diff --git a/src/Squidex/Config/Domain/EventPublishersServices.cs b/src/Squidex/Config/Domain/EventPublishersServices.cs index 9116f7594..dad6cd6ec 100644 --- a/src/Squidex/Config/Domain/EventPublishersServices.cs +++ b/src/Squidex/Config/Domain/EventPublishersServices.cs @@ -8,10 +8,10 @@ using System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; namespace Squidex.Config.Domain { @@ -54,7 +54,7 @@ namespace Squidex.Config.Domain if (enabled) { - services.AddSingletonAs(c => new RabbitMqEventConsumer(c.GetRequiredService(), name, publisherConfig, exchange, eventsFilter)) + services.AddSingletonAs(c => new RabbitMqEventConsumer(c.GetRequiredService(), name, publisherConfig, exchange, eventsFilter)) .As(); } } diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index be0d316e6..10596cbbe 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -20,7 +20,7 @@ using Squidex.Domain.Apps.Events; using Squidex.Extensions.Actions; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Config.Domain { @@ -49,6 +49,7 @@ namespace Squidex.Config.Domain new AppPatternsConverter(), new ClaimsPrincipalConverter(), new InstantConverter(), + new JsonValueConverter(), new LanguageConverter(), new LanguagesConfigConverter(), new NamedGuidIdConverter(), @@ -86,6 +87,8 @@ namespace Squidex.Config.Domain services.AddSingleton(DefaultJsonSerializer); services.AddSingleton(TypeNameRegistry); + services.AddSingleton(new NewtonsoftJsonSerializer(DefaultJsonSettings)); + return services; } diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index eb5c8065f..5731d4744 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -29,6 +29,7 @@ using Squidex.Domain.Users.MongoDb.Infrastructure; using Squidex.Infrastructure; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Migrations; using Squidex.Infrastructure.MongoDb; using Squidex.Infrastructure.States; @@ -88,7 +89,7 @@ namespace Squidex.Config.Domain .As() .As>(); - services.AddSingletonAs(c => new MongoContentRepository(mongoContentDatabase, c.GetService())) + services.AddSingletonAs(c => new MongoContentRepository(mongoContentDatabase, c.GetRequiredService(), c.GetRequiredService())) .As() .As>() .As(); diff --git a/src/Squidex/Config/Domain/SubscriptionServices.cs b/src/Squidex/Config/Domain/SubscriptionServices.cs index a9205dbeb..10437c2b7 100644 --- a/src/Squidex/Config/Domain/SubscriptionServices.cs +++ b/src/Squidex/Config/Domain/SubscriptionServices.cs @@ -19,7 +19,7 @@ namespace Squidex.Config.Domain { public static void AddMySubscriptionServices(this IServiceCollection services, IConfiguration config) { - services.AddSingletonAs(c => c.GetService>()?.Value?.Plans.OrEmpty()); + services.AddSingletonAs(c => c.GetRequiredService>()?.Value?.Plans.OrEmpty()); services.AddSingletonAs() .As(); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs index 70d28c50b..e9f155b52 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Rules/RuleTests.cs @@ -128,7 +128,7 @@ namespace Squidex.Domain.Apps.Core.Model.Rules [MemberData(nameof(Triggers))] public void Should_freeze_triggers(RuleTrigger trigger) { - TestData.TestFreeze(trigger); + TestUtils.TestFreeze(trigger); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs index ce33221b3..439600188 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs @@ -110,7 +110,7 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas [MemberData(nameof(FieldProperties))] public void Should_freeze_field_properties(FieldProperties action) { - TestData.TestFreeze(action); + TestUtils.TestFreeze(action); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs index 1f8073699..4f426ee04 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs @@ -278,7 +278,7 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas [Fact] public void Should_serialize_and_deserialize_schema() { - var schemaSource = TestData.MixedSchema(); + var schemaSource = TestUtils.MixedSchema(); var schemaTarget = schemaSource.SerializeAndDeserialize(); schemaTarget.Should().BeEquivalentTo(schemaSource); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs index 0c2d23704..f9b90bce8 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs @@ -58,7 +58,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new ContentFieldData() .AddValue("iv", JsonValue.Object()); - var actual = FieldConverters.ForValues(ValueConverters.EncodeJson(TestData.DefaultSerializer))(input, jsonField); + var actual = FieldConverters.ForValues(ValueConverters.EncodeJson(TestUtils.DefaultSerializer))(input, jsonField); var expected = new ContentFieldData() diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs index 09d0c4bdc..f1e3a82f6 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ValueConvertersTests.cs @@ -23,7 +23,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Object(); - var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, jsonField); + var result = ValueConverters.EncodeJson(TestUtils.DefaultSerializer)(source, jsonField); Assert.Equal(JsonValue.Create("e30="), result); } @@ -33,7 +33,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Null; - var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, jsonField); + var result = ValueConverters.EncodeJson(TestUtils.DefaultSerializer)(source, jsonField); Assert.Same(source, result); } @@ -43,7 +43,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Create("NO-JSON"); - var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, stringField); + var result = ValueConverters.EncodeJson(TestUtils.DefaultSerializer)(source, stringField); Assert.Same(source, result); } @@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Create("e30="); - var result = ValueConverters.DecodeJson(TestData.DefaultSerializer)(source, jsonField); + var result = ValueConverters.DecodeJson(TestUtils.DefaultSerializer)(source, jsonField); Assert.Equal(JsonValue.Object(), result); } @@ -63,7 +63,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Null; - var result = ValueConverters.DecodeJson(TestData.DefaultSerializer)(source, jsonField); + var result = ValueConverters.DecodeJson(TestUtils.DefaultSerializer)(source, jsonField); Assert.Same(source, result); } @@ -73,7 +73,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = JsonValue.Null; - var result = ValueConverters.EncodeJson(TestData.DefaultSerializer)(source, stringField); + var result = ValueConverters.EncodeJson(TestUtils.DefaultSerializer)(source, stringField); Assert.Same(source, result); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs index 8feb2df02..92ab7b60d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs @@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateEdmSchema { var languagesConfig = LanguagesConfig.Build(Language.DE, Language.EN); - var edmModel = TestData.MixedSchema().BuildEdmType(languagesConfig.ToResolver(), x => x); + var edmModel = TestUtils.MixedSchema().BuildEdmType(languagesConfig.ToResolver(), x => x); Assert.NotNull(edmModel); } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs index 8f873f290..922e4971c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs @@ -16,7 +16,7 @@ namespace Squidex.Domain.Apps.Core.Operations.GenerateJsonSchema { public class JsonSchemaTests { - private readonly Schema schema = TestData.MixedSchema(); + private readonly Schema schema = TestUtils.MixedSchema(); [Fact] public void Should_build_json_schema() diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs index b2b58a49d..06226aa4d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs @@ -38,7 +38,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules A.CallTo(() => user.Claims) .Returns(new List { new Claim(SquidexClaimTypes.DisplayName, "me") }); - sut = new RuleEventFormatter(TestData.DefaultSerializer, urlGenerator); + sut = new RuleEventFormatter(TestUtils.DefaultSerializer, urlGenerator); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs index 35226e184..7a36445b2 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs @@ -79,7 +79,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules A.CallTo(() => ruleTriggerHandler.TriggerType) .Returns(typeof(ContentChangedTrigger)); - sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, TestData.DefaultSerializer, clock, typeNameRegistry); + sut = new RuleService(new[] { ruleTriggerHandler }, new[] { ruleActionHandler }, eventEnricher, TestUtils.DefaultSerializer, clock, typeNameRegistry); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs similarity index 94% rename from tests/Squidex.Domain.Apps.Core.Tests/TestData.cs rename to tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index ca33bbd45..bc22739d1 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -16,17 +16,18 @@ using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.Collections; +using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; using Xunit; namespace Squidex.Domain.Apps.Core { - public static class TestData + public static class TestUtils { public static readonly IJsonSerializer DefaultSerializer = CreateSerializer(); - private static IJsonSerializer CreateSerializer() + public static IJsonSerializer CreateSerializer(TypeNameHandling typeNameHandling = TypeNameHandling.Auto) { var typeNameRegistry = new TypeNameRegistry(); @@ -46,13 +47,15 @@ namespace Squidex.Domain.Apps.Core new NamedGuidIdConverter(), new NamedLongIdConverter(), new NamedStringIdConverter(), + new PropertiesBagConverter(), + new PropertiesBagConverter(), new RefTokenConverter(), new RolesConverter(), new RuleConverter(), new SchemaConverter(), new StringEnumConverter()), - TypeNameHandling = TypeNameHandling.Auto + TypeNameHandling = typeNameHandling }; return new NewtonsoftJsonSerializer(serializerSettings); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppUISettingsGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppUISettingsGrainTests.cs index 1e5a0b3e5..45ae6d1af 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppUISettingsGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppUISettingsGrainTests.cs @@ -8,7 +8,7 @@ using System; using System.Threading.Tasks; using FakeItEasy; -using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.States; using Xunit; @@ -33,13 +33,12 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public async Task Should_set_setting() { - await sut.SetAsync(new JObject(new JProperty("key", 15)).AsJ()); + await sut.SetAsync(JsonValue.Object().Add("key", 15).AsJ()); var actual = await sut.GetAsync(); var expected = - new JObject( - new JProperty("key", 15)); + JsonValue.Object().Add("key", 15); Assert.Equal(expected.ToString(), actual.Value.ToString()); } @@ -47,13 +46,12 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public async Task Should_set_root_value() { - await sut.SetAsync("key", ((JToken)123).AsJ()); + await sut.SetAsync("key", JsonValue.Create(123).AsJ()); var actual = await sut.GetAsync(); var expected = - new JObject( - new JProperty("key", 123)); + JsonValue.Object().Add("key", 123); Assert.Equal(expected.ToString(), actual.Value.ToString()); } @@ -61,12 +59,12 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public async Task Should_remove_root_value() { - await sut.SetAsync("key", ((JToken)123).AsJ()); + await sut.SetAsync("key", JsonValue.Create(123).AsJ()); await sut.RemoveAsync("key"); var actual = await sut.GetAsync(); - var expected = new JObject(); + var expected = JsonValue.Object(); Assert.Equal(expected.ToString(), actual.Value.ToString()); } @@ -74,15 +72,13 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public async Task Should_set_nested_value() { - await sut.SetAsync("root.nested", ((JToken)123).AsJ()); + await sut.SetAsync("root.nested", JsonValue.Create(123).AsJ()); var actual = await sut.GetAsync(); var expected = - new JObject( - new JProperty("root", - new JObject( - new JProperty("nested", 123)))); + JsonValue.Object().Add("root", + JsonValue.Object().Add("nested", 123)); Assert.Equal(expected.ToString(), actual.Value.ToString()); } @@ -90,14 +86,14 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public async Task Should_remove_nested_value() { - await sut.SetAsync("root.nested", ((JToken)123).AsJ()); + await sut.SetAsync("root.nested", JsonValue.Create(123).AsJ()); await sut.RemoveAsync("root.nested"); var actual = await sut.GetAsync(); var expected = - new JObject( - new JProperty("root", new JObject())); + JsonValue.Object().Add("root", + JsonValue.Object()); Assert.Equal(expected.ToString(), actual.Value.ToString()); } @@ -105,9 +101,9 @@ namespace Squidex.Domain.Apps.Entities.Apps [Fact] public async Task Should_throw_exception_if_nested_not_an_object() { - await sut.SetAsync("root.nested", ((JToken)123).AsJ()); + await sut.SetAsync("root.nested", JsonValue.Create(123).AsJ()); - await Assert.ThrowsAsync(() => sut.SetAsync("root.nested.value", ((JToken)123).AsJ())); + await Assert.ThrowsAsync(() => sut.SetAsync("root.nested.value", JsonValue.Create(123).AsJ())); } [Fact] diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs index 9e18c3108..6d64aad03 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs @@ -8,11 +8,12 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading.Tasks; using FakeItEasy; -using FluentAssertions; +using Squidex.Domain.Apps.Core; +using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.States; using Squidex.Infrastructure.Tasks; using Xunit; @@ -22,9 +23,26 @@ namespace Squidex.Domain.Apps.Entities.Backup public class BackupReaderWriterTests { private readonly IStreamNameResolver streamNameResolver = A.Fake(); + private readonly IJsonSerializer serializer = TestUtils.DefaultSerializer; + private readonly IEventDataFormatter formatter; + private readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); + + [TypeName(nameof(MyEvent))] + public sealed class MyEvent : IEvent + { + public Guid GuidRaw { get; set; } + + public NamedId GuidNamed { get; set; } + + public Dictionary Values { get; set; } + } public BackupReaderWriterTests() { + typeNameRegistry.Map(typeof(MyEvent)); + + formatter = new DefaultEventDataFormatter(typeNameRegistry, serializer); + A.CallTo(() => streamNameResolver.WithNewId(A.Ignored, A>.Ignored)) .ReturnsLazily(new Func, string>((stream, idGenerator) => stream + "^2")); } @@ -34,77 +52,112 @@ namespace Squidex.Domain.Apps.Entities.Backup { var stream = new MemoryStream(); - var sourceEvents = new List(); + var random = new Random(); + var randomGuids = new List(); + + for (var i = 0; i < 100; i++) + { + randomGuids.Add(Guid.NewGuid()); + } + + Guid RandomGuid() + { + return randomGuids[random.Next(randomGuids.Count)]; + } + + var sourceEvents = new List<(string Stream, Envelope Event)>(); - using (var writer = new BackupWriter(stream, true)) + for (var i = 0; i < 200; i++) { - for (var i = 0; i < 1000; i++) + var @event = new MyEvent { - var eventData = new EventData { Type = i.ToString(), Metadata = i, Payload = i }; + GuidNamed = new NamedId(RandomGuid(), $"name{i}"), + GuidRaw = RandomGuid(), + Values = new Dictionary + { + [RandomGuid()] = $"name{i}_1", + [RandomGuid()] = $"name{i}_1", + } + }; + + var envelope = Envelope.Create(@event); + + envelope.Headers.Set(RandomGuid().ToString(), i); + envelope.Headers.Set("Id", RandomGuid()); + envelope.Headers.Set("Index", i); + + sourceEvents.Add(($"My-{RandomGuid()}", envelope)); + } + + using (var writer = new BackupWriter(serializer, stream, true)) + { + foreach (var @event in sourceEvents) + { + var eventData = formatter.ToEventData(@event.Event, Guid.NewGuid(), true); var eventStored = new StoredEvent("S", "1", 2, eventData); - if (i % 17 == 0) - { - var localI = i; + var index = @event.Event.Headers["Index"].ToInt32(); - await writer.WriteBlobAsync(eventData.Type, innerStream => + if (index % 17 == 0) + { + await writer.WriteBlobAsync(index.ToString(), innerStream => { - innerStream.WriteByte((byte)localI); + innerStream.WriteByte((byte)index); return TaskHelper.Done; }); } - else if (i % 37 == 0) + else if (index % 37 == 0) { - await writer.WriteJsonAsync(eventData.Type, $"JSON_{i}"); + await writer.WriteJsonAsync(index.ToString(), $"JSON_{index}"); } writer.WriteEvent(eventStored); - - sourceEvents.Add(eventStored); } } stream.Position = 0; - var readEvents = new List(); + var targetEvents = new List<(string Stream, Envelope Event)>(); - using (var reader = new BackupReader(stream)) + using (var reader = new BackupReader(serializer, stream)) { - await reader.ReadEventsAsync(streamNameResolver, async @event => + await reader.ReadEventsAsync(streamNameResolver, formatter, async @event => { - var i = int.Parse(@event.Data.Type); + var index = @event.Event.Headers["Index"].ToInt32(); - if (i % 17 == 0) + if (index % 17 == 0) { - await reader.ReadBlobAsync(@event.Data.Type, innerStream => + await reader.ReadBlobAsync(index.ToString(), innerStream => { - var b = innerStream.ReadByte(); + var byteRead = innerStream.ReadByte(); - Assert.Equal((byte)i, b); + Assert.Equal((byte)index, byteRead); return TaskHelper.Done; }); } - else if (i % 37 == 0) + else if (index % 37 == 0) { - var j = await reader.ReadJsonAttachmentAsync(@event.Data.Type); + var json = await reader.ReadJsonAttachmentAsync(index.ToString()); - Assert.Equal($"JSON_{i}", j.ToString()); + Assert.Equal($"JSON_{index}", json); } - readEvents.Add(@event); + targetEvents.Add(@event); }); - } - var sourceEventsWithNewStreamName = - sourceEvents.Select(x => - new StoredEvent(streamNameResolver.WithNewId(x.StreamName, null), - x.EventPosition, - x.EventStreamNumber, - x.Data)).ToList(); + for (var i = 0; i < targetEvents.Count; i++) + { + var lhs = targetEvents[i].Event.To(); + var rhs = sourceEvents[i].Event.To(); - readEvents.Should().BeEquivalentTo(sourceEventsWithNewStreamName); + Assert.Equal(rhs.Payload.GuidRaw, reader.OldGuid(lhs.Payload.GuidRaw)); + Assert.Equal(rhs.Payload.GuidNamed.Id, reader.OldGuid(lhs.Payload.GuidNamed.Id)); + + Assert.Equal(rhs.Headers["Id"].ToGuid(), reader.OldGuid(lhs.Headers["Id"].ToGuid())); + } + } } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/GuidMapperTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/GuidMapperTests.cs deleted file mode 100644 index fdab2731a..000000000 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/GuidMapperTests.cs +++ /dev/null @@ -1,161 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using Newtonsoft.Json.Linq; -using Xunit; - -namespace Squidex.Domain.Apps.Entities.Backup -{ - public class GuidMapperTests - { - private readonly Guid id1 = Guid.NewGuid(); - private readonly Guid id2 = Guid.NewGuid(); - private readonly GuidMapper map = new GuidMapper(); - - [Fact] - public void Should_map_guid_string_if_valid() - { - var result = map.NewGuidString(id1.ToString()); - - Assert.Equal(map.NewGuid(id1).ToString(), result); - } - - [Fact] - public void Should_return_null_if_mapping_invalid_guid_string() - { - var result = map.NewGuidString("invalid"); - - Assert.Null(result); - } - - [Fact] - public void Should_return_null_if_mapping_null_guid_string() - { - var result = map.NewGuidString(null); - - Assert.Null(result); - } - - [Fact] - public void Should_map_guid() - { - var result = map.NewGuids(id1); - - Assert.Equal(map.NewGuid(id1), result.Value()); - } - - [Fact] - public void Should_return_old_guid() - { - var newGuid = map.NewGuids(id1).Value(); - - Assert.Equal(id1, map.OldGuid(newGuid)); - } - - [Fact] - public void Should_map_guid_string() - { - var result = map.NewGuids(id1.ToString()); - - Assert.Equal(map.NewGuid(id1).ToString(), result.Value()); - } - - [Fact] - public void Should_map_named_id() - { - var result = map.NewGuids($"{id1},name"); - - Assert.Equal($"{map.NewGuid(id1)},name", result.Value()); - } - - [Fact] - public void Should_map_array_with_guid() - { - var obj = - new JObject( - new JProperty("k", - new JArray(id1, id1, id2))); - - map.NewGuids(obj); - - Assert.Equal(map.NewGuid(id1), obj["k"][0].Value()); - Assert.Equal(map.NewGuid(id1), obj["k"][1].Value()); - Assert.Equal(map.NewGuid(id2), obj["k"][2].Value()); - } - - [Fact] - public void Should_map_objects_with_guid_keys() - { - var obj = - new JObject( - new JProperty("k", - new JObject( - new JProperty(id1.ToString(), id1), - new JProperty(id2.ToString(), id2)))); - - map.NewGuids(obj); - - Assert.Equal(map.NewGuid(id1), obj["k"].Value(map.NewGuid(id1).ToString())); - Assert.Equal(map.NewGuid(id2), obj["k"].Value(map.NewGuid(id2).ToString())); - } - - [Fact] - public void Should_map_objects_with_guid() - { - var obj = - new JObject( - new JProperty("k", - new JObject( - new JProperty("v1", id1), - new JProperty("v2", id1), - new JProperty("v3", id2)))); - - map.NewGuids(obj); - - Assert.Equal(map.NewGuid(id1), obj["k"].Value("v1")); - Assert.Equal(map.NewGuid(id1), obj["k"].Value("v2")); - Assert.Equal(map.NewGuid(id2), obj["k"].Value("v3")); - } - - [Fact] - public void Should_map_objects_with_guid_string() - { - var obj = - new JObject( - new JProperty("k", - new JObject( - new JProperty("v1", id1.ToString()), - new JProperty("v2", id1.ToString()), - new JProperty("v3", id2.ToString())))); - - map.NewGuids(obj); - - Assert.Equal(map.NewGuid(id1).ToString(), obj["k"].Value("v1")); - Assert.Equal(map.NewGuid(id1).ToString(), obj["k"].Value("v2")); - Assert.Equal(map.NewGuid(id2).ToString(), obj["k"].Value("v3")); - } - - [Fact] - public void Should_map_objects_with_named_id() - { - var obj = - new JObject( - new JProperty("k", - new JObject( - new JProperty("v1", $"{id1},v1"), - new JProperty("v2", $"{id1},v2"), - new JProperty("v3", $"{id2},v3")))); - - map.NewGuids(obj); - - Assert.Equal($"{map.NewGuid(id1).ToString()},v1", obj["k"].Value("v1")); - Assert.Equal($"{map.NewGuid(id1).ToString()},v2", obj["k"].Value("v2")); - Assert.Equal($"{map.NewGuid(id2).ToString()},v3", obj["k"].Value("v3")); - } - } -} diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs index ffa580607..56bddfe27 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs @@ -41,10 +41,10 @@ namespace Squidex.Domain.Apps.Entities.Contents new NamedContentData() .AddField("my-field1", new ContentFieldData() - .AddValue(null)) + .AddValue("iv", null)) .AddField("my-field2", new ContentFieldData() - .AddValue(1)); + .AddValue("iv", 1)); private readonly NamedContentData data = new NamedContentData() .AddField("my-field1", diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs index f2a90e843..ff0a07365 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs @@ -8,7 +8,6 @@ using System; using System.Threading.Tasks; using FakeItEasy; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.Contents; using Squidex.Infrastructure; using Xunit; @@ -77,9 +76,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { id = asset.Id, version = 1, - created = asset.Created.ToDateTimeUtc(), + created = asset.Created, createdBy = "subject:user1", - lastModified = asset.LastModified.ToDateTimeUtc(), + lastModified = asset.LastModified, lastModifiedBy = "subject:user2", url = $"assets/{asset.Id}", thumbnailUrl = $"assets/{asset.Id}?width=100", @@ -147,9 +146,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { id = asset.Id, version = 1, - created = asset.Created.ToDateTimeUtc(), + created = asset.Created, createdBy = "subject:user1", - lastModified = asset.LastModified.ToDateTimeUtc(), + lastModified = asset.LastModified, lastModifiedBy = "subject:user2", url = $"assets/{asset.Id}", thumbnailUrl = $"assets/{asset.Id}?width=100", @@ -211,9 +210,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { id = asset.Id, version = 1, - created = asset.Created.ToDateTimeUtc(), + created = asset.Created, createdBy = "subject:user1", - lastModified = asset.LastModified.ToDateTimeUtc(), + lastModified = asset.LastModified, lastModifiedBy = "subject:user2", url = $"assets/{asset.Id}", thumbnailUrl = $"assets/{asset.Id}?width=100", @@ -298,9 +297,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { id = content.Id, version = 1, - created = content.Created.ToDateTimeUtc(), + created = content.Created, createdBy = "subject:user1", - lastModified = content.LastModified.ToDateTimeUtc(), + lastModified = content.LastModified, lastModifiedBy = "subject:user2", status = "DRAFT", url = $"contents/my-schema/{content.Id}", @@ -320,7 +319,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL }, myDatetime = new { - iv = content.LastModified.ToDateTimeUtc() + iv = content.LastModified }, myJson = new { @@ -440,9 +439,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { id = content.Id, version = 1, - created = content.Created.ToDateTimeUtc(), + created = content.Created, createdBy = "subject:user1", - lastModified = content.LastModified.ToDateTimeUtc(), + lastModified = content.LastModified, lastModifiedBy = "subject:user2", status = "DRAFT", url = $"contents/my-schema/{content.Id}", @@ -462,7 +461,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL }, myDatetime = new { - iv = content.LastModified.ToDateTimeUtc() + iv = content.LastModified }, myJson = new { @@ -560,9 +559,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL { id = content.Id, version = 1, - created = content.Created.ToDateTimeUtc(), + created = content.Created, createdBy = "subject:user1", - lastModified = content.LastModified.ToDateTimeUtc(), + lastModified = content.LastModified, lastModifiedBy = "subject:user2", status = "DRAFT", url = $"contents/my-schema/{content.Id}", @@ -582,7 +581,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL }, myDatetime = new { - iv = content.LastModified.ToDateTimeUtc() + iv = content.LastModified }, myJson = new { @@ -819,9 +818,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var result = await sut.QueryAsync(context, new GraphQLQuery { Query = query }); - var json = JToken.FromObject(result); + var json = serializer.Serialize(result); - Assert.Null(json["data"]); + Assert.Contains("\"data\":null", json); } private QueryContext MatchsAssetContext() diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs index d46676a0e..6988c899d 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs @@ -12,7 +12,6 @@ using FakeItEasy; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using NodaTime.Extensions; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Apps; @@ -23,6 +22,8 @@ using Squidex.Domain.Apps.Entities.Assets; using Squidex.Domain.Apps.Entities.Contents.TestData; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; +using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; using Xunit; #pragma warning disable SA1311 // Static readonly fields must begin with upper-case letter @@ -39,6 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL protected readonly IContentQueryService contentQuery = A.Fake(); protected readonly IAssetQueryService assetQuery = A.Fake(); protected readonly ISchemaEntity schema = A.Fake(); + protected readonly IJsonSerializer serializer = TestUtils.CreateSerializer(TypeNameHandling.None); protected readonly IMemoryCache cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); protected readonly IAppProvider appProvider = A.Fake(); protected readonly IAppEntity app = A.Dummy(); @@ -106,40 +108,40 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL .AddValue("de", "value")) .AddField("my-assets", new ContentFieldData() - .AddValue("iv", JToken.FromObject(new[] { assetId }))) + .AddValue("iv", JsonValue.Array(assetId.ToString()))) .AddField("my-number", new ContentFieldData() - .AddValue("iv", 1)) + .AddValue("iv", 1.0)) .AddField("my-boolean", new ContentFieldData() .AddValue("iv", true)) .AddField("my-datetime", new ContentFieldData() - .AddValue("iv", now.ToDateTimeUtc())) + .AddValue("iv", now)) .AddField("my-tags", new ContentFieldData() - .AddValue("iv", JToken.FromObject(new[] { "tag1", "tag2" }))) + .AddValue("iv", JsonValue.Array("tag1", "tag2"))) .AddField("my-references", new ContentFieldData() - .AddValue("iv", JToken.FromObject(new[] { refId }))) + .AddValue("iv", JsonValue.Array(refId.ToString()))) .AddField("my-geolocation", new ContentFieldData() - .AddValue("iv", JToken.FromObject(new { latitude = 10, longitude = 20 }))) + .AddValue("iv", JsonValue.Object().Add("latitude", 10).Add("longitude", 20))) .AddField("my-json", new ContentFieldData() - .AddValue("iv", JToken.FromObject(new { value = 1 }))) + .AddValue("iv", JsonValue.Object().Add("value", 1))) .AddField("my-localized", new ContentFieldData() .AddValue("de-DE", "de-DE")) .AddField("my-array", new ContentFieldData() - .AddValue("iv", new JArray( - new JObject( - new JProperty("nested-boolean", true), - new JProperty("nested-number", 1)), - new JObject( - new JProperty("nested-boolean", false), - new JProperty("nested-number", 2))))); + .AddValue("iv", JsonValue.Array( + JsonValue.Object() + .Add("nested-boolean", true) + .Add("nested-number", 1), + JsonValue.Object() + .Add("nested-boolean", false) + .Add("nested-number", 2)))); var content = new ContentEntity { @@ -179,22 +181,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL return asset; } - protected static void AssertResult(object expected, (bool HasErrors, object Response) result, bool checkErrors = true) + protected void AssertResult(object expected, (bool HasErrors, object Response) result, bool checkErrors = true) { if (checkErrors && result.HasErrors) { throw new InvalidOperationException(Serialize(result)); } - var resultJson = JsonConvert.SerializeObject(result.Response, Formatting.Indented); - var expectJson = JsonConvert.SerializeObject(expected, Formatting.Indented); + var resultJson = serializer.Serialize(result.Response, true); + var expectJson = serializer.Serialize(expected, true); Assert.Equal(expectJson, resultJson); } - private static string Serialize((bool HasErrors, object Response) result) + private string Serialize((bool HasErrors, object Response) result) { - return JsonConvert.SerializeObject(result); + return serializer.Serialize(result); } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleDequeuerTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleDequeuerTests.cs index 1705ca24d..68a3a2eb8 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleDequeuerTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleDequeuerTests.cs @@ -8,7 +8,6 @@ using System; using System.Threading.Tasks; using FakeItEasy; -using Newtonsoft.Json.Linq; using NodaTime; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; @@ -49,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Rules [InlineData(4, 0, RuleResult.Failed, RuleJobResult.Failed)] public async Task Should_set_next_attempt_based_on_num_calls(int calls, int minutes, RuleResult result, RuleJobResult jobResult) { - var actionData = new JObject(); + var actionData = "{}"; var actionName = "MyAction"; var @event = CreateEvent(calls, actionName, actionData); @@ -73,7 +72,7 @@ namespace Squidex.Domain.Apps.Entities.Rules .MustHaveHappened(); } - private IRuleEventEntity CreateEvent(int numCalls, string actionName, JObject actionData) + private IRuleEventEntity CreateEvent(int numCalls, string actionName, string actionData) { var @event = A.Fake(); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj b/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj index d88751b1e..79ec34354 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj @@ -18,6 +18,7 @@ + diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs index 7ad64cdb2..bec3549d1 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Globalization; using NodaTime; using Xunit; @@ -15,7 +14,6 @@ namespace Squidex.Infrastructure.EventSourcing public class EnvelopeExtensionsTests { private readonly Envelope sut = new Envelope(string.Empty); - private readonly CultureInfo culture = CultureInfo.InvariantCulture; [Fact] public void Should_set_and_get_timestamp() @@ -25,7 +23,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetTimestamp(timestamp); Assert.Equal(timestamp, sut.Headers.Timestamp()); - Assert.Equal(timestamp, sut.Headers["Timestamp"].ToInstant(culture)); + Assert.Equal(timestamp, sut.Headers["Timestamp"].ToInstant()); } [Fact] @@ -36,7 +34,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetCommitId(commitId); Assert.Equal(commitId, sut.Headers.CommitId()); - Assert.Equal(commitId, sut.Headers["CommitId"].ToGuid(culture)); + Assert.Equal(commitId, sut.Headers["CommitId"].ToGuid()); } [Fact] @@ -47,7 +45,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetEventId(commitId); Assert.Equal(commitId, sut.Headers.EventId()); - Assert.Equal(commitId, sut.Headers["EventId"].ToGuid(culture)); + Assert.Equal(commitId, sut.Headers["EventId"].ToGuid()); } [Fact] @@ -58,7 +56,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetAggregateId(commitId); Assert.Equal(commitId, sut.Headers.AggregateId()); - Assert.Equal(commitId, sut.Headers["AggregateId"].ToGuid(culture)); + Assert.Equal(commitId, sut.Headers["AggregateId"].ToGuid()); } [Fact] @@ -80,7 +78,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetEventStreamNumber(eventStreamNumber); Assert.Equal(eventStreamNumber, sut.Headers.EventStreamNumber()); - Assert.Equal(eventStreamNumber, sut.Headers["EventStreamNumber"].ToInt64(culture)); + Assert.Equal(eventStreamNumber, sut.Headers["EventStreamNumber"].ToInt64()); } } } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs index da62e3e23..7f5bd174c 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs @@ -79,7 +79,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains A.CallTo(() => persistence.WriteSnapshotAsync(A.Ignored)) .Invokes(new Action(s => state = s)); - A.CallTo(() => formatter.Parse(eventData, true)).Returns(envelope); + A.CallTo(() => formatter.Parse(eventData, true, null)).Returns(envelope); sut = new MyEventConsumerGrain( x => eventConsumer, @@ -192,7 +192,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains [Fact] public async Task Should_ignore_old_events() { - A.CallTo(() => formatter.Parse(eventData, true)) + A.CallTo(() => formatter.Parse(eventData, true, null)) .Throws(new TypeNameNotFoundException()); var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData); @@ -326,7 +326,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains { var ex = new InvalidOperationException(); - A.CallTo(() => formatter.Parse(eventData, true)) + A.CallTo(() => formatter.Parse(eventData, true, null)) .Throws(ex); var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData); diff --git a/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs b/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs index defe9c236..e60eec701 100644 --- a/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs +++ b/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs @@ -1,12 +1,11 @@ // ========================================================================== // Squidex Headless CMS // ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) +// Copyright () Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; -using System.Globalization; using System.Linq; using Microsoft.CSharp.RuntimeBinder; using NodaTime; @@ -17,7 +16,6 @@ namespace Squidex.Infrastructure { public class PropertiesBagTests { - private readonly CultureInfo c = CultureInfo.InvariantCulture; private readonly PropertiesBag bag = new PropertiesBag(); private readonly dynamic dynamicBag; @@ -52,7 +50,7 @@ namespace Squidex.Infrastructure Assert.Equal(kvp.Value.RawValue, bag[kvp.Key].RawValue); } - Assert.Equal(bag["Key5"].ToGuid(c), output["Key5"].ToGuid(c)); + Assert.Equal(bag["Key5"].ToGuid(), output["Key5"].ToGuid()); } [Fact] @@ -84,7 +82,7 @@ namespace Squidex.Infrastructure Assert.True(bag.Contains("NewKey")); Assert.Equal(1, bag.Count); - Assert.Equal(123, bag["NewKey"].ToInt64(c)); + Assert.Equal(123, bag["NewKey"].ToInt64()); Assert.False(bag.Contains("OldKey")); } @@ -172,7 +170,7 @@ namespace Squidex.Infrastructure { bag.Set("Key", "abc"); - Assert.Throws(() => bag["Key"].ToInt64(CultureInfo.InvariantCulture)); + Assert.Throws(() => bag["Key"].ToInt64()); } [Fact] @@ -212,7 +210,7 @@ namespace Squidex.Infrastructure { bag.Set("Key", long.MaxValue); - Assert.Throws(() => bag["Key"].ToInt32(c)); + Assert.Throws(() => bag["Key"].ToInt32()); } [Fact] @@ -236,7 +234,7 @@ namespace Squidex.Infrastructure { bag.Set("Key", double.MaxValue); - Assert.Equal(float.PositiveInfinity, bag["Key"].ToSingle(c)); + Assert.Equal(float.PositiveInfinity, bag["Key"].ToSingle()); } [Fact] @@ -340,7 +338,7 @@ namespace Squidex.Infrastructure { bag.Set("Key", SystemClock.Instance.GetCurrentInstant()); - Assert.Throws(() => bag["Key"].ToGuid(CultureInfo.InvariantCulture)); + Assert.Throws(() => bag["Key"].ToGuid()); } private void AssertNumber() @@ -366,8 +364,8 @@ namespace Squidex.Infrastructure private void AssertBoolean(bool expected) { - Assert.Equal(expected, bag["Key"].ToBoolean(c)); - Assert.Equal(expected, bag["Key"].ToNullableBoolean(c)); + Assert.Equal(expected, bag["Key"].ToBoolean()); + Assert.Equal(expected, bag["Key"].ToNullableBoolean()); Assert.Equal(expected, (bool)dynamicBag.Key); Assert.Equal(expected, (bool?)dynamicBag.Key); @@ -375,8 +373,8 @@ namespace Squidex.Infrastructure private void AssertInstant(Instant expected) { - Assert.Equal(expected, bag["Key"].ToInstant(c)); - Assert.Equal(expected, bag["Key"].ToNullableInstant(c).Value); + Assert.Equal(expected, bag["Key"].ToInstant()); + Assert.Equal(expected, bag["Key"].ToNullableInstant().Value); Assert.Equal(expected, (Instant)dynamicBag.Key); Assert.Equal(expected, (Instant?)dynamicBag.Key); @@ -384,8 +382,8 @@ namespace Squidex.Infrastructure private void AssertGuid(Guid expected) { - Assert.Equal(expected, bag["Key"].ToGuid(c)); - Assert.Equal(expected, bag["Key"].ToNullableGuid(c)); + Assert.Equal(expected, bag["Key"].ToGuid()); + Assert.Equal(expected, bag["Key"].ToNullableGuid()); Assert.Equal(expected, (Guid)dynamicBag.Key); Assert.Equal(expected, (Guid?)dynamicBag.Key); @@ -393,8 +391,8 @@ namespace Squidex.Infrastructure private void AssertDouble(double expected) { - Assert.Equal(expected, bag["Key"].ToDouble(c)); - Assert.Equal(expected, bag["Key"].ToNullableDouble(c)); + Assert.Equal(expected, bag["Key"].ToDouble()); + Assert.Equal(expected, bag["Key"].ToNullableDouble()); Assert.Equal(expected, (double)dynamicBag.Key); Assert.Equal(expected, (double?)dynamicBag.Key); @@ -402,8 +400,8 @@ namespace Squidex.Infrastructure private void AssertSingle(float expected) { - Assert.Equal(expected, bag["Key"].ToSingle(c)); - Assert.Equal(expected, bag["Key"].ToNullableSingle(c)); + Assert.Equal(expected, bag["Key"].ToSingle()); + Assert.Equal(expected, bag["Key"].ToNullableSingle()); Assert.Equal(expected, (float)dynamicBag.Key); Assert.Equal(expected, (float?)dynamicBag.Key); @@ -411,8 +409,8 @@ namespace Squidex.Infrastructure private void AssertInt32(long expected) { - Assert.Equal(expected, bag["Key"].ToInt64(c)); - Assert.Equal(expected, bag["Key"].ToNullableInt64(c)); + Assert.Equal(expected, bag["Key"].ToInt64()); + Assert.Equal(expected, bag["Key"].ToNullableInt64()); Assert.Equal(expected, (long)dynamicBag.Key); Assert.Equal(expected, (long?)dynamicBag.Key); @@ -420,8 +418,8 @@ namespace Squidex.Infrastructure private void AssertInt64(int expected) { - Assert.Equal(expected, bag["Key"].ToInt64(c)); - Assert.Equal(expected, bag["Key"].ToNullableInt64(c)); + Assert.Equal(expected, bag["Key"].ToInt64()); + Assert.Equal(expected, bag["Key"].ToNullableInt64()); Assert.Equal(expected, (int)dynamicBag.Key); Assert.Equal(expected, (int?)dynamicBag.Key); diff --git a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs index 5da0ea0c2..e7223fca2 100644 --- a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs +++ b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs @@ -61,7 +61,7 @@ namespace Squidex.Infrastructure.States A.CallTo(() => eventStore.QueryAsync(key, 0)) .Returns(new List { storedEvent }); - A.CallTo(() => eventDataFormatter.Parse(storedEvent.Data, true)) + A.CallTo(() => eventDataFormatter.Parse(storedEvent.Data, true, null)) .Throws(new TypeNameNotFoundException()); var persistedEvents = new List(); @@ -256,7 +256,7 @@ namespace Squidex.Infrastructure.States eventsStored.Add(eventStored); - A.CallTo(() => eventDataFormatter.Parse(eventData, true)) + A.CallTo(() => eventDataFormatter.Parse(eventData, true, null)) .Returns(new Envelope(@event)); i++; diff --git a/tools/Migrate_01/Rebuilder.cs b/tools/Migrate_01/Rebuilder.cs index be45577c0..6214e37b4 100644 --- a/tools/Migrate_01/Rebuilder.cs +++ b/tools/Migrate_01/Rebuilder.cs @@ -25,6 +25,7 @@ using Squidex.Infrastructure; using Squidex.Infrastructure.Caching; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.States; namespace Migrate_01 @@ -33,18 +34,21 @@ namespace Migrate_01 { private readonly FieldRegistry fieldRegistry; private readonly ILocalCache localCache; + private readonly IJsonSerializer serializer; private readonly IStore store; private readonly IEventStore eventStore; public Rebuilder( FieldRegistry fieldRegistry, ILocalCache localCache, + IJsonSerializer serializer, IStore store, IEventStore eventStore) { this.fieldRegistry = fieldRegistry; this.eventStore = eventStore; this.localCache = localCache; + this.serializer = serializer; this.store = store; } @@ -104,7 +108,9 @@ namespace Migrate_01 await eventStore.QueryAsync(async storedEvent => { - var id = Guid.Parse(storedEvent.Data.Metadata.Value(CommonHeaders.AggregateId)); + var headers = serializer.Deserialize(storedEvent.Data.Metadata); + + var id = headers.AggregateId(); if (handledIds.Add(id)) { From 30a8025389fcb8bcb7164562f383a02756a6b89a Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 26 Nov 2018 16:11:20 +0100 Subject: [PATCH 12/33] Build errors fixed. --- .../Commands/DomainObjectGrainBase.cs | 2 +- .../Models/Fields/BooleanFieldPropertiesDto.cs | 3 --- .../Models/Fields/DateTimeFieldPropertiesDto.cs | 4 ---- .../Models/Fields/GeolocationFieldPropertiesDto.cs | 3 --- .../Models/Fields/NumberFieldPropertiesDto.cs | 3 --- .../Models/Fields/StringFieldPropertiesDto.cs | 3 --- .../Models/Fields/TagsFieldPropertiesDto.cs | 3 --- .../Areas/Api/Controllers/UI/UIController.cs | 3 ++- .../Pipeline/Diagnostics/HealthCheckMiddleware.cs | 14 ++++++++------ 9 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/Squidex.Infrastructure/Commands/DomainObjectGrainBase.cs b/src/Squidex.Infrastructure/Commands/DomainObjectGrainBase.cs index 1f6044d3d..548a82c33 100644 --- a/src/Squidex.Infrastructure/Commands/DomainObjectGrainBase.cs +++ b/src/Squidex.Infrastructure/Commands/DomainObjectGrainBase.cs @@ -221,7 +221,7 @@ namespace Squidex.Infrastructure.Commands { var result = await ExecuteAsync(command.Value); - return result.AsJ(); + return result; } protected abstract Task ExecuteAsync(IAggregateCommand command); diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/BooleanFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/BooleanFieldPropertiesDto.cs index 45964540e..7b92fccdb 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/BooleanFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/BooleanFieldPropertiesDto.cs @@ -5,8 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Reflection; @@ -29,7 +27,6 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// /// The editor that is used to manage this field. /// - [JsonConverter(typeof(StringEnumConverter))] public BooleanFieldEditor Editor { get; set; } public override FieldProperties ToProperties() diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/DateTimeFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/DateTimeFieldPropertiesDto.cs index f5f7ba515..0340f7313 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/DateTimeFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/DateTimeFieldPropertiesDto.cs @@ -5,8 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using NodaTime; using Squidex.Domain.Apps.Core.Schemas; @@ -35,13 +33,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// /// The editor that is used to manage this field. /// - [JsonConverter(typeof(StringEnumConverter))] public DateTimeFieldEditor Editor { get; set; } /// /// The calculated default value for the field value. /// - [JsonConverter(typeof(StringEnumConverter))] public DateTimeCalculatedDefaultValue? CalculatedDefaultValue { get; set; } public override FieldProperties ToProperties() diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/GeolocationFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/GeolocationFieldPropertiesDto.cs index 898b2df3e..4ba929093 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/GeolocationFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/GeolocationFieldPropertiesDto.cs @@ -5,8 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Reflection; @@ -24,7 +22,6 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// /// The editor that is used to manage this field. /// - [JsonConverter(typeof(StringEnumConverter))] public GeolocationFieldEditor Editor { get; set; } public override FieldProperties ToProperties() diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs index 4a7861b04..9e3670ff0 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs @@ -5,8 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Collections; @@ -45,7 +43,6 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// /// The editor that is used to manage this field. /// - [JsonConverter(typeof(StringEnumConverter))] public NumberFieldEditor Editor { get; set; } public override FieldProperties ToProperties() diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs index 0722fec99..483f93bc8 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs @@ -5,8 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Collections; @@ -55,7 +53,6 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// /// The editor that is used to manage this field. /// - [JsonConverter(typeof(StringEnumConverter))] public StringFieldEditor Editor { get; set; } public override FieldProperties ToProperties() diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs index 3a7727107..777103f7c 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs @@ -5,8 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using NJsonSchema.Annotations; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Infrastructure.Collections; @@ -35,7 +33,6 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// /// The editor that is used to manage this field. /// - [JsonConverter(typeof(StringEnumConverter))] public TagsFieldEditor Editor { get; set; } public override FieldProperties ToProperties() diff --git a/src/Squidex/Areas/Api/Controllers/UI/UIController.cs b/src/Squidex/Areas/Api/Controllers/UI/UIController.cs index d5c486d93..6d34ef4c3 100644 --- a/src/Squidex/Areas/Api/Controllers/UI/UIController.cs +++ b/src/Squidex/Areas/Api/Controllers/UI/UIController.cs @@ -14,6 +14,7 @@ using Squidex.Config; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Extensions.Actions.Twitter; using Squidex.Infrastructure.Commands; +using Squidex.Infrastructure.Orleans; using Squidex.Pipeline; namespace Squidex.Areas.Api.Controllers.UI @@ -78,7 +79,7 @@ namespace Squidex.Areas.Api.Controllers.UI [ApiPermission] public async Task PutSetting(string app, string key, [FromBody] UpdateSettingDto request) { - await grainFactory.GetGrain(AppId).SetAsync(key, request.Value); + await grainFactory.GetGrain(AppId).SetAsync(key, request.Value.AsJ()); return NoContent(); } diff --git a/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs b/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs index 2025dbbfb..00725377d 100644 --- a/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs +++ b/src/Squidex/Pipeline/Diagnostics/HealthCheckMiddleware.cs @@ -11,9 +11,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Newtonsoft.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.Diagnostics; +using Squidex.Infrastructure.Json; namespace Squidex.Pipeline.Diagnostics { @@ -23,19 +23,19 @@ namespace Squidex.Pipeline.Diagnostics private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(2); private readonly Dictionary healthChecks; - private readonly JsonSerializerSettings serializerSettings; + private readonly IJsonSerializer serializer; private readonly RequestDelegate next; private readonly List scopes; - public HealthCheckMiddleware(IEnumerable healthChecks, JsonSerializerSettings serializerSettings, RequestDelegate next, string scopes) + public HealthCheckMiddleware(IEnumerable healthChecks, IJsonSerializer serializer, RequestDelegate next, string scopes) { Guard.NotNull(healthChecks, nameof(healthChecks)); - Guard.NotNull(serializerSettings, nameof(serializerSettings)); + Guard.NotNull(serializer, nameof(serializer)); this.healthChecks = healthChecks.ToDictionary(GetName); this.next = next; + this.serializer = serializer; this.scopes = SplitScopes(scopes); - this.serializerSettings = serializerSettings; } public async Task Invoke(HttpContext context) @@ -58,7 +58,9 @@ namespace Squidex.Pipeline.Diagnostics var response = results.ToDictionary(x => x.Name, x => x.Result); - await context.Response.WriteAsync(JsonConvert.SerializeObject(new { status = response }, Formatting.Indented, serializerSettings)); + var json = serializer.Serialize(new { status = response }); + + await context.Response.WriteAsync(json); } } else From e35da8de8b05c7de70c0e6871854899b9e9ea366 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 26 Nov 2018 17:53:03 +0100 Subject: [PATCH 13/33] Fix registration. --- src/Squidex/Config/Domain/SerializationServices.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 10596cbbe..2f68fccc3 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -20,6 +20,7 @@ using Squidex.Domain.Apps.Events; using Squidex.Extensions.Actions; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; namespace Squidex.Config.Domain @@ -87,7 +88,7 @@ namespace Squidex.Config.Domain services.AddSingleton(DefaultJsonSerializer); services.AddSingleton(TypeNameRegistry); - services.AddSingleton(new NewtonsoftJsonSerializer(DefaultJsonSettings)); + services.AddSingleton(new NewtonsoftJsonSerializer(DefaultJsonSettings)); return services; } From 5378880556170a631b52c79e14f326ddc3f629c4 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 26 Nov 2018 19:47:25 +0100 Subject: [PATCH 14/33] Removed properties bag. --- .../HandleRules/RuleService.cs | 2 +- .../Backup/BackupReader.cs | 42 +- .../SquidexHeaderExtensions.cs | 4 +- .../EventSourcing/Formatter.cs | 21 +- .../EventSourcing/GetEventStore.cs | 14 +- .../GetEventStoreSubscription.cs | 9 +- .../EventSourcing/MongoEvent.cs | 9 +- .../MongoDb/BsonJsonConverter.cs | 155 ------- .../DefaultEventDataFormatter.cs | 20 +- .../EventSourcing/EnvelopeExtensions.cs | 46 +- .../EventSourcing/EnvelopeHeaders.cs | 25 +- .../EventSourcing/EventData.cs | 19 +- .../Json/Newtonsoft/PropertiesBagConverter.cs | 78 ---- .../Json/Objects/JsonObject.cs | 16 +- src/Squidex.Infrastructure/PropertiesBag.cs | 112 ----- src/Squidex.Infrastructure/PropertyValue.cs | 235 ---------- .../Config/Domain/EventStoreServices.cs | 3 +- .../Config/Domain/SerializationServices.cs | 2 - .../TestUtils.cs | 2 - .../Backup/BackupReaderWriterTests.cs | 12 +- .../DefaultEventDataFormatterTests.cs | 4 +- .../EventSourcing/EnvelopeExtensionsTests.cs | 10 +- .../EventSourcing/EnvelopeHeaderTests.cs | 19 +- .../Grains/EventConsumerGrainTests.cs | 2 +- .../EventSourcing/RetrySubscriptionTests.cs | 4 +- .../MongoDb/BsonConverterTests.cs | 38 -- .../PropertiesBagTests.cs | 428 ------------------ .../States/PersistenceEventSourcingTests.cs | 4 +- .../TestHelpers/JsonHelper.cs | 2 - tools/Migrate_01/Rebuilder.cs | 2 +- 30 files changed, 182 insertions(+), 1157 deletions(-) delete mode 100644 src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs delete mode 100644 src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs delete mode 100644 src/Squidex.Infrastructure/PropertiesBag.cs delete mode 100644 src/Squidex.Infrastructure/PropertyValue.cs delete mode 100644 tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs index 8a5dbac53..d6f4fa5a3 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleService.cs @@ -93,7 +93,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules var now = clock.GetCurrentInstant(); var eventTime = - @event.Headers.Contains(CommonHeaders.Timestamp) ? + @event.Headers.ContainsKey(CommonHeaders.Timestamp) ? @event.Headers.Timestamp() : now; diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs index b6cce2231..2c3560334 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs @@ -9,12 +9,16 @@ using System; using System.IO; using System.IO.Compression; using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Entities.Backup.Helpers; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.States; +#pragma warning disable SA1401 // Fields must be private + namespace Squidex.Domain.Apps.Entities.Backup { public sealed class BackupReader : DisposableObjectBase @@ -25,6 +29,36 @@ namespace Squidex.Domain.Apps.Entities.Backup private int readEvents; private int readAttachments; + private sealed class ComaptibleStoredEvent + { + [JsonProperty] + public string StreamName; + + [JsonProperty] + public string EventPosition; + + [JsonProperty] + public long EventStreamNumber; + + [JsonProperty] + public CompatibleEventData Data; + } + + private sealed class CompatibleEventData + { + [JsonProperty] + public string Type; + + [JsonProperty] + public JRaw Payload; + + [JsonProperty] + public EnvelopeHeaders Headers; + + [JsonProperty] + public EnvelopeHeaders Metadata; + } + public int ReadEvents { get { return readEvents; } @@ -117,10 +151,14 @@ namespace Squidex.Domain.Apps.Entities.Backup using (var stream = eventEntry.Open()) { - var storedEvent = serializer.Deserialize(stream); + var storedEvent = serializer.Deserialize(stream); + + var src = storedEvent.Data; + + var data = new EventData(src.Type, src.Headers ?? src.Metadata, src.Payload.ToString()); var eventStream = streamNameResolver.WithNewId(storedEvent.StreamName, guidMapper.NewGuidOrNull); - var eventEnvelope = formatter.Parse(storedEvent.Data, true, guidMapper.NewGuidOrValue); + var eventEnvelope = formatter.Parse(data, true, guidMapper.NewGuidOrValue); await handler((eventStream, eventEnvelope)); } diff --git a/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs b/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs index 007b19de8..d65fcd3ff 100644 --- a/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs +++ b/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs @@ -14,12 +14,12 @@ namespace Squidex.Domain.Apps.Events { public static Guid AppId(this EnvelopeHeaders headers) { - return headers[SquidexHeaders.AppId].ToGuid(); + return headers.GetGuid(SquidexHeaders.AppId); } public static Envelope SetAppId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Set(SquidexHeaders.AppId, value); + envelope.Headers.Add(SquidexHeaders.AppId, value); return envelope; } diff --git a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs index 6fdfaa288..8a2dd111f 100644 --- a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs +++ b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/Formatter.cs @@ -8,20 +8,23 @@ using System; using System.Text; using EventStore.ClientAPI; +using Squidex.Infrastructure.Json; using EventStoreData = EventStore.ClientAPI.EventData; namespace Squidex.Infrastructure.EventSourcing { public static class Formatter { - public static StoredEvent Read(ResolvedEvent resolvedEvent) + public static StoredEvent Read(ResolvedEvent resolvedEvent, IJsonSerializer serializer) { var @event = resolvedEvent.Event; - var body = Encoding.UTF8.GetString(@event.Data); - var meta = Encoding.UTF8.GetString(@event.Metadata); + var metadata = Encoding.UTF8.GetString(@event.Data); - var eventData = new EventData { Type = @event.EventType, Payload = body, Metadata = meta }; + var headersJson = Encoding.UTF8.GetString(@event.Metadata); + var headers = serializer.Deserialize(headersJson); + + var eventData = new EventData(@event.EventType, headers, metadata); return new StoredEvent( @event.EventStreamId, @@ -30,12 +33,14 @@ namespace Squidex.Infrastructure.EventSourcing eventData); } - public static EventStoreData Write(EventData eventData) + public static EventStoreData Write(EventData eventData, IJsonSerializer serializer) { - var body = Encoding.UTF8.GetBytes(eventData.Payload); - var meta = Encoding.UTF8.GetBytes(eventData.Metadata); + var payload = Encoding.UTF8.GetBytes(eventData.Payload); + + var headersJson = serializer.Serialize(eventData.Headers); + var headersBytes = Encoding.UTF8.GetBytes(headersJson); - return new EventStoreData(Guid.NewGuid(), eventData.Type, true, body, meta); + return new EventStoreData(Guid.NewGuid(), eventData.Type, true, payload, headersBytes); } } } diff --git a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStore.cs b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStore.cs index 9ea5bc45c..68ceef876 100644 --- a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStore.cs +++ b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStore.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using EventStore.ClientAPI; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Log; namespace Squidex.Infrastructure.EventSourcing @@ -20,14 +21,17 @@ namespace Squidex.Infrastructure.EventSourcing private const int WritePageSize = 500; private const int ReadPageSize = 500; private readonly IEventStoreConnection connection; + private readonly IJsonSerializer serializer; private readonly string prefix; private readonly ProjectionClient projectionClient; - public GetEventStore(IEventStoreConnection connection, string prefix, string projectionHost) + public GetEventStore(IEventStoreConnection connection, IJsonSerializer serializer, string prefix, string projectionHost) { Guard.NotNull(connection, nameof(connection)); + Guard.NotNull(serializer, nameof(serializer)); this.connection = connection; + this.serializer = serializer; this.prefix = prefix?.Trim(' ', '-').WithFallback("squidex"); @@ -50,7 +54,7 @@ namespace Squidex.Infrastructure.EventSourcing public IEventSubscription CreateSubscription(IEventSubscriber subscriber, string streamFilter, string position = null) { - return new GetEventStoreSubscription(connection, subscriber, projectionClient, position, streamFilter); + return new GetEventStoreSubscription(connection, subscriber, serializer, projectionClient, position, streamFilter); } public Task CreateIndexAsync(string property) @@ -95,7 +99,7 @@ namespace Squidex.Infrastructure.EventSourcing foreach (var resolved in currentSlice.Events) { - var storedEvent = Formatter.Read(resolved); + var storedEvent = Formatter.Read(resolved, serializer); await callback(storedEvent); } @@ -123,7 +127,7 @@ namespace Squidex.Infrastructure.EventSourcing foreach (var resolved in currentSlice.Events) { - var storedEvent = Formatter.Read(resolved); + var storedEvent = Formatter.Read(resolved, serializer); result.Add(storedEvent); } @@ -164,7 +168,7 @@ namespace Squidex.Infrastructure.EventSourcing return; } - var eventsToSave = events.Select(Formatter.Write).ToList(); + var eventsToSave = events.Select(x => Formatter.Write(x, serializer)).ToList(); if (eventsToSave.Count < WritePageSize) { diff --git a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs index e77d4a204..a1d3faf01 100644 --- a/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs +++ b/src/Squidex.Infrastructure.GetEventStore/EventSourcing/GetEventStoreSubscription.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using EventStore.ClientAPI; using EventStore.ClientAPI.Exceptions; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Tasks; namespace Squidex.Infrastructure.EventSourcing @@ -16,12 +17,14 @@ namespace Squidex.Infrastructure.EventSourcing { private readonly IEventStoreConnection connection; private readonly IEventSubscriber subscriber; + private readonly IJsonSerializer serializer; private readonly EventStoreCatchUpSubscription subscription; private readonly long? position; public GetEventStoreSubscription( IEventStoreConnection connection, IEventSubscriber subscriber, + IJsonSerializer serializer, ProjectionClient projectionClient, string position, string streamFilter) @@ -34,8 +37,10 @@ namespace Squidex.Infrastructure.EventSourcing var streamName = projectionClient.CreateProjectionAsync(streamFilter).Result; + this.serializer = serializer; this.subscriber = subscriber; - this.subscription = SubscribeToStream(streamName); + + subscription = SubscribeToStream(streamName); } public Task StopAsync() @@ -56,7 +61,7 @@ namespace Squidex.Infrastructure.EventSourcing return connection.SubscribeToStreamFrom(streamName, position, settings, (s, e) => { - var storedEvent = Formatter.Read(e); + var storedEvent = Formatter.Read(e, serializer); subscriber.OnEventAsync(this, storedEvent).Wait(); }, null, diff --git a/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs b/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs index 8748ba8b1..70e4d3397 100644 --- a/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs +++ b/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEvent.cs @@ -21,18 +21,19 @@ namespace Squidex.Infrastructure.EventSourcing [BsonRequired] public string Payload { get; set; } - [BsonElement] + [BsonElement("Metadata")] [BsonRequired] - public BsonDocument Metadata { get; set; } + [BsonJson] + public EnvelopeHeaders Headers { get; set; } public static MongoEvent FromEventData(EventData data) { - return new MongoEvent { Type = data.Type, Metadata = BsonDocument.Parse(data.Payload), Payload = data.Payload }; + return new MongoEvent { Type = data.Type, Headers = data.Headers, Payload = data.Payload }; } public EventData ToEventData() { - return new EventData { Type = Type, Metadata = Metadata.ToJson().ToString(), Payload = Payload }; + return new EventData(Type, Headers, Payload); } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs deleted file mode 100644 index e9aa9d8cc..000000000 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs +++ /dev/null @@ -1,155 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Globalization; -using MongoDB.Bson; -using Newtonsoft.Json.Linq; - -namespace Squidex.Infrastructure.MongoDb -{ - public static class BsonJsonConverter - { - public static BsonDocument ToBson(this JObject source) - { - var result = new BsonDocument(); - - foreach (var property in source) - { - result.Add(property.Key.EscapeJson(), property.Value.ToBson()); - } - - return result; - } - - public static JObject ToJson(this BsonDocument source) - { - var result = new JObject(); - - foreach (var property in source) - { - result.Add(property.Name.UnescapeBson(), property.Value.ToJson()); - } - - return result; - } - - public static BsonArray ToBson(this JArray source) - { - var result = new BsonArray(); - - foreach (var item in source) - { - result.Add(item.ToBson()); - } - - return result; - } - - public static JArray ToJson(this BsonArray source) - { - var result = new JArray(); - - foreach (var item in source) - { - result.Add(item.ToJson()); - } - - return result; - } - - public static BsonValue ToBson(this JToken source) - { - switch (source.Type) - { - case JTokenType.Object: - return ((JObject)source).ToBson(); - case JTokenType.Array: - return ((JArray)source).ToBson(); - case JTokenType.Integer: - return BsonValue.Create(((JValue)source).Value); - case JTokenType.Float: - return BsonValue.Create(((JValue)source).Value); - case JTokenType.String: - return BsonValue.Create(((JValue)source).Value); - case JTokenType.Boolean: - return BsonValue.Create(((JValue)source).Value); - case JTokenType.Null: - return BsonNull.Value; - case JTokenType.Undefined: - return BsonUndefined.Value; - case JTokenType.Bytes: - return BsonValue.Create(((JValue)source).Value); - case JTokenType.Guid: - return BsonValue.Create(((JValue)source).ToString(CultureInfo.InvariantCulture)); - case JTokenType.Uri: - return BsonValue.Create(((JValue)source).ToString(CultureInfo.InvariantCulture)); - case JTokenType.TimeSpan: - return BsonValue.Create(((JValue)source).ToString(CultureInfo.InvariantCulture)); - case JTokenType.Date: - { - var value = ((JValue)source).Value; - - if (value is DateTime dateTime) - { - return dateTime.ToString("yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture); - } - else if (value is DateTimeOffset dateTimeOffset) - { - if (dateTimeOffset.Offset == TimeSpan.Zero) - { - return dateTimeOffset.UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture); - } - else - { - return dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture); - } - } - else - { - return value.ToString(); - } - } - } - - throw new NotSupportedException($"Cannot convert {source.GetType()} to Bson."); - } - - public static JToken ToJson(this BsonValue source) - { - switch (source.BsonType) - { - case BsonType.Document: - return source.AsBsonDocument.ToJson(); - case BsonType.Array: - return source.AsBsonArray.ToJson(); - case BsonType.Double: - return new JValue(source.AsDouble); - case BsonType.String: - return new JValue(source.AsString); - case BsonType.Boolean: - return new JValue(source.AsBoolean); - case BsonType.DateTime: - return new JValue(source.ToUniversalTime()); - case BsonType.Int32: - return new JValue(source.AsInt32); - case BsonType.Int64: - return new JValue(source.AsInt64); - case BsonType.Decimal128: - return new JValue(source.AsDecimal); - case BsonType.Binary: - return new JValue(source.AsBsonBinaryData.Bytes); - case BsonType.Null: - return JValue.CreateNull(); - case BsonType.Undefined: - return JValue.CreateUndefined(); - } - - throw new NotSupportedException($"Cannot convert {source.GetType()} to Json."); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs index ba6f659a8..247f6a918 100644 --- a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs @@ -27,17 +27,15 @@ namespace Squidex.Infrastructure.EventSourcing public Envelope Parse(EventData eventData, bool migrate = true, Func stringConverter = null) { - var eventType = typeNameRegistry.GetType(eventData.Type); + var payloadType = typeNameRegistry.GetType(eventData.Type); + var payload = serializer.Deserialize(eventData.Payload, payloadType, stringConverter); - var eventHeaders = serializer.Deserialize(eventData.Metadata, null, stringConverter); - var eventContent = serializer.Deserialize(eventData.Payload, eventType, stringConverter); - - if (migrate && eventContent is IMigratedEvent migratedEvent) + if (migrate && payload is IMigratedEvent migratedEvent) { - eventContent = migratedEvent.Migrate(); + payload = migratedEvent.Migrate(); } - var envelope = new Envelope(eventContent, eventHeaders); + var envelope = new Envelope(payload, eventData.Headers); return envelope; } @@ -51,14 +49,12 @@ namespace Squidex.Infrastructure.EventSourcing eventPayload = migratedEvent.Migrate(); } - var eventType = typeNameRegistry.GetName(eventPayload.GetType()); + var payloadType = typeNameRegistry.GetName(eventPayload.GetType()); + var payload = serializer.Serialize(envelope.Payload); envelope.SetCommitId(commitId); - var eventHeaders = serializer.Serialize(envelope.Headers); - var eventContent = serializer.Serialize(envelope.Payload); - - return new EventData { Type = eventType, Payload = eventContent, Metadata = eventHeaders }; + return new EventData(payloadType, envelope.Headers, payload); } } } diff --git a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs index f1dce1331..20176f576 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs @@ -6,7 +6,10 @@ // ========================================================================== using System; +using System.Globalization; using NodaTime; +using NodaTime.Text; +using Squidex.Infrastructure.Json.Objects; namespace Squidex.Infrastructure.EventSourcing { @@ -19,69 +22,90 @@ namespace Squidex.Infrastructure.EventSourcing public static Envelope SetEventPosition(this Envelope envelope, string value) where T : class { - envelope.Headers.Set(CommonHeaders.EventNumber, value); + envelope.Headers.Add(CommonHeaders.EventNumber, value); return envelope; } public static long EventStreamNumber(this EnvelopeHeaders headers) { - return headers[CommonHeaders.EventStreamNumber].ToInt64(); + return headers.GetInt64(CommonHeaders.EventStreamNumber); } public static Envelope SetEventStreamNumber(this Envelope envelope, long value) where T : class { - envelope.Headers.Set(CommonHeaders.EventStreamNumber, value); + envelope.Headers.Add(CommonHeaders.EventStreamNumber, value); return envelope; } public static Guid CommitId(this EnvelopeHeaders headers) { - return headers[CommonHeaders.CommitId].ToGuid(); + return headers.GetGuid(CommonHeaders.CommitId); } public static Envelope SetCommitId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Set(CommonHeaders.CommitId, value); + envelope.Headers.Add(CommonHeaders.CommitId, value); return envelope; } public static Guid AggregateId(this EnvelopeHeaders headers) { - return headers[CommonHeaders.AggregateId].ToGuid(); + return headers.GetGuid(CommonHeaders.AggregateId); } public static Envelope SetAggregateId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Set(CommonHeaders.AggregateId, value); + envelope.Headers.Add(CommonHeaders.AggregateId, value); return envelope; } public static Guid EventId(this EnvelopeHeaders headers) { - return headers[CommonHeaders.EventId].ToGuid(); + return headers.GetGuid(CommonHeaders.EventId); } public static Envelope SetEventId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Set(CommonHeaders.EventId, value); + envelope.Headers.Add(CommonHeaders.EventId, value); return envelope; } public static Instant Timestamp(this EnvelopeHeaders headers) { - return headers[CommonHeaders.Timestamp].ToInstant(); + return headers.GetInstant(CommonHeaders.Timestamp); } public static Envelope SetTimestamp(this Envelope envelope, Instant value) where T : class { - envelope.Headers.Set(CommonHeaders.Timestamp, value); + envelope.Headers.Add(CommonHeaders.Timestamp, value); return envelope; } + + public static long GetInt64(this JsonObject obj, string key) + { + var value = obj[key]; + + return value is JsonScalar s ? (long)s.Value : long.Parse(value.ToString(), CultureInfo.InvariantCulture); + } + + public static Guid GetGuid(this JsonObject obj, string key) + { + var value = obj[key]; + + return Guid.Parse(value.ToString()); + } + + public static Instant GetInstant(this JsonObject obj, string key) + { + var value = obj[key]; + + return InstantPattern.General.Parse(value.ToString()).Value; + } } } diff --git a/src/Squidex.Infrastructure/EventSourcing/EnvelopeHeaders.cs b/src/Squidex.Infrastructure/EventSourcing/EnvelopeHeaders.cs index 3b53fcd30..021ec109f 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EnvelopeHeaders.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EnvelopeHeaders.cs @@ -5,37 +5,24 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Squidex.Infrastructure.Json.Objects; + namespace Squidex.Infrastructure.EventSourcing { - public sealed class EnvelopeHeaders : PropertiesBag + public sealed class EnvelopeHeaders : JsonObject { public EnvelopeHeaders() { } - public EnvelopeHeaders(PropertiesBag bag) + public EnvelopeHeaders(JsonObject headers) + : base(headers) { - if (bag == null) - { - return; - } - - foreach (var property in bag.Properties) - { - Set(property.Key, property.Value.RawValue); - } } public EnvelopeHeaders Clone() { - var clone = new EnvelopeHeaders(); - - foreach (var property in Properties) - { - clone.Set(property.Key, property.Value.RawValue); - } - - return clone; + return new EnvelopeHeaders(this); } } } diff --git a/src/Squidex.Infrastructure/EventSourcing/EventData.cs b/src/Squidex.Infrastructure/EventSourcing/EventData.cs index a3d82188f..016043919 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EventData.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EventData.cs @@ -7,12 +7,25 @@ namespace Squidex.Infrastructure.EventSourcing { - public class EventData + public sealed class EventData { - public string Payload { get; set; } + public EnvelopeHeaders Headers { get; } - public string Metadata { get; set; } + public string Payload { get; } public string Type { get; set; } + + public EventData(string type, EnvelopeHeaders headers, string payload) + { + Guard.NotNull(type, nameof(type)); + Guard.NotNull(headers, nameof(headers)); + Guard.NotNull(payload, nameof(payload)); + + Headers = headers; + + Payload = payload; + + Type = type; + } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs deleted file mode 100644 index 8eb624c1f..000000000 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/PropertiesBagConverter.cs +++ /dev/null @@ -1,78 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using Newtonsoft.Json; -using NodaTime; -using NodaTime.Extensions; - -namespace Squidex.Infrastructure.Json.Newtonsoft -{ - public sealed class PropertiesBagConverter : JsonClassConverter where T : PropertiesBag, new() - { - protected override void WriteValue(JsonWriter writer, T value, JsonSerializer serializer) - { - writer.WriteStartObject(); - - foreach (var kvp in value.Properties) - { - writer.WritePropertyName(kvp.Key); - - if (kvp.Value.RawValue is Instant instant) - { - writer.WriteValue(instant.ToString()); - } - else - { - writer.WriteValue(kvp.Value.RawValue); - } - } - - writer.WriteEndObject(); - } - - protected override T ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) - { - if (reader.TokenType != JsonToken.StartObject) - { - throw new JsonException($"Expected Object, but got {reader.TokenType}."); - } - - var properties = new T(); - - while (reader.Read()) - { - if (reader.TokenType != JsonToken.PropertyName) - { - break; - } - - var key = reader.Value.ToString(); - - reader.Read(); - - var value = reader.Value; - - if (value is DateTime dateTime) - { - properties.Set(key, dateTime.ToInstant()); - } - else - { - properties.Set(key, value); - } - } - - return properties; - } - - public override bool CanConvert(Type objectType) - { - return objectType == typeof(T); - } - } -} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs index a2cacce74..0c29a39ca 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs @@ -12,9 +12,9 @@ using System.Linq; namespace Squidex.Infrastructure.Json.Objects { - public sealed class JsonObject : IReadOnlyDictionary, IJsonValue, IEquatable + public class JsonObject : IReadOnlyDictionary, IJsonValue, IEquatable { - private readonly Dictionary inner = new Dictionary(); + private readonly Dictionary inner; public IJsonValue this[string key] { @@ -51,6 +51,16 @@ namespace Squidex.Infrastructure.Json.Objects get { return JsonValueType.Array; } } + public JsonObject() + { + inner = new Dictionary(); + } + + public JsonObject(JsonObject obj) + { + inner = new Dictionary(obj.inner); + } + public JsonObject Add(string key, object value) { return Add(key, JsonValue.Create(value)); @@ -61,7 +71,7 @@ namespace Squidex.Infrastructure.Json.Objects Guard.NotNullOrEmpty(key, nameof(key)); Guard.NotNull(value, nameof(value)); - inner.Add(key, value); + inner[key] = value; return this; } diff --git a/src/Squidex.Infrastructure/PropertiesBag.cs b/src/Squidex.Infrastructure/PropertiesBag.cs deleted file mode 100644 index 511c76368..000000000 --- a/src/Squidex.Infrastructure/PropertiesBag.cs +++ /dev/null @@ -1,112 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Dynamic; - -namespace Squidex.Infrastructure -{ - public class PropertiesBag : DynamicObject - { - private static readonly PropertyValue FallbackValue = new PropertyValue(null); - private readonly Dictionary internalDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); - - public int Count - { - get { return internalDictionary.Count; } - } - - public IReadOnlyDictionary Properties - { - get { return internalDictionary; } - } - - public IEnumerable PropertyNames - { - get { return internalDictionary.Keys; } - } - - public PropertyValue this[string propertyName] - { - get - { - Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); - - return internalDictionary.GetOrDefault(propertyName) ?? FallbackValue; - } - } - - public override IEnumerable GetDynamicMemberNames() - { - return internalDictionary.Keys; - } - - public override bool TryGetMember(GetMemberBinder binder, out object result) - { - result = this[binder.Name]; - - return true; - } - - public override bool TrySetMember(SetMemberBinder binder, object value) - { - internalDictionary[binder.Name] = new PropertyValue(value); - - return true; - } - - public bool Contains(string propertyName) - { - Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); - - return internalDictionary.ContainsKey(propertyName); - } - - public bool Remove(string propertyName) - { - Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); - - return internalDictionary.Remove(propertyName); - } - - public PropertiesBag Set(string propertyName, object value) - { - Guard.NotNullOrEmpty(propertyName, nameof(propertyName)); - - internalDictionary[propertyName] = new PropertyValue(value); - - return this; - } - - public bool Rename(string oldPropertyName, string newPropertyName) - { - Guard.NotNullOrEmpty(oldPropertyName, nameof(oldPropertyName)); - Guard.NotNullOrEmpty(newPropertyName, nameof(newPropertyName)); - - if (internalDictionary.ContainsKey(newPropertyName)) - { - throw new ArgumentException($"An property with the key '{newPropertyName}' already exists.", newPropertyName); - } - - if (string.Equals(oldPropertyName, newPropertyName, StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException($"The property names '{newPropertyName}' are equal.", newPropertyName); - } - - if (!internalDictionary.TryGetValue(oldPropertyName, out var property)) - { - return false; - } - - internalDictionary[newPropertyName] = property; - internalDictionary.Remove(oldPropertyName); - - return true; - } - } -} diff --git a/src/Squidex.Infrastructure/PropertyValue.cs b/src/Squidex.Infrastructure/PropertyValue.cs deleted file mode 100644 index ddec447c6..000000000 --- a/src/Squidex.Infrastructure/PropertyValue.cs +++ /dev/null @@ -1,235 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Globalization; -using NodaTime; -using NodaTime.Text; - -namespace Squidex.Infrastructure -{ - public sealed class PropertyValue : DynamicObject - { - private readonly object rawValue; - - private static readonly Dictionary> Parsers = - new Dictionary> - { - { typeof(string), p => p.ToString() }, - { typeof(bool), p => p.ToBoolean() }, - { typeof(bool?), p => p.ToNullableBoolean() }, - { typeof(float), p => p.ToSingle() }, - { typeof(float?), p => p.ToNullableSingle() }, - { typeof(double), p => p.ToDouble() }, - { typeof(double?), p => p.ToNullableDouble() }, - { typeof(int), p => p.ToInt32() }, - { typeof(int?), p => p.ToNullableInt32() }, - { typeof(long), p => p.ToInt64() }, - { typeof(long?), p => p.ToNullableInt64() }, - { typeof(Instant), p => p.ToInstant() }, - { typeof(Instant?), p => p.ToNullableInstant() }, - { typeof(Guid), p => p.ToGuid() }, - { typeof(Guid?), p => p.ToNullableGuid() } - }; - - public object RawValue - { - get { return rawValue; } - } - - internal PropertyValue(object rawValue) - { - if (rawValue != null && !Parsers.ContainsKey(rawValue.GetType())) - { - throw new InvalidOperationException($"The type '{rawValue.GetType()}' is not supported."); - } - - this.rawValue = rawValue; - } - - public override bool TryConvert(ConvertBinder binder, out object result) - { - result = null; - - if (!Parsers.TryGetValue(binder.Type, out var parser)) - { - return false; - } - - result = parser(this); - - return true; - } - - public override string ToString() - { - return rawValue?.ToString(); - } - - public bool ToBoolean() - { - return ToOrParseValue(CultureInfo.InvariantCulture, ParseBoolean); - } - - public bool? ToNullableBoolean() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, ParseBoolean); - } - - public float ToSingle() - { - return ToOrParseValue(CultureInfo.InvariantCulture, x => float.Parse(x, CultureInfo.InvariantCulture)); - } - - public float? ToNullableSingle() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => float.Parse(x, CultureInfo.InvariantCulture)); - } - - public double ToDouble() - { - return ToOrParseValue(CultureInfo.InvariantCulture, x => double.Parse(x, CultureInfo.InvariantCulture)); - } - - public double? ToNullableDouble() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => double.Parse(x, CultureInfo.InvariantCulture)); - } - - public int ToInt32() - { - return ToOrParseValue(CultureInfo.InvariantCulture, x => int.Parse(x, CultureInfo.InvariantCulture)); - } - - public int? ToNullableInt32() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => int.Parse(x, CultureInfo.InvariantCulture)); - } - - public long ToInt64() - { - return ToOrParseValue(CultureInfo.InvariantCulture, x => long.Parse(x, CultureInfo.InvariantCulture)); - } - - public long? ToNullableInt64() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => long.Parse(x, CultureInfo.InvariantCulture)); - } - - public Instant ToInstant() - { - return ToOrParseValue(CultureInfo.InvariantCulture, x => InstantPattern.General.Parse(x).Value); - } - - public Instant? ToNullableInstant() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, x => InstantPattern.General.Parse(x).Value); - } - - public Guid ToGuid() - { - return ToOrParseValue(CultureInfo.InvariantCulture, Guid.Parse); - } - - public Guid? ToNullableGuid() - { - return ToNullableOrParseValue(CultureInfo.InvariantCulture, Guid.Parse); - } - - private T? ToNullableOrParseValue(IFormatProvider culture, Func parser) where T : struct - { - return TryParse(culture, parser, out var result) ? result : (T?)null; - } - - private T ToOrParseValue(IFormatProvider culture, Func parser) - { - return TryParse(culture, parser, out var result) ? result : default(T); - } - - private bool TryParse(IFormatProvider culture, Func parser, out T result) - { - var value = rawValue; - - if (value != null) - { - var valueType = value.GetType(); - - if (valueType == typeof(T)) - { - result = (T)value; - } - else if (valueType == typeof(string)) - { - result = Parse(parser, valueType, value); - } - else - { - result = Convert(culture, value, valueType); - } - - return true; - } - - result = default(T); - - return false; - } - - private static T Convert(IFormatProvider culture, object value, Type valueType) - { - var requestedType = typeof(T); - - try - { - return (T)System.Convert.ChangeType(value, requestedType, culture); - } - catch (OverflowException) - { - var message = $"The property has type '{valueType}' and cannot be casted to '{requestedType}' because it is either too small or large."; - - throw new InvalidCastException(message); - } - catch (InvalidCastException) - { - var message = $"The property has type '{valueType}' and cannot be casted to '{requestedType}'."; - - throw new InvalidCastException(message); - } - } - - private static T Parse(Func parser, Type valueType, object value) - { - var requestedType = typeof(T); - - try - { - return parser(value.ToString()); - } - catch (Exception ex) - { - var message = $"The property has type '{valueType}' and cannot be casted to '{requestedType}'."; - - throw new InvalidCastException(message, ex); - } - } - - private static bool ParseBoolean(string value) - { - switch (value) - { - case "1": - return true; - case "0": - return false; - default: - return bool.Parse(value); - } - } - } -} diff --git a/src/Squidex/Config/Domain/EventStoreServices.cs b/src/Squidex/Config/Domain/EventStoreServices.cs index 85066ae53..a960b1488 100644 --- a/src/Squidex/Config/Domain/EventStoreServices.cs +++ b/src/Squidex/Config/Domain/EventStoreServices.cs @@ -14,6 +14,7 @@ using Squidex.Infrastructure; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing.Grains; +using Squidex.Infrastructure.Json; using Squidex.Infrastructure.States; namespace Squidex.Config.Domain @@ -50,7 +51,7 @@ namespace Squidex.Config.Domain services.AddSingletonAs(c => new GetEventStoreHealthCheck(connection)) .As(); - services.AddSingletonAs(c => new GetEventStore(connection, eventStorePrefix, eventStoreProjectionHost)) + services.AddSingletonAs(c => new GetEventStore(connection, c.GetRequiredService(), eventStorePrefix, eventStoreProjectionHost)) .As(); } }); diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 2f68fccc3..96c8e1dd1 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -56,8 +56,6 @@ namespace Squidex.Config.Domain new NamedGuidIdConverter(), new NamedLongIdConverter(), new NamedStringIdConverter(), - new PropertiesBagConverter(), - new PropertiesBagConverter(), new RefTokenConverter(), new RolesConverter(), new RuleConverter(), diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index bc22739d1..bafb2c6f8 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -47,8 +47,6 @@ namespace Squidex.Domain.Apps.Core new NamedGuidIdConverter(), new NamedLongIdConverter(), new NamedStringIdConverter(), - new PropertiesBagConverter(), - new PropertiesBagConverter(), new RefTokenConverter(), new RolesConverter(), new RuleConverter(), diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs index 6d64aad03..1179039aa 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs @@ -82,9 +82,9 @@ namespace Squidex.Domain.Apps.Entities.Backup var envelope = Envelope.Create(@event); - envelope.Headers.Set(RandomGuid().ToString(), i); - envelope.Headers.Set("Id", RandomGuid()); - envelope.Headers.Set("Index", i); + envelope.Headers.Add(RandomGuid().ToString(), i); + envelope.Headers.Add("Id", RandomGuid()); + envelope.Headers.Add("Index", i); sourceEvents.Add(($"My-{RandomGuid()}", envelope)); } @@ -96,7 +96,7 @@ namespace Squidex.Domain.Apps.Entities.Backup var eventData = formatter.ToEventData(@event.Event, Guid.NewGuid(), true); var eventStored = new StoredEvent("S", "1", 2, eventData); - var index = @event.Event.Headers["Index"].ToInt32(); + var index = int.Parse(@event.Event.Headers["Index"].ToString()); if (index % 17 == 0) { @@ -124,7 +124,7 @@ namespace Squidex.Domain.Apps.Entities.Backup { await reader.ReadEventsAsync(streamNameResolver, formatter, async @event => { - var index = @event.Event.Headers["Index"].ToInt32(); + var index = int.Parse(@event.Event.Headers["Index"].ToString()); if (index % 17 == 0) { @@ -155,7 +155,7 @@ namespace Squidex.Domain.Apps.Entities.Backup Assert.Equal(rhs.Payload.GuidRaw, reader.OldGuid(lhs.Payload.GuidRaw)); Assert.Equal(rhs.Payload.GuidNamed.Id, reader.OldGuid(lhs.Payload.GuidNamed.Id)); - Assert.Equal(rhs.Headers["Id"].ToGuid(), reader.OldGuid(lhs.Headers["Id"].ToGuid())); + Assert.Equal(rhs.Headers.GetGuid("Id"), reader.OldGuid(lhs.Headers.GetGuid("Id"))); } } } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs index 212352d04..60e2b769f 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/DefaultEventDataFormatterTests.cs @@ -88,9 +88,9 @@ namespace Squidex.Infrastructure.EventSourcing Assert.Equal(inputEvent.Payload.MyProperty, outputEvent.Payload.MyProperty); } - private static void AssertHeaders(PropertiesBag lhs, PropertiesBag rhs) + private static void AssertHeaders(EnvelopeHeaders lhs, EnvelopeHeaders rhs) { - foreach (var key in lhs.PropertyNames.Concat(rhs.PropertyNames).Distinct()) + foreach (var key in lhs.Keys.Concat(rhs.Keys).Distinct()) { Assert.Equal(lhs[key].ToString(), rhs[key].ToString()); } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs index bec3549d1..9d377646b 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs @@ -23,7 +23,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetTimestamp(timestamp); Assert.Equal(timestamp, sut.Headers.Timestamp()); - Assert.Equal(timestamp, sut.Headers["Timestamp"].ToInstant()); + Assert.Equal(timestamp, sut.Headers.GetInstant("Timestamp")); } [Fact] @@ -34,7 +34,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetCommitId(commitId); Assert.Equal(commitId, sut.Headers.CommitId()); - Assert.Equal(commitId, sut.Headers["CommitId"].ToGuid()); + Assert.Equal(commitId, sut.Headers.GetGuid("CommitId")); } [Fact] @@ -45,7 +45,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetEventId(commitId); Assert.Equal(commitId, sut.Headers.EventId()); - Assert.Equal(commitId, sut.Headers["EventId"].ToGuid()); + Assert.Equal(commitId, sut.Headers.GetGuid("EventId")); } [Fact] @@ -56,7 +56,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetAggregateId(commitId); Assert.Equal(commitId, sut.Headers.AggregateId()); - Assert.Equal(commitId, sut.Headers["AggregateId"].ToGuid()); + Assert.Equal(commitId, sut.Headers.GetGuid("AggregateId")); } [Fact] @@ -78,7 +78,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetEventStreamNumber(eventStreamNumber); Assert.Equal(eventStreamNumber, sut.Headers.EventStreamNumber()); - Assert.Equal(eventStreamNumber, sut.Headers["EventStreamNumber"].ToInt64()); + Assert.Equal(eventStreamNumber, sut.Headers.GetInt64("EventStreamNumber")); } } } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs index c3f4b091c..21b1c7363 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.Linq; +using Squidex.Infrastructure.Json.Objects; using Xunit; namespace Squidex.Infrastructure.EventSourcing @@ -17,21 +18,13 @@ namespace Squidex.Infrastructure.EventSourcing { var headers = new EnvelopeHeaders(); - Assert.Equal(0, headers.Count); - } - - [Fact] - public void Should_create_headers_with_null_properties() - { - var headers = new EnvelopeHeaders(null); - - Assert.Equal(0, headers.Count); + Assert.Empty(headers); } [Fact] public void Should_create_headers_as_copy() { - var source = new PropertiesBag().Set("Key1", 123); + var source = new JsonObject().Add("Key1", 123); var headers = new EnvelopeHeaders(source); CompareHeaders(headers, source); @@ -40,7 +33,7 @@ namespace Squidex.Infrastructure.EventSourcing [Fact] public void Should_clone_headers() { - var source = new PropertiesBag().Set("Key1", 123); + var source = new JsonObject().Add("Key1", 123); var headers = new EnvelopeHeaders(source); var clone = headers.Clone(); @@ -48,9 +41,9 @@ namespace Squidex.Infrastructure.EventSourcing CompareHeaders(headers, clone); } - private static void CompareHeaders(PropertiesBag lhs, PropertiesBag rhs) + private static void CompareHeaders(JsonObject lhs, JsonObject rhs) { - foreach (var key in lhs.PropertyNames.Concat(rhs.PropertyNames).Distinct()) + foreach (var key in lhs.Keys.Concat(rhs.Keys).Distinct()) { Assert.Equal(lhs[key].ToString(), rhs[key].ToString()); } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs index 7f5bd174c..b7842bec0 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs @@ -49,7 +49,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains private readonly ISemanticLog log = A.Fake(); private readonly IStore store = A.Fake>(); private readonly IEventDataFormatter formatter = A.Fake(); - private readonly EventData eventData = new EventData(); + private readonly EventData eventData = new EventData("Type", new EnvelopeHeaders(), "Payload"); private readonly Envelope envelope = new Envelope(new MyEvent()); private readonly EventConsumerGrain sut; private readonly string consumerName; diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/RetrySubscriptionTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/RetrySubscriptionTests.cs index 85aee50d2..10ad267e9 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/RetrySubscriptionTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/RetrySubscriptionTests.cs @@ -90,7 +90,7 @@ namespace Squidex.Infrastructure.EventSourcing [Fact] public async Task Should_forward_event_from_inner_subscription() { - var ev = new StoredEvent("Stream", "1", 2, new EventData()); + var ev = new StoredEvent("Stream", "1", 2, new EventData("Type", new EnvelopeHeaders(), "Payload")); await OnEventAsync(eventSubscription, ev); await sut.StopAsync(); @@ -102,7 +102,7 @@ namespace Squidex.Infrastructure.EventSourcing [Fact] public async Task Should_not_forward_event_when_message_is_from_another_subscription() { - var ev = new StoredEvent("Stream", "1", 2, new EventData()); + var ev = new StoredEvent("Stream", "1", 2, new EventData("Type", new EnvelopeHeaders(), "Payload")); await OnEventAsync(A.Fake(), ev); await sut.StopAsync(); diff --git a/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs b/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs index 543d74468..c8ae76adf 100644 --- a/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs +++ b/tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs @@ -117,44 +117,6 @@ namespace Squidex.Infrastructure.MongoDb private readonly TestObject source = TestObject.CreateWithValues(); private readonly JsonSerializer serializer = JsonSerializer.CreateDefault(); - [Fact] - public void Should_serialize_and_deserialize_to_bson_with_json() - { - var target = JObject.FromObject(source).ToBson().ToJson().ToObject(); - - target.Should().BeEquivalentTo(source); - } - - [Fact] - public void Should_serialize_datetime_to_iso() - { - source.DateTime = new DateTime(2012, 12, 12, 12, 12, 12, DateTimeKind.Utc); - - var target = JObject.FromObject(source).ToBson(); - - Assert.Equal("2012-12-12T12:12:12Z", target["DateTime"].ToString()); - } - - [Fact] - public void Should_serialize_datetimeoffset_to_iso_utc() - { - source.DateTimeOffset = new DateTime(2012, 12, 12, 12, 12, 12, DateTimeKind.Utc); - - var target = JObject.FromObject(source).ToBson(); - - Assert.Equal("2012-12-12T12:12:12Z", target["DateTimeOffset"].ToString()); - } - - [Fact] - public void Should_serialize_datetimeoffset_to_iso_utc_with_offset() - { - source.DateTimeOffset = new DateTimeOffset(2012, 12, 12, 12, 12, 12, TimeSpan.FromHours(2)); - - var target = JObject.FromObject(source).ToBson(); - - Assert.Equal("2012-12-12T12:12:12+02:00", target["DateTimeOffset"].ToString()); - } - [Fact] public void Should_write_problematic_object() { diff --git a/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs b/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs deleted file mode 100644 index e60eec701..000000000 --- a/tests/Squidex.Infrastructure.Tests/PropertiesBagTests.cs +++ /dev/null @@ -1,428 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright () Squidex UG (haftungsbeschränkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Linq; -using Microsoft.CSharp.RuntimeBinder; -using NodaTime; -using Squidex.Infrastructure.TestHelpers; -using Xunit; - -namespace Squidex.Infrastructure -{ - public class PropertiesBagTests - { - private readonly PropertiesBag bag = new PropertiesBag(); - private readonly dynamic dynamicBag; - - public PropertiesBagTests() - { - dynamicBag = bag; - } - - [Fact] - public void Should_serialize_and_deserialize_empty_bag() - { - var output = bag.SerializeAndDeserialize(); - - Assert.Equal(bag.Count, output.Count); - } - - [Fact] - public void Should_serialize_and_deserialize() - { - var time = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); - - bag.Set("Key1", time); - bag.Set("Key2", "MyString"); - bag.Set("Key3", 123L); - bag.Set("Key4", true); - bag.Set("Key5", Guid.NewGuid()); - - var output = bag.SerializeAndDeserialize(); - - foreach (var kvp in output.Properties.Take(4)) - { - Assert.Equal(kvp.Value.RawValue, bag[kvp.Key].RawValue); - } - - Assert.Equal(bag["Key5"].ToGuid(), output["Key5"].ToGuid()); - } - - [Fact] - public void Should_return_false_when_renaming_unknown_property() - { - Assert.False(bag.Rename("OldKey", "NewKey")); - } - - [Fact] - public void Should_throw_when_renaming_to_existing_property() - { - bag.Set("NewKey", 1); - - Assert.Throws(() => bag.Rename("OldKey", "NewKey")); - } - - [Fact] - public void Should_throw_when_renaming_to_same_key() - { - Assert.Throws(() => bag.Rename("SameKey", "SameKey")); - } - - [Fact] - public void Should_provide_property_with_new_name_after_rename() - { - bag.Set("OldKey", 123); - - Assert.True(bag.Rename("OldKey", "NewKey")); - Assert.True(bag.Contains("NewKey")); - - Assert.Equal(1, bag.Count); - Assert.Equal(123, bag["NewKey"].ToInt64()); - - Assert.False(bag.Contains("OldKey")); - } - - [Fact] - public void Should_calculate_count_correctly() - { - bag.Set("Key1", 1); - bag.Set("Key2", 1); - - Assert.Equal(2, bag.Count); - } - - [Fact] - public void Should_calculate_keys_correctly() - { - bag.Set("Key1", 1); - bag.Set("Key2", 1); - - Assert.Equal(new[] { "Key1", "Key2" }, bag.PropertyNames.ToArray()); - Assert.Equal(new[] { "Key1", "Key2" }, bag.Properties.Keys.ToArray()); - Assert.Equal(new[] { "Key1", "Key2" }, bag.GetDynamicMemberNames().ToArray()); - } - - [Fact] - public void Should_return_correct_value_when_contains_check() - { - Assert.False(bag.Contains("Key")); - - bag.Set("Key", 1); - - Assert.True(bag.Contains("Key")); - Assert.True(bag.Contains("KEY")); - } - - [Fact] - public void Should_returne_false_when_property_to_rename_does_not_exist() - { - Assert.False(bag.Remove("NOTFOUND")); - } - - [Fact] - public void Should_ignore_casing_when_returning() - { - bag.Set("Key", 1); - - Assert.True(bag.Remove("KEY")); - Assert.False(bag.Contains("KEY")); - } - - [Fact] - public void Should_set_value_as_dynamic() - { - dynamicBag.Key = 456; - - Assert.Equal(456, (int)dynamicBag.Key); - } - - [Fact] - public void Should_throw_when_setting_value_with_invalid_type_dynamically() - { - Assert.Throws(() => dynamicBag.Key = (byte)123); - } - - [Fact] - public void Should_throw_when_setting_value_with_invalid_type() - { - Assert.Throws(() => bag.Set("Key", (byte)1)); - } - - [Fact] - public void Should_return_false_when_making_contains_check() - { - Assert.False(dynamicBag.Contains("Key")); - } - - [Fact] - public void Should_provide_default_value_if_not_exists() - { - Assert.Equal(0, (int)dynamicBag.Key); - } - - [Fact] - public void Should_throw_when_parsing_failed() - { - bag.Set("Key", "abc"); - - Assert.Throws(() => bag["Key"].ToInt64()); - } - - [Fact] - public void Should_return_false_when_converter_does_not_exist() - { - bag.Set("Key", "abc"); - - Assert.Throws(() => (TimeSpan)dynamicBag.Key); - } - - [Fact] - public void Should_convert_string_to_numbers() - { - bag.Set("Key", 123); - - AssertNumber(); - } - - [Fact] - public void Should_convert_int_to_numbers() - { - bag.Set("Key", 123); - - AssertNumber(); - } - - [Fact] - public void Should_convert_long_to_numbers() - { - bag.Set("Key", 123L); - - AssertNumber(); - } - - [Fact] - public void Should_throw_when_casting_from_large_long() - { - bag.Set("Key", long.MaxValue); - - Assert.Throws(() => bag["Key"].ToInt32()); - } - - [Fact] - public void Should_convert_float_to_number() - { - bag.Set("Key", 123f); - - AssertNumber(); - } - - [Fact] - public void Should_convert_double_to_number() - { - bag.Set("Key", 123d); - - AssertNumber(); - } - - [Fact] - public void Should_throw_when_casting_from_large_doule() - { - bag.Set("Key", double.MaxValue); - - Assert.Equal(float.PositiveInfinity, bag["Key"].ToSingle()); - } - - [Fact] - public void Should_convert_from_instant_value() - { - var time = SystemClock.Instance.GetCurrentInstant(); - - bag.Set("Key", time); - - AssertInstant(time); - } - - [Fact] - public void Should_convert_from_instant_string() - { - var time = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); - - bag.Set("Key", time.ToString()); - - AssertInstant(time); - } - - [Fact] - public void Should_convert_from_guid_value() - { - var id = Guid.NewGuid(); - - bag.Set("Key", id); - - AssertGuid(id); - } - - [Fact] - public void Should_convert_from_guid_string() - { - var id = Guid.NewGuid(); - - bag.Set("Key", id.ToString()); - - AssertGuid(id); - } - - [Fact] - public void Should_convert_from_boolean_value() - { - bag.Set("Key", true); - - AssertBoolean(true); - } - - [Fact] - public void Should_convert_from_boolean_string() - { - bag.Set("Key", "true"); - - AssertBoolean(true); - } - - [Fact] - public void Should_convert_boolean_from_number() - { - bag.Set("Key", 1); - - AssertBoolean(true); - } - - [Fact] - public void Should_convert_boolean_to_truthy_number_string() - { - bag.Set("Key", "1"); - - AssertBoolean(true); - } - - [Fact] - public void Should_convert_boolean_to_falsy_number_string() - { - bag.Set("Key", "0"); - - AssertBoolean(false); - } - - [Fact] - public void Should_provide_value_as_string() - { - bag.Set("Key", "Foo"); - - AssertString("Foo"); - } - - [Fact] - public void Should_provide_null() - { - bag.Set("Key", null); - - AssertNull(); - } - - [Fact] - public void Should_throw_when_converting_instant_to_number() - { - bag.Set("Key", SystemClock.Instance.GetCurrentInstant()); - - Assert.Throws(() => bag["Key"].ToGuid()); - } - - private void AssertNumber() - { - AssertInt32(123); - AssertInt64(123); - AssertSingle(123); - AssertDouble(123); - } - - private void AssertString(string expected) - { - Assert.Equal(expected, bag["Key"].ToString()); - - Assert.Equal(expected, (string)dynamicBag.Key); - } - - private void AssertNull() - { - Assert.Null(bag["Key"].ToString()); - Assert.Null(bag["Key"].RawValue); - } - - private void AssertBoolean(bool expected) - { - Assert.Equal(expected, bag["Key"].ToBoolean()); - Assert.Equal(expected, bag["Key"].ToNullableBoolean()); - - Assert.Equal(expected, (bool)dynamicBag.Key); - Assert.Equal(expected, (bool?)dynamicBag.Key); - } - - private void AssertInstant(Instant expected) - { - Assert.Equal(expected, bag["Key"].ToInstant()); - Assert.Equal(expected, bag["Key"].ToNullableInstant().Value); - - Assert.Equal(expected, (Instant)dynamicBag.Key); - Assert.Equal(expected, (Instant?)dynamicBag.Key); - } - - private void AssertGuid(Guid expected) - { - Assert.Equal(expected, bag["Key"].ToGuid()); - Assert.Equal(expected, bag["Key"].ToNullableGuid()); - - Assert.Equal(expected, (Guid)dynamicBag.Key); - Assert.Equal(expected, (Guid?)dynamicBag.Key); - } - - private void AssertDouble(double expected) - { - Assert.Equal(expected, bag["Key"].ToDouble()); - Assert.Equal(expected, bag["Key"].ToNullableDouble()); - - Assert.Equal(expected, (double)dynamicBag.Key); - Assert.Equal(expected, (double?)dynamicBag.Key); - } - - private void AssertSingle(float expected) - { - Assert.Equal(expected, bag["Key"].ToSingle()); - Assert.Equal(expected, bag["Key"].ToNullableSingle()); - - Assert.Equal(expected, (float)dynamicBag.Key); - Assert.Equal(expected, (float?)dynamicBag.Key); - } - - private void AssertInt32(long expected) - { - Assert.Equal(expected, bag["Key"].ToInt64()); - Assert.Equal(expected, bag["Key"].ToNullableInt64()); - - Assert.Equal(expected, (long)dynamicBag.Key); - Assert.Equal(expected, (long?)dynamicBag.Key); - } - - private void AssertInt64(int expected) - { - Assert.Equal(expected, bag["Key"].ToInt64()); - Assert.Equal(expected, bag["Key"].ToNullableInt64()); - - Assert.Equal(expected, (int)dynamicBag.Key); - Assert.Equal(expected, (int?)dynamicBag.Key); - } - } -} \ No newline at end of file diff --git a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs index e7223fca2..a061b8a61 100644 --- a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs +++ b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs @@ -56,7 +56,7 @@ namespace Squidex.Infrastructure.States [Fact] public async Task Should_ignore_old_events() { - var storedEvent = new StoredEvent("1", "1", 0, new EventData()); + var storedEvent = new StoredEvent("1", "1", 0, new EventData("Type", new EnvelopeHeaders(), "Payload")); A.CallTo(() => eventStore.QueryAsync(key, 0)) .Returns(new List { storedEvent }); @@ -251,7 +251,7 @@ namespace Squidex.Infrastructure.States foreach (var @event in events) { - var eventData = new EventData(); + var eventData = new EventData("Type", new EnvelopeHeaders(), "Payload"); var eventStored = new StoredEvent(i.ToString(), i.ToString(), i, eventData); eventsStored.Add(eventStored); diff --git a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs index 9d913bdda..0eee70a27 100644 --- a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs +++ b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs @@ -32,8 +32,6 @@ namespace Squidex.Infrastructure.TestHelpers new NamedGuidIdConverter(), new NamedLongIdConverter(), new NamedStringIdConverter(), - new PropertiesBagConverter(), - new PropertiesBagConverter(), new RefTokenConverter(), new StringEnumConverter()), diff --git a/tools/Migrate_01/Rebuilder.cs b/tools/Migrate_01/Rebuilder.cs index 6214e37b4..d3bac5427 100644 --- a/tools/Migrate_01/Rebuilder.cs +++ b/tools/Migrate_01/Rebuilder.cs @@ -108,7 +108,7 @@ namespace Migrate_01 await eventStore.QueryAsync(async storedEvent => { - var headers = serializer.Deserialize(storedEvent.Data.Metadata); + var headers = storedEvent.Data.Headers; var id = headers.AggregateId(); From e62ad7d46223c5e3a743483a07df36110b9b4c6e Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 26 Nov 2018 21:12:26 +0100 Subject: [PATCH 15/33] Fixes for json. --- .../SquidexHeaderExtensions.cs | 2 +- .../EventSourcing/EnvelopeExtensions.cs | 62 +++- .../Newtonsoft/EnvelopeHeadersConverter.cs | 34 ++ .../Json/Newtonsoft/JsonValueConverter.cs | 5 +- .../Json/Objects/JsonArray.cs | 20 +- .../Json/Objects/JsonObject.cs | 8 +- .../Json/Objects/JsonScalar.cs | 18 +- .../Json/Objects/JsonValue.cs | 17 +- .../Config/Domain/SerializationServices.cs | 1 + tests/RunCoverage.ps1 | 2 +- .../Model/PartitioningTests.cs | 37 +- .../TestUtils.cs | 1 + .../EventSourcing/EnvelopeExtensionsTests.cs | 4 +- .../Grains/EventConsumerGrainTests.cs | 8 +- .../Json/Objects/JsonObjectTests.cs | 321 ++++++++++++++++++ .../NamedIdTests.cs | 52 +-- .../RefTokenTests.cs | 42 +-- .../TestHelpers/JsonHelper.cs | 1 + 18 files changed, 487 insertions(+), 148 deletions(-) create mode 100644 src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs create mode 100644 tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs diff --git a/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs b/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs index d65fcd3ff..dc2e05ad2 100644 --- a/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs +++ b/src/Squidex.Domain.Apps.Events/SquidexHeaderExtensions.cs @@ -19,7 +19,7 @@ namespace Squidex.Domain.Apps.Events public static Envelope SetAppId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Add(SquidexHeaders.AppId, value); + envelope.Headers.Add(SquidexHeaders.AppId, value.ToString()); return envelope; } diff --git a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs index 20176f576..968eadf3c 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs @@ -17,7 +17,7 @@ namespace Squidex.Infrastructure.EventSourcing { public static string EventPosition(this EnvelopeHeaders headers) { - return headers[CommonHeaders.EventNumber].ToString(); + return headers.GetString(CommonHeaders.EventNumber); } public static Envelope SetEventPosition(this Envelope envelope, string value) where T : class @@ -29,7 +29,7 @@ namespace Squidex.Infrastructure.EventSourcing public static long EventStreamNumber(this EnvelopeHeaders headers) { - return headers.GetInt64(CommonHeaders.EventStreamNumber); + return headers.GetLong(CommonHeaders.EventStreamNumber); } public static Envelope SetEventStreamNumber(this Envelope envelope, long value) where T : class @@ -46,7 +46,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Envelope SetCommitId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Add(CommonHeaders.CommitId, value); + envelope.Headers.Add(CommonHeaders.CommitId, value.ToString()); return envelope; } @@ -58,7 +58,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Envelope SetAggregateId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Add(CommonHeaders.AggregateId, value); + envelope.Headers.Add(CommonHeaders.AggregateId, value.ToString()); return envelope; } @@ -70,7 +70,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Envelope SetEventId(this Envelope envelope, Guid value) where T : class { - envelope.Headers.Add(CommonHeaders.EventId, value); + envelope.Headers.Add(CommonHeaders.EventId, value.ToString()); return envelope; } @@ -82,30 +82,62 @@ namespace Squidex.Infrastructure.EventSourcing public static Envelope SetTimestamp(this Envelope envelope, Instant value) where T : class { - envelope.Headers.Add(CommonHeaders.Timestamp, value); + envelope.Headers.Add(CommonHeaders.Timestamp, value.ToString()); return envelope; } - public static long GetInt64(this JsonObject obj, string key) + public static long GetLong(this JsonObject obj, string key) { - var value = obj[key]; - - return value is JsonScalar s ? (long)s.Value : long.Parse(value.ToString(), CultureInfo.InvariantCulture); + if (obj.TryGetValue(key, out var v)) + { + if (v is JsonScalar number) + { + return (long)number.Value; + } + else if (v.Type == JsonValueType.String && double.TryParse(v.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return (long)result; + } + } + + return 0; } public static Guid GetGuid(this JsonObject obj, string key) { - var value = obj[key]; - - return Guid.Parse(value.ToString()); + if (obj.TryGetValue(key, out var v)) + { + if (v.Type == JsonValueType.String && Guid.TryParse(v.ToString(), out var guid)) + { + return guid; + } + } + + return default(Guid); } public static Instant GetInstant(this JsonObject obj, string key) { - var value = obj[key]; + if (obj.TryGetValue(key, out var v)) + { + if (v.Type == JsonValueType.String && InstantPattern.General.Parse(v.ToString()).TryGetValue(default(Instant), out var instant)) + { + return instant; + } + } + + return default(Instant); + } + + public static string GetString(this JsonObject obj, string key) + { + if (obj.TryGetValue(key, out var v)) + { + return v.ToString(); + } - return InstantPattern.General.Parse(value.ToString()).Value; + return string.Empty; } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs new file mode 100644 index 000000000..a90b97950 --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs @@ -0,0 +1,34 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using Newtonsoft.Json; +using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Json.Objects; + +namespace Squidex.Infrastructure.Json.Newtonsoft +{ + public sealed class EnvelopeHeadersConverter : JsonValueConverter + { + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var result = base.ReadJson(reader, objectType, existingValue, serializer); + + if (result is JsonObject obj) + { + return new EnvelopeHeaders(obj); + } + + return result; + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(EnvelopeHeaders); + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs index 5b31bb412..fdbf6f97b 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -8,13 +8,14 @@ using System; using System.Globalization; using Newtonsoft.Json; +using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json.Objects; #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator namespace Squidex.Infrastructure.Json.Newtonsoft { - public sealed class JsonValueConverter : JsonConverter + public class JsonValueConverter : JsonConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { @@ -161,7 +162,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft public override bool CanConvert(Type objectType) { - return typeof(IJsonValue).IsAssignableFrom(objectType); + return objectType != typeof(EnvelopeHeaders) && typeof(IJsonValue).IsAssignableFrom(objectType); } } } diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs b/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs index 00880e34a..e3d58f511 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonArray.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -23,28 +22,19 @@ namespace Squidex.Infrastructure.Json.Objects { } - public JsonArray(IList values) - : base(values) - { - } - - public JsonArray(params object[] values) + internal JsonArray(params object[] values) : base(values?.Select(JsonValue.Create).ToList()) { } protected override void InsertItem(int index, IJsonValue item) { - Guard.NotNull(item, nameof(item)); - - base.InsertItem(index, item); + base.InsertItem(index, item ?? JsonValue.Null); } protected override void SetItem(int index, IJsonValue item) { - Guard.NotNull(item, nameof(item)); - - base.SetItem(index, item); + base.SetItem(index, item ?? JsonValue.Null); } public override bool Equals(object obj) @@ -77,7 +67,7 @@ namespace Squidex.Infrastructure.Json.Objects public override int GetHashCode() { - var hashCode = 0; + var hashCode = 17; for (var i = 0; i < Count; i++) { @@ -94,7 +84,7 @@ namespace Squidex.Infrastructure.Json.Objects public override string ToString() { - return $"[{string.Join(", ", this)}]"; + return $"[{string.Join(", ", this.Select(x => x.ToJsonString()))}]"; } } } diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs index 0c29a39ca..7f1f6ceda 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs @@ -25,9 +25,8 @@ namespace Squidex.Infrastructure.Json.Objects set { Guard.NotNullOrEmpty(key, nameof(key)); - Guard.NotNull(value, nameof(value)); - inner[key] = value; + inner[key] = value ?? JsonValue.Null; } } @@ -68,10 +67,7 @@ namespace Squidex.Infrastructure.Json.Objects public JsonObject Add(string key, IJsonValue value) { - Guard.NotNullOrEmpty(key, nameof(key)); - Guard.NotNull(value, nameof(value)); - - inner[key] = value; + inner[key] = value ?? JsonValue.Null; return this; } diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs b/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs index 0689f7ecd..bea068163 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs @@ -47,14 +47,24 @@ namespace Squidex.Infrastructure.Json.Objects return value.GetHashCode(); } - public string ToJsonString() + public override string ToString() { - return Type == JsonValueType.String ? $"\"{value}\"" : ToString(); + if (Type == JsonValueType.Boolean) + { + return Equals(Value, true) ? "true" : "false"; + } + + return Value.ToString(); } - public override string ToString() + public string ToJsonString() { - return value.ToString(); + if (Type == JsonValueType.String) + { + return $"\"{value}\""; + } + + return ToString(); } } } diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs index 3fc3ae13e..5022aadab 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs @@ -8,16 +8,20 @@ using System; using NodaTime; +#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + namespace Squidex.Infrastructure.Json.Objects { public static class JsonValue { - public static readonly JsonScalar Empty = new JsonScalar(JsonValueType.String, string.Empty); + public static readonly IJsonValue Empty = new JsonScalar(JsonValueType.String, string.Empty); + + public static readonly IJsonValue True = new JsonScalar(JsonValueType.Boolean, true); + public static readonly IJsonValue False = new JsonScalar(JsonValueType.Boolean, false); - public static readonly JsonScalar True = new JsonScalar(JsonValueType.Boolean, true); - public static readonly JsonScalar False = new JsonScalar(JsonValueType.Boolean, false); + public static readonly IJsonValue Null = JsonNull.Null; - public static readonly JsonNull Null = JsonNull.Null; + public static readonly IJsonValue Zero = new JsonScalar(JsonValueType.Number, 0); public static JsonArray Array() { @@ -76,6 +80,11 @@ namespace Squidex.Infrastructure.Json.Objects { Guard.ValidNumber(value, nameof(value)); + if (value == 0) + { + return Zero; + } + return new JsonScalar(JsonValueType.Number, value); } diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 96c8e1dd1..0baee6338 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -49,6 +49,7 @@ namespace Squidex.Config.Domain new AppContributorsConverter(), new AppPatternsConverter(), new ClaimsPrincipalConverter(), + new EnvelopeHeadersConverter(), new InstantConverter(), new JsonValueConverter(), new LanguageConverter(), diff --git a/tests/RunCoverage.ps1 b/tests/RunCoverage.ps1 index a30fd78cb..ea27808f8 100644 --- a/tests/RunCoverage.ps1 +++ b/tests/RunCoverage.ps1 @@ -76,6 +76,6 @@ if ($all -Or $web) { -oldStyle } -&"$folderHome\.nuget\packages\ReportGenerator\4.0.4\tools\ReportGenerator.exe" ` +&"$folderHome\.nuget\packages\ReportGenerator\4.0.4\tools\net47\ReportGenerator.exe" ` -reports:"$folderWorking\$folderReports\*.xml" ` -targetdir:"$folderWorking\$folderReports\Output" \ No newline at end of file diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/PartitioningTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/PartitioningTests.cs index b82d85bcc..f16cdf930 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Model/PartitioningTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/PartitioningTests.cs @@ -68,37 +68,18 @@ namespace Squidex.Domain.Apps.Core.Model [Fact] public void Should_make_correct_equal_comparisons() { - var partitioning1a = new Partitioning("partitioning1"); - var partitioning1b = new Partitioning("partitioning1"); - var partitioning2a = new Partitioning("partitioning2"); + var partitioning1_a = new Partitioning("partitioning1"); + var partitioning1_b = new Partitioning("partitioning1"); - Assert.True(partitioning1a.Equals(partitioning1b)); + var partitioning2 = new Partitioning("partitioning2"); - Assert.False(partitioning1a.Equals(partitioning2a)); - } - - [Fact] - public void Should_make_correct_object_equal_comparisons() - { - object partitioning1a = new Partitioning("partitioning1"); - object partitioning1b = new Partitioning("partitioning1"); - object partitioning2a = new Partitioning("partitioning2"); - - Assert.True(partitioning1a.Equals(partitioning1b)); - - Assert.False(partitioning1a.Equals(partitioning2a)); - } - - [Fact] - public void Should_provide_correct_hash_codes() - { - var partitioning1a = new Partitioning("partitioning1"); - var partitioning1b = new Partitioning("partitioning1"); - var partitioning2a = new Partitioning("partitioning2"); - - Assert.Equal(partitioning1a.GetHashCode(), partitioning1b.GetHashCode()); + Assert.Equal(partitioning1_a, partitioning1_b); + Assert.Equal(partitioning1_a.GetHashCode(), partitioning1_b.GetHashCode()); + Assert.True(partitioning1_a.Equals((object)partitioning1_b)); - Assert.NotEqual(partitioning1a.GetHashCode(), partitioning2a.GetHashCode()); + Assert.NotEqual(partitioning1_a, partitioning2); + Assert.NotEqual(partitioning1_a.GetHashCode(), partitioning2.GetHashCode()); + Assert.False(partitioning1_a.Equals((object)partitioning2)); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index bafb2c6f8..a73b14f3c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -40,6 +40,7 @@ namespace Squidex.Domain.Apps.Core new AppContributorsConverter(), new AppPatternsConverter(), new ClaimsPrincipalConverter(), + new EnvelopeHeadersConverter(), new InstantConverter(), new JsonValueConverter(), new LanguageConverter(), diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs index 9d377646b..464585379 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeExtensionsTests.cs @@ -18,7 +18,7 @@ namespace Squidex.Infrastructure.EventSourcing [Fact] public void Should_set_and_get_timestamp() { - var timestamp = SystemClock.Instance.GetCurrentInstant(); + var timestamp = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); sut.SetTimestamp(timestamp); @@ -78,7 +78,7 @@ namespace Squidex.Infrastructure.EventSourcing sut.SetEventStreamNumber(eventStreamNumber); Assert.Equal(eventStreamNumber, sut.Headers.EventStreamNumber()); - Assert.Equal(eventStreamNumber, sut.Headers.GetInt64("EventStreamNumber")); + Assert.Equal(eventStreamNumber, sut.Headers.GetLong("EventStreamNumber")); } } } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs index b7842bec0..a65750d97 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs @@ -64,7 +64,10 @@ namespace Squidex.Infrastructure.EventSourcing.Grains consumerName = eventConsumer.GetType().Name; A.CallTo(() => store.WithSnapshots(A.Ignored, consumerName, A>.Ignored)) - .Invokes(new Action>((t, key, a) => apply = a)) + .Invokes(new Action>((t, key, a) => + { + apply = a; + })) .Returns(persistence); A.CallTo(() => eventStore.CreateSubscription(A.Ignored, A.Ignored, A.Ignored)) @@ -79,7 +82,8 @@ namespace Squidex.Infrastructure.EventSourcing.Grains A.CallTo(() => persistence.WriteSnapshotAsync(A.Ignored)) .Invokes(new Action(s => state = s)); - A.CallTo(() => formatter.Parse(eventData, true, null)).Returns(envelope); + A.CallTo(() => formatter.Parse(eventData, true, null)) + .Returns(envelope); sut = new MyEventConsumerGrain( x => eventConsumer, diff --git a/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs b/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs new file mode 100644 index 000000000..a5c00aae3 --- /dev/null +++ b/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs @@ -0,0 +1,321 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Squidex.Infrastructure.Json.Objects +{ + public class JsonObjectTests + { + [Fact] + public void Should_make_correct_object_equal_comparisons() + { + var obj_count1_key1_val1_a = JsonValue.Object().Add("key1", 1); + var obj_count1_key1_val1_b = JsonValue.Object().Add("key1", 1); + + var obj_count1_key1_val2 = JsonValue.Object().Add("key1", 2); + var obj_count1_key2_val1 = JsonValue.Object().Add("key2", 1); + var obj_count2_key1_val1 = JsonValue.Object().Add("key1", 1).Add("key2", 2); + + var number = JsonValue.Create(1); + + Assert.Equal(obj_count1_key1_val1_a, obj_count1_key1_val1_b); + Assert.Equal(obj_count1_key1_val1_a.GetHashCode(), obj_count1_key1_val1_b.GetHashCode()); + Assert.True(obj_count1_key1_val1_a.Equals((object)obj_count1_key1_val1_b)); + + Assert.NotEqual(obj_count1_key1_val1_a, obj_count1_key1_val2); + Assert.NotEqual(obj_count1_key1_val1_a.GetHashCode(), obj_count1_key1_val2.GetHashCode()); + Assert.False(obj_count1_key1_val1_a.Equals((object)obj_count1_key1_val2)); + + Assert.NotEqual(obj_count1_key1_val1_a, obj_count1_key2_val1); + Assert.NotEqual(obj_count1_key1_val1_a.GetHashCode(), obj_count1_key2_val1.GetHashCode()); + Assert.False(obj_count1_key1_val1_a.Equals((object)obj_count1_key2_val1)); + + Assert.NotEqual(obj_count1_key1_val1_a, obj_count2_key1_val1); + Assert.NotEqual(obj_count1_key1_val1_a.GetHashCode(), obj_count2_key1_val1.GetHashCode()); + Assert.False(obj_count1_key1_val1_a.Equals((object)obj_count2_key1_val1)); + + Assert.NotEqual(obj_count1_key1_val1_a, number); + Assert.NotEqual(obj_count1_key1_val1_a.GetHashCode(), number.GetHashCode()); + Assert.False(obj_count1_key1_val1_a.Equals((object)number)); + } + + [Fact] + public void Should_make_correct_array_equal_comparisons() + { + var array_count1_val1_a = JsonValue.Array(1); + var array_count1_val1_b = JsonValue.Array(1); + + var array_count1_val2 = JsonValue.Array(2); + var array_count2_val1 = JsonValue.Array(1, 2); + + var number = JsonValue.Create(1); + + Assert.Equal(array_count1_val1_a, array_count1_val1_b); + Assert.Equal(array_count1_val1_a.GetHashCode(), array_count1_val1_b.GetHashCode()); + Assert.True(array_count1_val1_a.Equals((object)array_count1_val1_b)); + + Assert.NotEqual(array_count1_val1_a, array_count1_val2); + Assert.NotEqual(array_count1_val1_a.GetHashCode(), array_count1_val2.GetHashCode()); + Assert.False(array_count1_val1_a.Equals((object)array_count1_val2)); + + Assert.NotEqual(array_count1_val1_a, array_count2_val1); + Assert.NotEqual(array_count1_val1_a.GetHashCode(), array_count2_val1.GetHashCode()); + Assert.False(array_count1_val1_a.Equals((object)array_count2_val1)); + + Assert.NotEqual(array_count1_val1_a, number); + Assert.NotEqual(array_count1_val1_a.GetHashCode(), number.GetHashCode()); + Assert.False(array_count1_val1_a.Equals((object)number)); + } + + [Fact] + public void Should_make_correct_array_scalar_comparisons() + { + var number_val1_a = JsonValue.Create(1); + var number_val1_b = JsonValue.Create(1); + + var number_val2 = JsonValue.Create(2); + + var boolean = JsonValue.True; + + Assert.Equal(number_val1_a, number_val1_b); + Assert.Equal(number_val1_a.GetHashCode(), number_val1_b.GetHashCode()); + Assert.True(number_val1_a.Equals((object)number_val1_b)); + + Assert.NotEqual(number_val1_a, number_val2); + Assert.NotEqual(number_val1_a.GetHashCode(), number_val2.GetHashCode()); + Assert.False(number_val1_a.Equals((object)number_val2)); + + Assert.NotEqual(number_val1_a, boolean); + Assert.NotEqual(number_val1_a.GetHashCode(), boolean.GetHashCode()); + Assert.False(number_val1_a.Equals((object)boolean)); + } + + [Fact] + public void Should_make_correct_null_comparisons() + { + var null_a = JsonValue.Null; + var null_b = JsonValue.Null; + + var boolean = JsonValue.True; + + Assert.Equal(null_a, null_b); + Assert.Equal(null_a.GetHashCode(), null_b.GetHashCode()); + Assert.True(null_a.Equals((object)null_b)); + + Assert.NotEqual(null_a, boolean); + Assert.NotEqual(null_a.GetHashCode(), boolean.GetHashCode()); + Assert.False(null_a.Equals((object)boolean)); + } + + [Fact] + public void Should_cache_null() + { + Assert.Same(JsonValue.Null, JsonValue.Create((string)null)); + } + + [Fact] + public void Should_cache_true() + { + Assert.Same(JsonValue.True, JsonValue.Create(true)); + } + + [Fact] + public void Should_cache_false() + { + Assert.Same(JsonValue.False, JsonValue.Create(false)); + } + + [Fact] + public void Should_cache_empty() + { + Assert.Same(JsonValue.Empty, JsonValue.Create(string.Empty)); + } + + [Fact] + public void Should_cache_zero() + { + Assert.Same(JsonValue.Zero, JsonValue.Create(0)); + } + + [Fact] + public void Should_create_array() + { + var json = JsonValue.Array(1, "2"); + + Assert.Equal("[1, \"2\"]", json.ToJsonString()); + Assert.Equal("[1, \"2\"]", json.ToString()); + } + + [Fact] + public void Should_create_object() + { + var json = JsonValue.Object().Add("key1", 1).Add("key2", "2"); + + Assert.Equal("{\"key1\":1, \"key2\":\"2\"}", json.ToJsonString()); + Assert.Equal("{\"key1\":1, \"key2\":\"2\"}", json.ToString()); + } + + [Fact] + public void Should_create_number() + { + var json = JsonValue.Create(123); + + Assert.Equal("123", json.ToJsonString()); + Assert.Equal("123", json.ToString()); + } + + [Fact] + public void Should_create_boolean_true() + { + var json = JsonValue.Create(true); + + Assert.Equal("true", json.ToJsonString()); + Assert.Equal("true", json.ToString()); + } + + [Fact] + public void Should_create_boolean_false() + { + var json = JsonValue.Create(false); + + Assert.Equal("false", json.ToJsonString()); + Assert.Equal("false", json.ToString()); + } + + [Fact] + public void Should_create_string() + { + var json = JsonValue.Create("hi"); + + Assert.Equal("\"hi\"", json.ToJsonString()); + Assert.Equal("hi", json.ToString()); + } + + [Fact] + public void Should_create_null() + { + var json = JsonValue.Create((object)null); + + Assert.Equal("null", json.ToJsonString()); + Assert.Equal("null", json.ToString()); + } + + [Fact] + public void Should_create_arrays_in_different_ways() + { + var numbers = new[] + { + JsonValue.Array(1.0f, 2.0f), + JsonValue.Array(JsonValue.Create(1.0f), JsonValue.Create(2.0f)) + }; + + Assert.Single(numbers.Distinct()); + Assert.Single(numbers.Select(x => x.GetHashCode()).Distinct()); + } + + [Fact] + public void Should_create_number_from_types() + { + var numbers = new[] + { + JsonValue.Create(1.0f), + JsonValue.Create(1.0), + JsonValue.Create(1L), + JsonValue.Create(1) + }; + + Assert.Single(numbers.Distinct()); + Assert.Single(numbers.Select(x => x.GetHashCode()).Distinct()); + } + + [Fact] + public void Should_create_null_when_adding_null_to_array() + { + var array = JsonValue.Array(); + + array.Add(null); + + Assert.Same(JsonValue.Null, array[0]); + } + + [Fact] + public void Should_create_null_when_replacing_to_null_in_array() + { + var array = JsonValue.Array(1); + + array[0] = null; + + Assert.Same(JsonValue.Null, array[0]); + } + + [Fact] + public void Should_create_null_when_adding_null_to_object() + { + var obj = JsonValue.Object(); + + obj.Add("key", null); + + Assert.Same(JsonValue.Null, obj["key"]); + } + + [Fact] + public void Should_create_null_when_replacing_to_null_object() + { + var obj = JsonValue.Object(); + + obj["key"] = null; + + Assert.Same(JsonValue.Null, obj["key"]); + } + + [Fact] + public void Should_remove_value_from_object() + { + var obj = JsonValue.Object().Add("key", 1); + + obj.Remove("key"); + + Assert.False(obj.TryGetValue("key", out _)); + Assert.False(obj.ContainsKey("key")); + } + + [Fact] + public void Should_clear_values_from_object() + { + var obj = JsonValue.Object().Add("key", 1); + + obj.Clear(); + + Assert.False(obj.TryGetValue("key", out _)); + Assert.False(obj.ContainsKey("key")); + } + + [Fact] + public void Should_provide_collection_values_from_object() + { + var obj = JsonValue.Object().Add("11", "44").Add("22", "88"); + + var kvps = new[] + { + new KeyValuePair("11", JsonValue.Create("44")), + new KeyValuePair("22", JsonValue.Create("88")) + }; + + Assert.Equal(2, obj.Count); + + Assert.Equal(new[] { "11", "22" }, obj.Keys); + Assert.Equal(new[] { "44", "88" }, obj.Values.Select(x => x.ToString())); + + Assert.Equal(kvps, obj.ToArray()); + Assert.Equal(kvps, ((IEnumerable)obj).OfType>().ToArray()); + } + } +} diff --git a/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs b/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs index bdf62cae4..44a09138a 100644 --- a/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs +++ b/tests/Squidex.Infrastructure.Tests/NamedIdTests.cs @@ -40,49 +40,23 @@ namespace Squidex.Infrastructure var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); - var token1a = NamedId.Of(id1, "my-name1"); - var token1b = NamedId.Of(id1, "my-name1"); - var token1c = NamedId.Of(id1, "my-name2"); - var token2a = NamedId.Of(id2, "my-name1"); + var named_id1_name1_a = NamedId.Of(id1, "name1"); + var named_id1_name1_b = NamedId.Of(id1, "name1"); - Assert.True(token1a.Equals(token1b)); + var named_id2_name1 = NamedId.Of(id2, "name1"); + var named_id1_name2 = NamedId.Of(id1, "name2"); - Assert.False(token1a.Equals(token2a)); - Assert.False(token1a.Equals(token1c)); - } - - [Fact] - public void Should_make_correct_object_equal_comparisons() - { - var id1 = Guid.NewGuid(); - var id2 = Guid.NewGuid(); - - object token1a = NamedId.Of(id1, "my-name1"); - object token1b = NamedId.Of(id1, "my-name1"); - object token1c = NamedId.Of(id1, "my-name2"); - object token2a = NamedId.Of(id2, "my-name1"); - - Assert.True(token1a.Equals(token1b)); - - Assert.False(token1a.Equals(token2a)); - Assert.False(token1a.Equals(token1c)); - } - - [Fact] - public void Should_provide_correct_hash_codes() - { - var id1 = Guid.NewGuid(); - var id2 = Guid.NewGuid(); - - object token1a = NamedId.Of(id1, "my-name1"); - object token1b = NamedId.Of(id1, "my-name1"); - object token1c = NamedId.Of(id1, "my-name2"); - object token2a = NamedId.Of(id2, "my-name1"); + Assert.Equal(named_id1_name1_a, named_id1_name1_b); + Assert.Equal(named_id1_name1_a.GetHashCode(), named_id1_name1_b.GetHashCode()); + Assert.True(named_id1_name1_a.Equals((object)named_id1_name1_b)); - Assert.Equal(token1a.GetHashCode(), token1b.GetHashCode()); + Assert.NotEqual(named_id1_name1_a, named_id2_name1); + Assert.NotEqual(named_id1_name1_a.GetHashCode(), named_id2_name1.GetHashCode()); + Assert.False(named_id1_name1_a.Equals((object)named_id2_name1)); - Assert.NotEqual(token1a.GetHashCode(), token2a.GetHashCode()); - Assert.NotEqual(token1a.GetHashCode(), token1c.GetHashCode()); + Assert.NotEqual(named_id1_name1_a, named_id1_name2); + Assert.NotEqual(named_id1_name1_a.GetHashCode(), named_id1_name2.GetHashCode()); + Assert.False(named_id1_name1_a.Equals((object)named_id1_name2)); } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs b/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs index 09620ee0f..b7ddf5d99 100644 --- a/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs +++ b/tests/Squidex.Infrastructure.Tests/RefTokenTests.cs @@ -70,39 +70,23 @@ namespace Squidex.Infrastructure [Fact] public void Should_make_correct_equal_comparisons() { - var token1a = RefToken.Parse("client:client1"); - var token1b = RefToken.Parse("client:client1"); - var token2a = RefToken.Parse("client:client2"); + var token_type1_id1_a = RefToken.Parse("type1:client1"); + var token_type1_id1_b = RefToken.Parse("type1:client1"); - Assert.True(token1a.Equals(token1b)); + var token_type2_id1 = RefToken.Parse("type2:client1"); + var token_type1_id2 = RefToken.Parse("type1:client2"); - Assert.False(token1a.Equals(token2a)); - } - - [Fact] - public void Should_make_correct_object_equal_comparisons() - { - object token1a = RefToken.Parse("client:client1"); - object token1b = RefToken.Parse("client:client1"); - object token2a = RefToken.Parse("client:client2"); - - Assert.True(token1a.Equals(token1b)); - - Assert.False(token1a.Equals(token2a)); - Assert.False(token1b.Equals(token2a)); - } - - [Fact] - public void Should_provide_correct_hash_codes() - { - var token1a = RefToken.Parse("client:client1"); - var token1b = RefToken.Parse("client:client1"); - var token2a = RefToken.Parse("client:client2"); + Assert.Equal(token_type1_id1_a, token_type1_id1_b); + Assert.Equal(token_type1_id1_a.GetHashCode(), token_type1_id1_b.GetHashCode()); + Assert.True(token_type1_id1_a.Equals((object)token_type1_id1_b)); - Assert.Equal(token1a.GetHashCode(), token1b.GetHashCode()); + Assert.NotEqual(token_type1_id1_a, token_type2_id1); + Assert.NotEqual(token_type1_id1_a.GetHashCode(), token_type2_id1.GetHashCode()); + Assert.False(token_type1_id1_a.Equals((object)token_type2_id1)); - Assert.NotEqual(token1a.GetHashCode(), token2a.GetHashCode()); - Assert.NotEqual(token1b.GetHashCode(), token2a.GetHashCode()); + Assert.NotEqual(token_type1_id1_a, token_type1_id2); + Assert.NotEqual(token_type1_id1_a.GetHashCode(), token_type1_id2.GetHashCode()); + Assert.False(token_type1_id1_a.Equals((object)token_type1_id2)); } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs index 0eee70a27..5bb1b818a 100644 --- a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs +++ b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs @@ -28,6 +28,7 @@ namespace Squidex.Infrastructure.TestHelpers new ClaimsPrincipalConverter(), new InstantConverter(), new JsonValueConverter(), + new EnvelopeHeadersConverter(), new LanguageConverter(), new NamedGuidIdConverter(), new NamedLongIdConverter(), From dbc4a932dad9401caa0b9adeaada02c1a32134c2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 27 Nov 2018 15:08:18 +0100 Subject: [PATCH 16/33] Backup fixes. --- .../Backup/BackupReader.cs | 61 ++++----- .../Backup/BackupVersion.cs | 15 +++ .../Backup/BackupWriter.cs | 13 +- .../Backup/GuidMapper.cs | 2 +- .../Backup/Model/CompatibleStoredEvent.cs | 116 ++++++++++++++++++ .../DefaultEventDataFormatter.cs | 14 +-- .../Queries/FilterValue.cs | 20 ++- src/Squidex/appsettings.json | 2 +- .../ConvertContent/ContentConversionTests.cs | 4 +- .../ConvertContent/FieldConvertersTests.cs | 32 ++--- .../HandleRules/RuleServiceTests.cs | 2 +- .../Scripting/ContentDataObjectTests.cs | 6 +- .../Backup/BackupReaderWriterTests.cs | 25 ++-- .../Squidex.Domain.Apps.Entities.Tests.csproj | 5 - 14 files changed, 221 insertions(+), 96 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Entities/Backup/BackupVersion.cs create mode 100644 src/Squidex.Domain.Apps.Entities/Backup/Model/CompatibleStoredEvent.cs diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs index 2c3560334..660ca8627 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs @@ -8,13 +8,14 @@ using System; using System.IO; using System.IO.Compression; +using System.Linq; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Entities.Backup.Helpers; +using Squidex.Domain.Apps.Entities.Backup.Model; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; +using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.States; #pragma warning disable SA1401 // Fields must be private @@ -29,36 +30,6 @@ namespace Squidex.Domain.Apps.Entities.Backup private int readEvents; private int readAttachments; - private sealed class ComaptibleStoredEvent - { - [JsonProperty] - public string StreamName; - - [JsonProperty] - public string EventPosition; - - [JsonProperty] - public long EventStreamNumber; - - [JsonProperty] - public CompatibleEventData Data; - } - - private sealed class CompatibleEventData - { - [JsonProperty] - public string Type; - - [JsonProperty] - public JRaw Payload; - - [JsonProperty] - public EnvelopeHeaders Headers; - - [JsonProperty] - public EnvelopeHeaders Metadata; - } - public int ReadEvents { get { return readEvents; } @@ -151,20 +122,34 @@ namespace Squidex.Domain.Apps.Entities.Backup using (var stream = eventEntry.Open()) { - var storedEvent = serializer.Deserialize(stream); - - var src = storedEvent.Data; + var (streamName, data) = serializer.Deserialize(stream).ToEvent(); - var data = new EventData(src.Type, src.Headers ?? src.Metadata, src.Payload.ToString()); + MapHeaders(data); - var eventStream = streamNameResolver.WithNewId(storedEvent.StreamName, guidMapper.NewGuidOrNull); + var eventStream = streamNameResolver.WithNewId(streamName, guidMapper.NewGuidOrNull); var eventEnvelope = formatter.Parse(data, true, guidMapper.NewGuidOrValue); - await handler((eventStream, eventEnvelope)); + await handler((streamName, eventEnvelope)); } readEvents++; } } + + private void MapHeaders(EventData data) + { + foreach (var kvp in data.Headers.ToList()) + { + if (kvp.Value.Type == JsonValueType.String) + { + var newGuid = guidMapper.NewGuidOrNull(kvp.Value.ToString()); + + if (newGuid != null) + { + data.Headers.Add(kvp.Key, newGuid); + } + } + } + } } } diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupVersion.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupVersion.cs new file mode 100644 index 000000000..e6cddcd7d --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupVersion.cs @@ -0,0 +1,15 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Domain.Apps.Entities.Backup +{ + public enum BackupVersion + { + V2, + V1 + } +} diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs index 98363cb77..0f3033bcb 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupWriter.cs @@ -10,6 +10,7 @@ using System.IO; using System.IO.Compression; using System.Threading.Tasks; using Squidex.Domain.Apps.Entities.Backup.Helpers; +using Squidex.Domain.Apps.Entities.Backup.Model; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; @@ -21,6 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Backup { private readonly ZipArchive archive; private readonly IJsonSerializer serializer; + private readonly Func converter; private int writtenEvents; private int writtenAttachments; @@ -34,12 +36,17 @@ namespace Squidex.Domain.Apps.Entities.Backup get { return writtenAttachments; } } - public BackupWriter(IJsonSerializer serializer, Stream stream, bool keepOpen = false) + public BackupWriter(IJsonSerializer serializer, Stream stream, bool keepOpen = false, BackupVersion version = BackupVersion.V2) { Guard.NotNull(serializer, nameof(serializer)); this.serializer = serializer; + converter = + version == BackupVersion.V1 ? + new Func(CompatibleStoredEvent.V1) : + new Func(CompatibleStoredEvent.V2); + archive = new ZipArchive(stream, ZipArchiveMode.Create, keepOpen); } @@ -90,7 +97,9 @@ namespace Squidex.Domain.Apps.Entities.Backup using (var stream = eventEntry.Open()) { - serializer.Serialize(storedEvent, stream); + var @event = converter(storedEvent); + + serializer.Serialize(@event, stream); } writtenEvents++; diff --git a/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs b/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs index a2ac8973d..e4b5aceb1 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs @@ -19,7 +19,7 @@ namespace Squidex.Domain.Apps.Entities.Backup public Guid OldGuid(Guid newGuid) { - return newToOldGuid.GetOrDefault(newGuid); + return newToOldGuid.GetOrCreate(newGuid, x => x); } public string NewGuidOrNull(string value) diff --git a/src/Squidex.Domain.Apps.Entities/Backup/Model/CompatibleStoredEvent.cs b/src/Squidex.Domain.Apps.Entities/Backup/Model/CompatibleStoredEvent.cs new file mode 100644 index 000000000..ac84f1bb7 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities/Backup/Model/CompatibleStoredEvent.cs @@ -0,0 +1,116 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Squidex.Infrastructure.EventSourcing; + +#pragma warning disable SA1401 // Fields must be private + +namespace Squidex.Domain.Apps.Entities.Backup.Model +{ + public sealed class CompatibleStoredEvent + { + [JsonProperty("n")] + public NewEvent NewEvent; + + [JsonProperty] + public string StreamName; + + [JsonProperty] + public string EventPosition; + + [JsonProperty] + public long EventStreamNumber; + + [JsonProperty] + public CompatibleEventData Data; + + public static CompatibleStoredEvent V1(StoredEvent stored) + { + return new CompatibleStoredEvent + { + Data = CompatibleEventData.V1(stored.Data), + EventPosition = stored.EventPosition, + EventStreamNumber = stored.EventStreamNumber, + StreamName = stored.StreamName + }; + } + + public static CompatibleStoredEvent V2(StoredEvent stored) + { + return new CompatibleStoredEvent { NewEvent = NewEvent.V2(stored) }; + } + + public (string Stream, EventData Data) ToEvent() + { + if (NewEvent != null) + { + return NewEvent.ToEvent(); + } + else + { + return (StreamName, Data.ToData()); + } + } + } + + public sealed class CompatibleEventData + { + [JsonProperty] + public string Type; + + [JsonProperty] + public JRaw Payload; + + [JsonProperty] + public EnvelopeHeaders Metadata; + + public static CompatibleEventData V1(EventData data) + { + var payload = new JRaw(data.Payload); + + return new CompatibleEventData { Type = data.Type, Payload = payload, Metadata = data.Headers }; + } + + public EventData ToData() + { + return new EventData(Type, Metadata, Payload.ToString()); + } + } + + public sealed class NewEvent + { + [JsonProperty("t")] + public string EventType; + + [JsonProperty("s")] + public string StreamName; + + [JsonProperty("p")] + public string EventPayload; + + [JsonProperty("h")] + public EnvelopeHeaders EventHeaders; + + public static NewEvent V2(StoredEvent stored) + { + return new NewEvent + { + EventType = stored.Data.Type, + EventHeaders = stored.Data.Headers, + EventPayload = stored.Data.Payload, + StreamName = stored.StreamName + }; + } + + public (string Stream, EventData Data) ToEvent() + { + return (StreamName, new EventData(EventType, EventHeaders, EventPayload)); + } + } +} diff --git a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs index 247f6a918..d8e27f511 100644 --- a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs @@ -10,7 +10,7 @@ using Squidex.Infrastructure.Json; namespace Squidex.Infrastructure.EventSourcing { - public class DefaultEventDataFormatter : IEventDataFormatter + public sealed class DefaultEventDataFormatter : IEventDataFormatter { private readonly IJsonSerializer serializer; private readonly TypeNameRegistry typeNameRegistry; @@ -28,14 +28,14 @@ namespace Squidex.Infrastructure.EventSourcing public Envelope Parse(EventData eventData, bool migrate = true, Func stringConverter = null) { var payloadType = typeNameRegistry.GetType(eventData.Type); - var payload = serializer.Deserialize(eventData.Payload, payloadType, stringConverter); + var payloadObj = serializer.Deserialize(eventData.Payload, payloadType, stringConverter); - if (migrate && payload is IMigratedEvent migratedEvent) + if (migrate && payloadObj is IMigratedEvent migratedEvent) { - payload = migratedEvent.Migrate(); + payloadObj = migratedEvent.Migrate(); } - var envelope = new Envelope(payload, eventData.Headers); + var envelope = new Envelope(payloadObj, eventData.Headers); return envelope; } @@ -50,11 +50,11 @@ namespace Squidex.Infrastructure.EventSourcing } var payloadType = typeNameRegistry.GetName(eventPayload.GetType()); - var payload = serializer.Serialize(envelope.Payload); + var payloadJson = serializer.Serialize(envelope.Payload); envelope.SetCommitId(commitId); - return new EventData(payloadType, envelope.Headers, payload); + return new EventData(payloadType, envelope.Headers, payloadJson); } } } diff --git a/src/Squidex.Infrastructure/Queries/FilterValue.cs b/src/Squidex.Infrastructure/Queries/FilterValue.cs index d340a4c88..7c07827f8 100644 --- a/src/Squidex.Infrastructure/Queries/FilterValue.cs +++ b/src/Squidex.Infrastructure/Queries/FilterValue.cs @@ -8,6 +8,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.Linq; using NodaTime; @@ -126,26 +127,23 @@ namespace Squidex.Infrastructure.Queries { return $"[{string.Join(", ", list.OfType().Select(ToString).ToArray())}]"; } - else - { - return ToString(Value); - } + + return ToString(Value); } private string ToString(object value) { - if (ValueType == FilterValueType.String) - { - return $"'{value.ToString().Replace("'", "\\'")}'"; - } - else if (value == null) + if (value == null) { return "null"; } - else + + if (value is string s) { - return value.ToString(); + return $"'{s.Replace("'", "\\'")}'"; } + + return string.Format(CultureInfo.InvariantCulture, "{0}", value); } } } diff --git a/src/Squidex/appsettings.json b/src/Squidex/appsettings.json index 2907858cd..0b1d8de1a 100644 --- a/src/Squidex/appsettings.json +++ b/src/Squidex/appsettings.json @@ -253,7 +253,7 @@ "identity": { /* - * Enable password auth. Set this to false if you want to disable local login, leaving only 3rd party login options. + * Enable password auth. Set this to false if you want to disable local login, leaving only 3rd party login options. */ "allowPasswordAuth": true, /* diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs index 43700a84c..a19acee27 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs @@ -174,7 +174,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new NamedContentData() .AddField("field1", new ContentFieldData() - .AddValue("en", new JsonArray("hello", "loved"))) + .AddValue("en", JsonValue.Array("hello", "loved"))) .AddField("field2", new ContentFieldData() .AddValue("iv", "world")); @@ -191,7 +191,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent new NamedContentData() .AddField("field1", new ContentFieldData() - .AddValue("en", new JsonArray(JsonValue.Object().Add("p1", "hello")))) + .AddValue("en", JsonValue.Array(JsonValue.Object().Add("p1", "hello")))) .AddField("field2", new ContentFieldData() .AddValue("iv", "world")); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs index f9b90bce8..278e2bb3b 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/FieldConvertersTests.cs @@ -73,7 +73,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("field1", 100) .Add("field2", 200) @@ -84,7 +84,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("1", 100))); @@ -97,7 +97,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("field1", 100) .Add("field2", 200) @@ -108,7 +108,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("field1", 100))); @@ -121,7 +121,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("1", 100) .Add("2", 200) @@ -132,7 +132,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("1", 100))); @@ -145,7 +145,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var input = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("1", 100) .Add("2", 200) @@ -156,7 +156,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent var expected = new ContentFieldData() .AddValue("iv", - new JsonArray( + JsonValue.Array( JsonValue.Object() .Add("field1", 100))); @@ -422,11 +422,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JsonArray("1", "2")); + .AddValue("iv", JsonValue.Array("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JsonArray("url/to/1", "url/to/2")); + .AddValue("iv", JsonValue.Array("url/to/1", "url/to/2")); var rtesult = FieldConverters.ResolveAssetUrls(new HashSet(new[] { "1" }), assetUrlGenerator)(source, assetsField); @@ -438,11 +438,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JsonArray("1", "2")); + .AddValue("iv", JsonValue.Array("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JsonArray("url/to/1", "url/to/2")); + .AddValue("iv", JsonValue.Array("url/to/1", "url/to/2")); var rtesult = FieldConverters.ResolveAssetUrls(new HashSet(new[] { "*" }), assetUrlGenerator)(source, assetsField); @@ -454,11 +454,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JsonArray("1", "2")); + .AddValue("iv", JsonValue.Array("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JsonArray("1", "2")); + .AddValue("iv", JsonValue.Array("1", "2")); var rtesult = FieldConverters.ResolveAssetUrls(new HashSet(new[] { "2" }), assetUrlGenerator)(source, assetsField); @@ -470,11 +470,11 @@ namespace Squidex.Domain.Apps.Core.Operations.ConvertContent { var source = new ContentFieldData() - .AddValue("iv", new JsonArray("1", "2")); + .AddValue("iv", JsonValue.Array("1", "2")); var expected = new ContentFieldData() - .AddValue("iv", new JsonArray("1", "2")); + .AddValue("iv", JsonValue.Array("1", "2")); var rtesult = FieldConverters.ResolveAssetUrls(null, assetUrlGenerator)(source, assetsField); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs index 7a36445b2..90ce03bb3 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleServiceTests.cs @@ -171,7 +171,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules { var @event = new ContentCreated { SchemaId = NamedId.Of(Guid.NewGuid(), "my-schema"), AppId = NamedId.Of(Guid.NewGuid(), "my-event") }; - var now = SystemClock.Instance.GetCurrentInstant(); + var now = Instant.FromUnixTimeSeconds(SystemClock.Instance.GetCurrentInstant().ToUnixTimeSeconds()); var ruleConfig = ValidRule(); var ruleEnvelope = Envelope.Create(@event); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs index 488c32b9f..271953f3c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs @@ -155,13 +155,13 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting new NamedContentData() .AddField("number", new ContentFieldData() - .AddValue("iv", new JsonArray(1.0, 2.0))); + .AddValue("iv", JsonValue.Array(1.0, 2.0))); var expected = new NamedContentData() .AddField("number", new ContentFieldData() - .AddValue("iv", new JsonArray(1.0, 4.0, 5.0))); + .AddValue("iv", JsonValue.Array(1.0, 4.0, 5.0))); var result = ExecuteScript(original, @"data.number.iv = [data.number.iv[0], data.number.iv[1] + 2, 5]"); @@ -278,7 +278,7 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting new NamedContentData() .AddField("obj", new ContentFieldData() - .AddValue("iv", new JsonArray())); + .AddValue("iv", JsonValue.Array())); ExecuteScript(original, "data.obj.iv[0] = 1"); } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs index 1179039aa..7f31050f4 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs @@ -47,8 +47,10 @@ namespace Squidex.Domain.Apps.Entities.Backup .ReturnsLazily(new Func, string>((stream, idGenerator) => stream + "^2")); } - [Fact] - public async Task Should_write_and_read_events() + [Theory] + [InlineData(BackupVersion.V1)] + [InlineData(BackupVersion.V2)] + public async Task Should_write_and_read_events_to_backup(BackupVersion version) { var stream = new MemoryStream(); @@ -83,13 +85,13 @@ namespace Squidex.Domain.Apps.Entities.Backup var envelope = Envelope.Create(@event); envelope.Headers.Add(RandomGuid().ToString(), i); - envelope.Headers.Add("Id", RandomGuid()); + envelope.Headers.Add("Id", RandomGuid().ToString()); envelope.Headers.Add("Index", i); sourceEvents.Add(($"My-{RandomGuid()}", envelope)); } - using (var writer = new BackupWriter(serializer, stream, true)) + using (var writer = new BackupWriter(serializer, stream, true, version)) { foreach (var @event in sourceEvents) { @@ -149,13 +151,18 @@ namespace Squidex.Domain.Apps.Entities.Backup for (var i = 0; i < targetEvents.Count; i++) { - var lhs = targetEvents[i].Event.To(); - var rhs = sourceEvents[i].Event.To(); + var tgt = targetEvents[i].Event.To(); + var src = sourceEvents[i].Event.To(); - Assert.Equal(rhs.Payload.GuidRaw, reader.OldGuid(lhs.Payload.GuidRaw)); - Assert.Equal(rhs.Payload.GuidNamed.Id, reader.OldGuid(lhs.Payload.GuidNamed.Id)); + Assert.Equal(src.Payload.GuidRaw, reader.OldGuid(tgt.Payload.GuidRaw)); + Assert.Equal(src.Payload.GuidNamed.Id, reader.OldGuid(tgt.Payload.GuidNamed.Id)); - Assert.Equal(rhs.Headers.GetGuid("Id"), reader.OldGuid(lhs.Headers.GetGuid("Id"))); + Assert.NotEqual(src.Payload.GuidRaw, tgt.Payload.GuidRaw); + Assert.NotEqual(src.Payload.GuidNamed.Id, tgt.Payload.GuidNamed.Id); + + Assert.Equal(src.Headers.GetGuid("Id"), reader.OldGuid(tgt.Headers.GetGuid("Id"))); + + Assert.NotEqual(src.Headers.GetGuid("Id"), tgt.Headers.GetGuid("Id")); } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj b/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj index 79ec34354..a557808d2 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Squidex.Domain.Apps.Entities.Tests.csproj @@ -5,11 +5,6 @@ 2.1.1 Squidex.Domain.Apps.Entities - - - - - From 265fa0aadb3531762392c8303c99d513258472ba Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 29 Nov 2018 19:17:09 +0100 Subject: [PATCH 17/33] Performance optimizations. --- .../Backup/GuidMapper.cs | 29 ++++++---- .../Json/Newtonsoft/JsonValueConverter.cs | 3 +- .../Json/Newtonsoft/NamedGuidIdConverter.cs | 12 ++--- .../Json/Newtonsoft/NamedLongIdConverter.cs | 12 ++--- .../Json/Newtonsoft/NamedStringIdConverter.cs | 18 ++++--- .../Json/Newtonsoft/RefTokenConverter.cs | 7 ++- .../Json/Objects/JsonObject.cs | 2 +- src/Squidex.Infrastructure/NamedId{T}.cs | 53 +++++++++++++++---- src/Squidex.Infrastructure/RefToken.cs | 44 +++++++++------ .../States/DefaultStreamNameResolver.cs | 2 +- .../StringExtensions.cs | 6 +-- .../Config/Domain/SerializationServices.cs | 1 - .../TestUtils.cs | 1 - .../Backup/BackupReaderWriterTests.cs | 26 ++++----- ...HeaderTests.cs => EnvelopeHeadersTests.cs} | 19 +++++-- .../Json/Objects/JsonObjectTests.cs | 44 +++++++++++++-- .../TestHelpers/JsonHelper.cs | 3 +- .../Migrations/ConvertEventStore.cs | 1 - 18 files changed, 194 insertions(+), 89 deletions(-) rename tests/Squidex.Infrastructure.Tests/EventSourcing/{EnvelopeHeaderTests.cs => EnvelopeHeadersTests.cs} (71%) diff --git a/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs b/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs index e4b5aceb1..4b1916655 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/GuidMapper.cs @@ -16,6 +16,7 @@ namespace Squidex.Domain.Apps.Entities.Backup private static readonly int GuidLength = Guid.Empty.ToString().Length; private readonly Dictionary oldToNewGuid = new Dictionary(); private readonly Dictionary newToOldGuid = new Dictionary(); + private readonly Dictionary strings = new Dictionary(); public Guid OldGuid(Guid newGuid) { @@ -44,39 +45,49 @@ namespace Squidex.Domain.Apps.Entities.Backup private bool TryGenerateNewGuidString(string value, out string result) { - result = null; - if (value.Length == GuidLength) { + if (strings.TryGetValue(value, out result)) + { + return true; + } + if (Guid.TryParse(value, out var guid)) { var newGuid = GenerateNewGuid(guid); - result = newGuid.ToString(); + strings[value] = result = newGuid.ToString(); return true; } } + result = null; + return false; } private bool TryGenerateNewNamedId(string value, out string result) { - result = null; - - if (value.Length > GuidLength && value[GuidLength] == ',') + if (value.Length > GuidLength) { - if (Guid.TryParse(value.Substring(0, GuidLength), out var guid)) + if (strings.TryGetValue(value, out result)) { - var newGuid = GenerateNewGuid(guid); + return true; + } - result = newGuid + value.Substring(GuidLength); + if (NamedId.TryParse(value, Guid.TryParse, out var namedId)) + { + var newGuid = GenerateNewGuid(namedId.Id); + + strings[value] = result = new NamedId(newGuid, namedId.Name).ToString(); return true; } } + result = null; + return false; } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs index fdbf6f97b..749cc9586 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -8,7 +8,6 @@ using System; using System.Globalization; using Newtonsoft.Json; -using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json.Objects; #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator @@ -162,7 +161,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft public override bool CanConvert(Type objectType) { - return objectType != typeof(EnvelopeHeaders) && typeof(IJsonValue).IsAssignableFrom(objectType); + return typeof(IJsonValue).IsAssignableFrom(objectType); } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs index f40e50481..f1b141060 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs @@ -14,7 +14,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft { protected override void WriteValue(JsonWriter writer, NamedId value, JsonSerializer serializer) { - writer.WriteValue($"{value.Id},{value.Name}"); + writer.WriteValue(value.ToString()); } protected override NamedId ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) @@ -24,14 +24,12 @@ namespace Squidex.Infrastructure.Json.Newtonsoft throw new JsonException($"Expected String, but got {reader.TokenType}."); } - try + if (!NamedId.TryParse(reader.Value.ToString(), Guid.TryParse, out var result)) { - return NamedId.Parse(reader.Value.ToString(), Guid.TryParse); - } - catch (ArgumentException ex) - { - throw new JsonException(ex.Message); + throw new JsonException("Named id must have more than 2 parts divided by commata."); } + + return result; } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs index b90415b71..d984e572b 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs @@ -14,7 +14,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft { protected override void WriteValue(JsonWriter writer, NamedId value, JsonSerializer serializer) { - writer.WriteValue($"{value.Id},{value.Name}"); + writer.WriteValue(value.ToString()); } protected override NamedId ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) @@ -24,14 +24,12 @@ namespace Squidex.Infrastructure.Json.Newtonsoft throw new JsonException($"Expected String, but got {reader.TokenType}."); } - try + if (!NamedId.TryParse(reader.Value.ToString(), long.TryParse, out var result)) { - return NamedId.Parse(reader.Value.ToString(), long.TryParse); - } - catch (ArgumentException ex) - { - throw new JsonException(ex.Message); + throw new JsonException("Named id must have at least 2 parts divided by commata."); } + + return result; } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs index 78f39fb1f..573cbaa57 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Linq; using Newtonsoft.Json; namespace Squidex.Infrastructure.Json.Newtonsoft @@ -15,7 +14,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft { protected override void WriteValue(JsonWriter writer, NamedId value, JsonSerializer serializer) { - writer.WriteValue($"{value.Id},{value.Name}"); + writer.WriteValue(value.ToString()); } protected override NamedId ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) @@ -25,14 +24,19 @@ namespace Squidex.Infrastructure.Json.Newtonsoft throw new JsonException($"Expected String, but got {reader.TokenType}."); } - var parts = reader.Value.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - if (parts.Length < 2) + if (!NamedId.TryParse(reader.Value.ToString(), ParseString, out var result)) { - throw new JsonException("Named id must have more than 2 parts divided by colon."); + throw new JsonException("Named id must have at least 2 parts divided by commata."); } - return NamedId.Of(parts[0], string.Join(",", parts.Skip(1))); + return result; + } + + private static bool ParseString(string value, out string result) + { + result = value; + + return true; } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs index 9f12baacc..988f3ff95 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/RefTokenConverter.cs @@ -24,7 +24,12 @@ namespace Squidex.Infrastructure.Json.Newtonsoft throw new JsonException($"Expected String, but got {reader.TokenType}."); } - return RefToken.Parse(reader.Value.ToString()); + if (!RefToken.TryParse(reader.Value.ToString(), out var result)) + { + throw new JsonException("Named id must have at least 2 parts divided by colon."); + } + + return result; } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs index 7f1f6ceda..c4974ce47 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonObject.cs @@ -50,7 +50,7 @@ namespace Squidex.Infrastructure.Json.Objects get { return JsonValueType.Array; } } - public JsonObject() + internal JsonObject() { inner = new Dictionary(); } diff --git a/src/Squidex.Infrastructure/NamedId{T}.cs b/src/Squidex.Infrastructure/NamedId{T}.cs index e8f99f6d4..eeeab8ab9 100644 --- a/src/Squidex.Infrastructure/NamedId{T}.cs +++ b/src/Squidex.Infrastructure/NamedId{T}.cs @@ -6,7 +6,8 @@ // ========================================================================== using System; -using System.Linq; + +#pragma warning disable RECS0108 // Warns about static fields in generic types namespace Squidex.Infrastructure { @@ -14,6 +15,8 @@ namespace Squidex.Infrastructure public sealed class NamedId : IEquatable> { + private static readonly int GuidLength = Guid.Empty.ToString().Length; + public T Id { get; } public string Name { get; } @@ -48,23 +51,51 @@ namespace Squidex.Infrastructure return (Id.GetHashCode() * 397) ^ Name.GetHashCode(); } - public static NamedId Parse(string value, Parser parser) + public static bool TryParse(string value, Parser parser, out NamedId result) { - Guard.NotNull(value, nameof(value)); - - var parts = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - if (parts.Length < 2) + if (value != null) { - throw new ArgumentException("Named id must have more than 2 parts divided by commata."); + if (typeof(T) == typeof(Guid)) + { + if (value.Length > GuidLength + 1 && value[GuidLength] == ',') + { + if (parser(value.Substring(0, GuidLength), out var id)) + { + result = new NamedId(id, value.Substring(GuidLength + 1)); + + return true; + } + } + } + else + { + var index = value.IndexOf(','); + + if (index > 0 && index < value.Length - 1) + { + if (parser(value.Substring(0, index), out var id)) + { + result = new NamedId(id, value.Substring(index + 1)); + + return true; + } + } + } } - if (!parser(parts[0], out var id)) + result = null; + + return false; + } + + public static NamedId Parse(string value, Parser parser) + { + if (!TryParse(value, parser, out var result)) { - throw new ArgumentException("Named id must be a valid guid."); + throw new ArgumentException("Named id must have at least 2 parts divided by commata.", nameof(value)); } - return new NamedId(id, string.Join(",", parts.Skip(1))); + return result; } } } diff --git a/src/Squidex.Infrastructure/RefToken.cs b/src/Squidex.Infrastructure/RefToken.cs index d9298b6aa..5d0c1d215 100644 --- a/src/Squidex.Infrastructure/RefToken.cs +++ b/src/Squidex.Infrastructure/RefToken.cs @@ -6,7 +6,6 @@ // ========================================================================== using System; -using System.Linq; namespace Squidex.Infrastructure { @@ -26,20 +25,6 @@ namespace Squidex.Infrastructure Identifier = identifier; } - public static RefToken Parse(string input) - { - Guard.NotNullOrEmpty(input, nameof(input)); - - var parts = input.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries); - - if (parts.Length < 2) - { - throw new ArgumentException("Input must have more than 2 parts divided by colon.", nameof(input)); - } - - return new RefToken(parts[0], string.Join(":", parts.Skip(1))); - } - public override string ToString() { return $"{Type}:{Identifier}"; @@ -59,5 +44,34 @@ namespace Squidex.Infrastructure { return (Type.GetHashCode() * 397) ^ Identifier.GetHashCode(); } + + public static bool TryParse(string value, out RefToken result) + { + if (value != null) + { + var idx = value.IndexOf(':'); + + if (idx > 0 && idx < value.Length - 1) + { + result = new RefToken(value.Substring(0, idx), value.Substring(idx + 1)); + + return true; + } + } + + result = null; + + return false; + } + + public static RefToken Parse(string value) + { + if (!TryParse(value, out var result)) + { + throw new ArgumentException("Ref token must have more than 2 parts divided by colon.", nameof(value)); + } + + return result; + } } } diff --git a/src/Squidex.Infrastructure/States/DefaultStreamNameResolver.cs b/src/Squidex.Infrastructure/States/DefaultStreamNameResolver.cs index 582011a20..e7b30bca6 100644 --- a/src/Squidex.Infrastructure/States/DefaultStreamNameResolver.cs +++ b/src/Squidex.Infrastructure/States/DefaultStreamNameResolver.cs @@ -1,4 +1,4 @@ -// ========================================================================== + // ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschränkt) diff --git a/src/Squidex.Infrastructure/StringExtensions.cs b/src/Squidex.Infrastructure/StringExtensions.cs index 41b23ac9e..bfa46b900 100644 --- a/src/Squidex.Infrastructure/StringExtensions.cs +++ b/src/Squidex.Infrastructure/StringExtensions.cs @@ -331,7 +331,7 @@ namespace Squidex.Infrastructure return string.Empty; } - var sb = new StringBuilder(); + var sb = new StringBuilder(value.Length); var last = NullChar; var length = 0; @@ -387,7 +387,7 @@ namespace Squidex.Infrastructure return string.Empty; } - var sb = new StringBuilder(); + var sb = new StringBuilder(value.Length); var length = 0; @@ -429,7 +429,7 @@ namespace Squidex.Infrastructure return string.Empty; } - var sb = new StringBuilder(); + var sb = new StringBuilder(value.Length); var last = NullChar; var length = 0; diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 0baee6338..500a1aad3 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -19,7 +19,6 @@ using Squidex.Domain.Apps.Core.Schemas.Json; using Squidex.Domain.Apps.Events; using Squidex.Extensions.Actions; using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs index a73b14f3c..dec0ade55 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/TestUtils.cs @@ -16,7 +16,6 @@ using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; using Squidex.Infrastructure; using Squidex.Infrastructure.Collections; -using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; using Xunit; diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs index 7f31050f4..01cf6bc52 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Backup/BackupReaderWriterTests.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using FakeItEasy; using Squidex.Domain.Apps.Core; @@ -77,8 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Backup GuidRaw = RandomGuid(), Values = new Dictionary { - [RandomGuid()] = $"name{i}_1", - [RandomGuid()] = $"name{i}_1", + [RandomGuid()] = "Key" } }; @@ -149,20 +149,22 @@ namespace Squidex.Domain.Apps.Entities.Backup targetEvents.Add(@event); }); - for (var i = 0; i < targetEvents.Count; i++) + void CompareGuid(Guid source, Guid target) { - var tgt = targetEvents[i].Event.To(); - var src = sourceEvents[i].Event.To(); - - Assert.Equal(src.Payload.GuidRaw, reader.OldGuid(tgt.Payload.GuidRaw)); - Assert.Equal(src.Payload.GuidNamed.Id, reader.OldGuid(tgt.Payload.GuidNamed.Id)); + Assert.Equal(source, reader.OldGuid(target)); + Assert.NotEqual(source, target); + } - Assert.NotEqual(src.Payload.GuidRaw, tgt.Payload.GuidRaw); - Assert.NotEqual(src.Payload.GuidNamed.Id, tgt.Payload.GuidNamed.Id); + for (var i = 0; i < targetEvents.Count; i++) + { + var source = targetEvents[i].Event.To(); - Assert.Equal(src.Headers.GetGuid("Id"), reader.OldGuid(tgt.Headers.GetGuid("Id"))); + var target = sourceEvents[i].Event.To(); - Assert.NotEqual(src.Headers.GetGuid("Id"), tgt.Headers.GetGuid("Id")); + CompareGuid(target.Payload.Values.First().Key, source.Payload.Values.First().Key); + CompareGuid(target.Payload.GuidRaw, source.Payload.GuidRaw); + CompareGuid(target.Payload.GuidNamed.Id, source.Payload.GuidNamed.Id); + CompareGuid(target.Headers.GetGuid("Id"), source.Headers.GetGuid("Id")); } } } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeadersTests.cs similarity index 71% rename from tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs rename to tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeadersTests.cs index 21b1c7363..4a2a0286e 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeaderTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/EnvelopeHeadersTests.cs @@ -7,11 +7,12 @@ using System.Linq; using Squidex.Infrastructure.Json.Objects; +using Squidex.Infrastructure.TestHelpers; using Xunit; namespace Squidex.Infrastructure.EventSourcing { - public class EnvelopeHeaderTests + public class EnvelopeHeadersTests { [Fact] public void Should_create_headers() @@ -24,7 +25,8 @@ namespace Squidex.Infrastructure.EventSourcing [Fact] public void Should_create_headers_as_copy() { - var source = new JsonObject().Add("Key1", 123); + var source = JsonValue.Object().Add("Key1", 123); + var headers = new EnvelopeHeaders(source); CompareHeaders(headers, source); @@ -33,14 +35,23 @@ namespace Squidex.Infrastructure.EventSourcing [Fact] public void Should_clone_headers() { - var source = new JsonObject().Add("Key1", 123); - var headers = new EnvelopeHeaders(source); + var headers = new EnvelopeHeaders(JsonValue.Object().Add("Key1", 123)); var clone = headers.Clone(); CompareHeaders(headers, clone); } + [Fact] + public void Should_serialize_and_deserialize() + { + var value = new EnvelopeHeaders(JsonValue.Object().Add("Key1", 123)); + + var deserialized = value.SerializeAndDeserialize(); + + CompareHeaders(deserialized, value); + } + private static void CompareHeaders(JsonObject lhs, JsonObject rhs) { foreach (var key in lhs.Keys.Concat(rhs.Keys).Distinct()) diff --git a/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs b/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs index a5c00aae3..5ad034901 100644 --- a/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Json/Objects/JsonObjectTests.cs @@ -5,9 +5,11 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using NodaTime; using Xunit; namespace Squidex.Infrastructure.Json.Objects @@ -119,6 +121,10 @@ namespace Squidex.Infrastructure.Json.Objects public void Should_cache_null() { Assert.Same(JsonValue.Null, JsonValue.Create((string)null)); + Assert.Same(JsonValue.Null, JsonValue.Create((bool?)null)); + Assert.Same(JsonValue.Null, JsonValue.Create((double?)null)); + Assert.Same(JsonValue.Null, JsonValue.Create((object)null)); + Assert.Same(JsonValue.Null, JsonValue.Create((Instant?)null)); } [Fact] @@ -145,6 +151,28 @@ namespace Squidex.Infrastructure.Json.Objects Assert.Same(JsonValue.Zero, JsonValue.Create(0)); } + [Fact] + public void Should_boolean_from_object() + { + Assert.Equal(JsonValue.True, JsonValue.Create((object)true)); + } + + [Fact] + public void Should_create_value_from_instant() + { + var instant = Instant.FromUnixTimeSeconds(4123125455); + + Assert.Equal(instant.ToString(), JsonValue.Create(instant).ToString()); + } + + [Fact] + public void Should_create_value_from_instant_object() + { + var instant = Instant.FromUnixTimeSeconds(4123125455); + + Assert.Equal(instant.ToString(), JsonValue.Create((object)instant).ToString()); + } + [Fact] public void Should_create_array() { @@ -226,10 +254,12 @@ namespace Squidex.Infrastructure.Json.Objects { var numbers = new[] { - JsonValue.Create(1.0f), - JsonValue.Create(1.0), - JsonValue.Create(1L), - JsonValue.Create(1) + JsonValue.Create(12.0f), + JsonValue.Create(12.0), + JsonValue.Create(12L), + JsonValue.Create(12), + JsonValue.Create((object)12.0d), + JsonValue.Create((double?)12.0d) }; Assert.Single(numbers.Distinct()); @@ -317,5 +347,11 @@ namespace Squidex.Infrastructure.Json.Objects Assert.Equal(kvps, obj.ToArray()); Assert.Equal(kvps, ((IEnumerable)obj).OfType>().ToArray()); } + + [Fact] + public void Should_throw_exception_when_creation_value_from_invalid_type() + { + Assert.Throws(() => JsonValue.Create(Guid.Empty)); + } } } diff --git a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs index 5bb1b818a..c3b088571 100644 --- a/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs +++ b/tests/Squidex.Infrastructure.Tests/TestHelpers/JsonHelper.cs @@ -8,7 +8,6 @@ using System; using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; @@ -27,8 +26,8 @@ namespace Squidex.Infrastructure.TestHelpers ContractResolver = new ConverterContractResolver( new ClaimsPrincipalConverter(), new InstantConverter(), - new JsonValueConverter(), new EnvelopeHeadersConverter(), + new JsonValueConverter(), new LanguageConverter(), new NamedGuidIdConverter(), new NamedLongIdConverter(), diff --git a/tools/Migrate_01/Migrations/ConvertEventStore.cs b/tools/Migrate_01/Migrations/ConvertEventStore.cs index 37c6a476d..4a4fc7e7f 100644 --- a/tools/Migrate_01/Migrations/ConvertEventStore.cs +++ b/tools/Migrate_01/Migrations/ConvertEventStore.cs @@ -12,7 +12,6 @@ using MongoDB.Driver; using Newtonsoft.Json.Linq; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Migrations; -using Squidex.Infrastructure.MongoDb; namespace Migrate_01.Migrations { From 038935d0a837b71b55d1408e3154ce601020f170 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 29 Nov 2018 21:13:59 +0100 Subject: [PATCH 18/33] Better json types --- .../EventSourcing/EnvelopeExtensions.cs | 2 +- .../Json/Newtonsoft/JsonValueConverter.cs | 10 +++--- .../Json/Objects/JsonBoolean.cs | 30 +++++++++++++++++ .../Json/Objects/JsonNumber.cs | 27 +++++++++++++++ .../Json/Objects/JsonScalar.cs | 33 +++++-------------- .../Json/Objects/JsonString.cs | 27 +++++++++++++++ .../Json/Objects/JsonValue.cs | 12 +++---- 7 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonBoolean.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs create mode 100644 src/Squidex.Infrastructure/Json/Objects/JsonString.cs diff --git a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs index 968eadf3c..e08a6ec4f 100644 --- a/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs +++ b/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs @@ -91,7 +91,7 @@ namespace Squidex.Infrastructure.EventSourcing { if (obj.TryGetValue(key, out var v)) { - if (v is JsonScalar number) + if (v is JsonNumber number) { return (long)number.Value; } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs index 749cc9586..917099317 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -115,13 +115,13 @@ namespace Squidex.Infrastructure.Json.Newtonsoft case JsonNull n: writer.WriteNull(); break; - case JsonScalar s: + case JsonBoolean s: writer.WriteValue(s.Value); break; - case JsonScalar s: + case JsonString s: writer.WriteValue(s.Value); break; - case JsonScalar s: + case JsonNumber s: if (s.Value % 1 == 0) { @@ -136,9 +136,9 @@ namespace Squidex.Infrastructure.Json.Newtonsoft case JsonArray array: writer.WriteStartArray(); - foreach (var item in array) + for (var i = 0; i < array.Count; i++) { - WriteJson(writer, item); + WriteJson(writer, array[i]); } writer.WriteEndArray(); diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonBoolean.cs b/src/Squidex.Infrastructure/Json/Objects/JsonBoolean.cs new file mode 100644 index 000000000..de4f1ddf0 --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonBoolean.cs @@ -0,0 +1,30 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonBoolean : JsonScalar + { + public static readonly JsonBoolean True = new JsonBoolean(true); + public static readonly JsonBoolean False = new JsonBoolean(false); + + public override JsonValueType Type + { + get { return JsonValueType.Boolean; } + } + + private JsonBoolean(bool value) + : base(value) + { + } + + public override string ToString() + { + return Value ? "true" : "false"; + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs b/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs new file mode 100644 index 000000000..4b0f3220f --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs @@ -0,0 +1,27 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonNumber : JsonScalar + { + public override JsonValueType Type + { + get { return JsonValueType.Number; } + } + + internal JsonNumber(double value) + : base(value) + { + } + + public override string ToJsonString() + { + return $"{Value}"; + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs b/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs index bea068163..5ea9c2bd7 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonScalar.cs @@ -9,22 +9,15 @@ using System; namespace Squidex.Infrastructure.Json.Objects { - public sealed class JsonScalar : IJsonValue, IEquatable> + public abstract class JsonScalar : IJsonValue, IEquatable> { - private readonly T value; + public abstract JsonValueType Type { get; } - public JsonValueType Type { get; } + public T Value { get; } - public T Value + protected JsonScalar(T value) { - get { return value; } - } - - internal JsonScalar(JsonValueType type, T value) - { - Type = type; - - this.value = value; + Value = value; } public override bool Equals(object obj) @@ -39,31 +32,21 @@ namespace Squidex.Infrastructure.Json.Objects public bool Equals(JsonScalar other) { - return other != null && other.Type == Type && Equals(other.value, value); + return other != null && other.Type == Type && Equals(other.Value, Value); } public override int GetHashCode() { - return value.GetHashCode(); + return Value.GetHashCode(); } public override string ToString() { - if (Type == JsonValueType.Boolean) - { - return Equals(Value, true) ? "true" : "false"; - } - return Value.ToString(); } - public string ToJsonString() + public virtual string ToJsonString() { - if (Type == JsonValueType.String) - { - return $"\"{value}\""; - } - return ToString(); } } diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonString.cs b/src/Squidex.Infrastructure/Json/Objects/JsonString.cs new file mode 100644 index 000000000..4aeccc93f --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Objects/JsonString.cs @@ -0,0 +1,27 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Json.Objects +{ + public sealed class JsonString : JsonScalar + { + public override JsonValueType Type + { + get { return JsonValueType.String; } + } + + internal JsonString(string value) + : base(value) + { + } + + public override string ToJsonString() + { + return $"\"{Value}\""; + } + } +} diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs index 5022aadab..922039f5e 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonValue.cs @@ -14,14 +14,14 @@ namespace Squidex.Infrastructure.Json.Objects { public static class JsonValue { - public static readonly IJsonValue Empty = new JsonScalar(JsonValueType.String, string.Empty); + public static readonly IJsonValue Empty = new JsonString(string.Empty); - public static readonly IJsonValue True = new JsonScalar(JsonValueType.Boolean, true); - public static readonly IJsonValue False = new JsonScalar(JsonValueType.Boolean, false); + public static readonly IJsonValue True = JsonBoolean.True; + public static readonly IJsonValue False = JsonBoolean.False; public static readonly IJsonValue Null = JsonNull.Null; - public static readonly IJsonValue Zero = new JsonScalar(JsonValueType.Number, 0); + public static readonly IJsonValue Zero = new JsonNumber(0); public static JsonArray Array() { @@ -85,7 +85,7 @@ namespace Squidex.Infrastructure.Json.Objects return Zero; } - return new JsonScalar(JsonValueType.Number, value); + return new JsonNumber(value); } public static IJsonValue Create(Instant? value) @@ -130,7 +130,7 @@ namespace Squidex.Infrastructure.Json.Objects return Empty; } - return new JsonScalar(JsonValueType.String, value); + return new JsonString(value); } } } From dbc80adc454888acadc5e1881fd2818681ac189a Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 30 Nov 2018 16:03:32 +0100 Subject: [PATCH 19/33] Even less newtonsoft. --- .../ElasticSearchActionHandler.cs | 12 ++--- .../Actions/Medium/MediumActionHandler.cs | 53 +++++++++++-------- .../Rules/RuleCreated.cs | 2 +- .../Schemas/FieldAdded.cs | 2 +- .../Json/Objects/JsonNumber.cs | 6 ++- 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs index 3688f7f75..991725964 100644 --- a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchActionHandler.cs @@ -8,7 +8,6 @@ using System; using System.Threading.Tasks; using Elasticsearch.Net; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; @@ -62,8 +61,7 @@ namespace Squidex.Extensions.Actions.ElasticSearch var json = ToJson(contentEvent); - ruleJob.Content = JObject.Parse(json); - ruleJob.Content["objectID"] = contentId; + ruleJob.Content = $"{{ \"objectId\": \"{contentId}\", {json.Substring(1)}"; } ruleJob.Username = action.Username; @@ -88,9 +86,7 @@ namespace Squidex.Extensions.Actions.ElasticSearch { if (job.Content != null) { - var doc = job.Content.ToString(); - - var response = await client.IndexAsync(job.IndexName, job.IndexType, job.ContentId, doc); + var response = await client.IndexAsync(job.IndexName, job.IndexType, job.ContentId, job.Content); return (response.Body, response.OriginalException); } @@ -118,10 +114,10 @@ namespace Squidex.Extensions.Actions.ElasticSearch public string ContentId { get; set; } + public string Content { get; set; } + public string IndexName { get; set; } public string IndexType { get; set; } - - public JObject Content { get; set; } } } diff --git a/extensions/Squidex.Extensions/Actions/Medium/MediumActionHandler.cs b/extensions/Squidex.Extensions/Actions/Medium/MediumActionHandler.cs index e3fe88fae..2aec919c6 100644 --- a/extensions/Squidex.Extensions/Actions/Medium/MediumActionHandler.cs +++ b/extensions/Squidex.Extensions/Actions/Medium/MediumActionHandler.cs @@ -9,11 +9,10 @@ using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; using Squidex.Infrastructure.Http; +using Squidex.Infrastructure.Json; namespace Squidex.Extensions.Actions.Medium { @@ -22,53 +21,61 @@ namespace Squidex.Extensions.Actions.Medium private const string Description = "Post to medium"; private readonly IHttpClientFactory httpClientFactory; + private readonly IJsonSerializer serializer; - public MediumActionHandler(RuleEventFormatter formatter, IHttpClientFactory httpClientFactory) + private sealed class UserResponse + { + public UserResponseData Data { get; set; } + } + + private sealed class UserResponseData + { + public string Id { get; set; } + } + + public MediumActionHandler(RuleEventFormatter formatter, IHttpClientFactory httpClientFactory, IJsonSerializer serializer) : base(formatter) { this.httpClientFactory = httpClientFactory; + + this.serializer = serializer; } protected override (string Description, MediumJob Data) CreateJob(EnrichedEvent @event, MediumAction action) { - var requestBody = - new JObject( - new JProperty("title", Format(action.Title, @event)), - new JProperty("contentFormat", action.IsHtml ? "html" : "markdown"), - new JProperty("content", Format(action.Content, @event)), - new JProperty("canonicalUrl", Format(action.CanonicalUrl, @event)), - new JProperty("tags", ParseTags(@event, action))); - - var ruleJob = new MediumJob + var ruleJob = new MediumJob { AccessToken = action.AccessToken, PublicationId = action.PublicationId }; + + var requestBody = new { - AccessToken = action.AccessToken, - PublicationId = action.PublicationId, - RequestBody = requestBody.ToString(Formatting.Indented) + title = Format(action.Title, @event), + contentFormat = action.IsHtml ? "html" : "markdown", + content = Format(action.Content, @event), + canonicalUrl = Format(action.CanonicalUrl, @event), + tags = ParseTags(@event, action) }; + ruleJob.RequestBody = ToJson(requestBody); + return (Description, ruleJob); } - private JArray ParseTags(EnrichedEvent @event, MediumAction action) + private string[] ParseTags(EnrichedEvent @event, MediumAction action) { if (string.IsNullOrWhiteSpace(action.Tags)) { return null; } - string[] tags; try { var jsonTags = Format(action.Tags, @event); - tags = JsonConvert.DeserializeObject(jsonTags); + return serializer.Deserialize(jsonTags); } catch { - tags = action.Tags.Split(','); + return action.Tags.Split(','); } - - return new JArray(tags); } protected override async Task<(string Dump, Exception Exception)> ExecuteJobAsync(MediumJob job) @@ -96,9 +103,9 @@ namespace Squidex.Extensions.Actions.Medium response = await httpClient.SendAsync(meRequest); var responseString = await response.Content.ReadAsStringAsync(); - var responseJson = JToken.Parse(responseString); + var responseJson = serializer.Deserialize(responseString); - var id = responseJson["data"]["id"].ToString(); + var id = responseJson.Data?.Id; path = $"v1/users/{id}/posts"; } diff --git a/src/Squidex.Domain.Apps.Events/Rules/RuleCreated.cs b/src/Squidex.Domain.Apps.Events/Rules/RuleCreated.cs index 10679e200..bab06a970 100644 --- a/src/Squidex.Domain.Apps.Events/Rules/RuleCreated.cs +++ b/src/Squidex.Domain.Apps.Events/Rules/RuleCreated.cs @@ -17,4 +17,4 @@ namespace Squidex.Domain.Apps.Events.Rules public RuleAction Action { get; set; } } -} +} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Events/Schemas/FieldAdded.cs b/src/Squidex.Domain.Apps.Events/Schemas/FieldAdded.cs index 7b136e947..d73358c30 100644 --- a/src/Squidex.Domain.Apps.Events/Schemas/FieldAdded.cs +++ b/src/Squidex.Domain.Apps.Events/Schemas/FieldAdded.cs @@ -19,4 +19,4 @@ namespace Squidex.Domain.Apps.Events.Schemas public FieldProperties Properties { get; set; } } -} +} \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs b/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs index 4b0f3220f..25c3c573f 100644 --- a/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs +++ b/src/Squidex.Infrastructure/Json/Objects/JsonNumber.cs @@ -5,6 +5,8 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Globalization; + namespace Squidex.Infrastructure.Json.Objects { public sealed class JsonNumber : JsonScalar @@ -19,9 +21,9 @@ namespace Squidex.Infrastructure.Json.Objects { } - public override string ToJsonString() + public override string ToString() { - return $"{Value}"; + return Value.ToString(CultureInfo.InvariantCulture); } } } From ac1ccac34cd53909805a18df46e3b23b60cf643c Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 1 Dec 2018 12:59:54 +0100 Subject: [PATCH 20/33] More optimizations. --- .../MongoDb/BsonJsonReader.cs | 20 +++++----- .../MongoDb/MongoExtensions.cs | 5 +-- .../Newtonsoft/ConverterContractResolver.cs | 39 +++++++++++++++++-- .../Newtonsoft/EnvelopeHeadersConverter.cs | 6 +++ .../Json/Newtonsoft/ISupportedTypes.cs | 17 ++++++++ .../Json/Newtonsoft/InstantConverter.cs | 10 +++++ .../Json/Newtonsoft/JsonClassConverter.cs | 16 +++++--- .../Json/Newtonsoft/JsonValueConverter.cs | 21 +++++++++- .../Log/JsonLogWriter.cs | 28 ++++++++----- .../Config/Domain/SerializationServices.cs | 4 -- src/Squidex/Squidex.csproj | 1 - 11 files changed, 128 insertions(+), 39 deletions(-) create mode 100644 src/Squidex.Infrastructure/Json/Newtonsoft/ISupportedTypes.cs diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs index acb8708fa..f801aeddc 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs @@ -37,16 +37,6 @@ namespace Squidex.Infrastructure.MongoDb { SetToken(NewtonsoftJsonToken.PropertyName, bsonReader.ReadName().UnescapeBson()); } - else if (bsonReader.State == BsonReaderState.EndOfDocument) - { - SetToken(NewtonsoftJsonToken.EndObject); - bsonReader.ReadEndDocument(); - } - else if (bsonReader.State == BsonReaderState.EndOfArray) - { - SetToken(NewtonsoftJsonToken.EndArray); - bsonReader.ReadEndArray(); - } else if (bsonReader.State == BsonReaderState.Value) { switch (bsonReader.CurrentBsonType) @@ -95,6 +85,16 @@ namespace Squidex.Infrastructure.MongoDb throw new NotSupportedException(); } } + else if (bsonReader.State == BsonReaderState.EndOfDocument) + { + SetToken(NewtonsoftJsonToken.EndObject); + bsonReader.ReadEndDocument(); + } + else if (bsonReader.State == BsonReaderState.EndOfArray) + { + SetToken(NewtonsoftJsonToken.EndArray); + bsonReader.ReadEndArray(); + } if (bsonReader.State == BsonReaderState.Initial) { diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoExtensions.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoExtensions.cs index 3681a4aa7..d8baba185 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoExtensions.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoExtensions.cs @@ -101,10 +101,7 @@ namespace Squidex.Infrastructure.MongoDb { var update = updater(Builders.Update.Set(x => x.Version, newVersion)); - await collection.UpdateOneAsync(x => x.Id.Equals(key) && x.Version == oldVersion, - update - .Set(x => x.Version, newVersion), - Upsert); + await collection.UpdateOneAsync(x => x.Id.Equals(key) && x.Version == oldVersion, update, Upsert); } catch (MongoWriteException ex) { diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs index e626d5e1d..53b203da3 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/ConverterContractResolver.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -14,10 +15,23 @@ namespace Squidex.Infrastructure.Json.Newtonsoft public sealed class ConverterContractResolver : CamelCasePropertyNamesContractResolver { private readonly JsonConverter[] converters; + private readonly object lockObject = new object(); + private Dictionary converterCache = new Dictionary(); public ConverterContractResolver(params JsonConverter[] converters) { this.converters = converters; + + foreach (var converter in converters) + { + if (converter is ISupportedTypes supportedTypes) + { + foreach (var type in supportedTypes.SupportedTypes) + { + converterCache[type] = converter; + } + } + } } protected override JsonDictionaryContract CreateDictionaryContract(Type objectType) @@ -38,15 +52,32 @@ namespace Squidex.Infrastructure.Json.Newtonsoft return result; } - foreach (var converter in converters) + var cache = converterCache; + + if (cache == null || !cache.TryGetValue(objectType, out result)) { - if (converter.CanConvert(objectType)) + foreach (var converter in converters) + { + if (converter.CanConvert(objectType)) + { + result = converter; + } + } + + lock (lockObject) { - return converter; + cache = converterCache; + + var updatedCache = (cache != null) + ? new Dictionary(cache) + : new Dictionary(); + updatedCache[objectType] = result; + + converterCache = updatedCache; } } - return null; + return result; } } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs index a90b97950..d4a529395 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/EnvelopeHeadersConverter.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Collections.Generic; using Newtonsoft.Json; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json.Objects; @@ -14,6 +15,11 @@ namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class EnvelopeHeadersConverter : JsonValueConverter { + public override IEnumerable SupportedTypes + { + get { yield return typeof(EnvelopeHeaders); } + } + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var result = base.ReadJson(reader, objectType, existingValue, serializer); diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/ISupportedTypes.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/ISupportedTypes.cs new file mode 100644 index 000000000..fa28fb93c --- /dev/null +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/ISupportedTypes.cs @@ -0,0 +1,17 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; + +namespace Squidex.Infrastructure.Json.Newtonsoft +{ + public interface ISupportedTypes + { + IEnumerable SupportedTypes { get; } + } +} diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs index 463d24411..9663accf9 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/InstantConverter.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Collections.Generic; using Newtonsoft.Json; using NodaTime; using NodaTime.Text; @@ -14,6 +15,15 @@ namespace Squidex.Infrastructure.Json.Newtonsoft { public sealed class InstantConverter : JsonConverter { + public IEnumerable SupportedTypes + { + get + { + yield return typeof(Instant); + yield return typeof(Instant?); + } + } + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value != null) diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs index 078bd451e..03acfc2f5 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonClassConverter.cs @@ -6,12 +6,18 @@ // ========================================================================== using System; +using System.Collections.Generic; using Newtonsoft.Json; namespace Squidex.Infrastructure.Json.Newtonsoft { - public abstract class JsonClassConverter : JsonConverter where T : class + public abstract class JsonClassConverter : JsonConverter, ISupportedTypes where T : class { + public IEnumerable SupportedTypes + { + get { yield return typeof(T); } + } + public sealed override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) @@ -22,6 +28,8 @@ namespace Squidex.Infrastructure.Json.Newtonsoft return ReadValue(reader, objectType, serializer); } + protected abstract T ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer); + public sealed override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) @@ -33,13 +41,11 @@ namespace Squidex.Infrastructure.Json.Newtonsoft WriteValue(writer, (T)value, serializer); } + protected abstract void WriteValue(JsonWriter writer, T value, JsonSerializer serializer); + public override bool CanConvert(Type objectType) { return objectType == typeof(T); } - - protected abstract void WriteValue(JsonWriter writer, T value, JsonSerializer serializer); - - protected abstract T ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer); } } diff --git a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs index 917099317..0e4282826 100644 --- a/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs +++ b/src/Squidex.Infrastructure/Json/Newtonsoft/JsonValueConverter.cs @@ -6,6 +6,7 @@ // ========================================================================== using System; +using System.Collections.Generic; using System.Globalization; using Newtonsoft.Json; using Squidex.Infrastructure.Json.Objects; @@ -14,8 +15,24 @@ using Squidex.Infrastructure.Json.Objects; namespace Squidex.Infrastructure.Json.Newtonsoft { - public class JsonValueConverter : JsonConverter + public class JsonValueConverter : JsonConverter, ISupportedTypes { + private readonly HashSet supportedTypes = new HashSet + { + typeof(IJsonValue), + typeof(JsonArray), + typeof(JsonBoolean), + typeof(JsonNull), + typeof(JsonNumber), + typeof(JsonObject), + typeof(JsonString) + }; + + public virtual IEnumerable SupportedTypes + { + get { return supportedTypes; } + } + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return ReadJson(reader); @@ -161,7 +178,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft public override bool CanConvert(Type objectType) { - return typeof(IJsonValue).IsAssignableFrom(objectType); + return supportedTypes.Contains(objectType); } } } diff --git a/src/Squidex.Infrastructure/Log/JsonLogWriter.cs b/src/Squidex.Infrastructure/Log/JsonLogWriter.cs index 4d8012f8f..b90cf64eb 100644 --- a/src/Squidex.Infrastructure/Log/JsonLogWriter.cs +++ b/src/Squidex.Infrastructure/Log/JsonLogWriter.cs @@ -96,7 +96,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, string value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value); return this; @@ -104,7 +104,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, double value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value); return this; @@ -112,7 +112,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, long value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value); return this; @@ -120,7 +120,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, bool value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value); return this; @@ -128,7 +128,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, DateTime value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value.ToString("o", CultureInfo.InvariantCulture)); return this; @@ -136,7 +136,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, DateTimeOffset value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value.ToString("o", CultureInfo.InvariantCulture)); return this; @@ -144,7 +144,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteProperty(string property, TimeSpan value) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteValue(value); return this; @@ -152,7 +152,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteObject(string property, Action objectWriter) { - jsonWriter.WritePropertyName(property); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteStartObject(); objectWriter?.Invoke(this); @@ -164,7 +164,7 @@ namespace Squidex.Infrastructure.Log IObjectWriter IObjectWriter.WriteArray(string property, Action arrayWriter) { - jsonWriter.WritePropertyName(property.ToCamelCase()); + jsonWriter.WritePropertyName(Format(property)); jsonWriter.WriteStartArray(); arrayWriter?.Invoke(this); @@ -185,6 +185,16 @@ namespace Squidex.Infrastructure.Log return this; } + private static string Format(string property) + { + if (ReferenceEquals(string.IsInterned(property), property)) + { + return property; + } + + return property.ToCamelCase(); + } + public override string ToString() { jsonWriter.WriteEndObject(); diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 500a1aad3..87916c8ac 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -9,8 +9,6 @@ using Microsoft.Extensions.DependencyInjection; using Migrate_01; using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using NodaTime; -using NodaTime.Serialization.JsonNet; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Apps.Json; using Squidex.Domain.Apps.Core.Rules.Json; @@ -68,8 +66,6 @@ namespace Squidex.Config.Domain settings.DateParseHandling = DateParseHandling.None; settings.TypeNameHandling = typeNameHandling; - - settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); } static SerializationServices() diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj index 93f9dad74..478449461 100644 --- a/src/Squidex/Squidex.csproj +++ b/src/Squidex/Squidex.csproj @@ -80,7 +80,6 @@ - From 9bf46ee086a8eaf2ded21a373334ccb1fd1b4bd2 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 1 Dec 2018 13:20:13 +0100 Subject: [PATCH 21/33] Bugfix --- src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs | 4 ++-- .../EventSourcing/DefaultEventDataFormatter.cs | 4 ++-- .../EventSourcing/IEventDataFormatter.cs | 2 +- .../EventSourcing/Grains/EventConsumerGrainTests.cs | 4 ++-- .../States/PersistenceEventSourcingTests.cs | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs index 660ca8627..3aa5bc9c5 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs @@ -127,9 +127,9 @@ namespace Squidex.Domain.Apps.Entities.Backup MapHeaders(data); var eventStream = streamNameResolver.WithNewId(streamName, guidMapper.NewGuidOrNull); - var eventEnvelope = formatter.Parse(data, true, guidMapper.NewGuidOrValue); + var eventEnvelope = formatter.Parse(data, guidMapper.NewGuidOrValue); - await handler((streamName, eventEnvelope)); + await handler((eventStream, eventEnvelope)); } readEvents++; diff --git a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs index d8e27f511..8135566cf 100644 --- a/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/DefaultEventDataFormatter.cs @@ -25,12 +25,12 @@ namespace Squidex.Infrastructure.EventSourcing this.serializer = serializer; } - public Envelope Parse(EventData eventData, bool migrate = true, Func stringConverter = null) + public Envelope Parse(EventData eventData, Func stringConverter = null) { var payloadType = typeNameRegistry.GetType(eventData.Type); var payloadObj = serializer.Deserialize(eventData.Payload, payloadType, stringConverter); - if (migrate && payloadObj is IMigratedEvent migratedEvent) + if (payloadObj is IMigratedEvent migratedEvent) { payloadObj = migratedEvent.Migrate(); } diff --git a/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs b/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs index 071808fb6..db3c3fdff 100644 --- a/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs +++ b/src/Squidex.Infrastructure/EventSourcing/IEventDataFormatter.cs @@ -11,7 +11,7 @@ namespace Squidex.Infrastructure.EventSourcing { public interface IEventDataFormatter { - Envelope Parse(EventData eventData, bool migrate = true, Func stringConverter = null); + Envelope Parse(EventData eventData, Func stringConverter = null); EventData ToEventData(Envelope envelope, Guid commitId, bool migrate = true); } diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs index a65750d97..03e9fb905 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs @@ -82,7 +82,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains A.CallTo(() => persistence.WriteSnapshotAsync(A.Ignored)) .Invokes(new Action(s => state = s)); - A.CallTo(() => formatter.Parse(eventData, true, null)) + A.CallTo(() => formatter.Parse(eventData, null)) .Returns(envelope); sut = new MyEventConsumerGrain( @@ -196,7 +196,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains [Fact] public async Task Should_ignore_old_events() { - A.CallTo(() => formatter.Parse(eventData, true, null)) + A.CallTo(() => formatter.Parse(eventData, null)) .Throws(new TypeNameNotFoundException()); var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData); diff --git a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs index a061b8a61..72e37048b 100644 --- a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs +++ b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs @@ -61,7 +61,7 @@ namespace Squidex.Infrastructure.States A.CallTo(() => eventStore.QueryAsync(key, 0)) .Returns(new List { storedEvent }); - A.CallTo(() => eventDataFormatter.Parse(storedEvent.Data, true, null)) + A.CallTo(() => eventDataFormatter.Parse(storedEvent.Data, null)) .Throws(new TypeNameNotFoundException()); var persistedEvents = new List(); @@ -256,7 +256,7 @@ namespace Squidex.Infrastructure.States eventsStored.Add(eventStored); - A.CallTo(() => eventDataFormatter.Parse(eventData, true, null)) + A.CallTo(() => eventDataFormatter.Parse(eventData, null)) .Returns(new Envelope(@event)); i++; From 31721abfb467aca1a6d0986ce415b55a16e47690 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 4 Dec 2018 16:27:53 +0100 Subject: [PATCH 22/33] Restore fix. --- src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs b/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs index 4a2952e15..38bc2394f 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs @@ -194,6 +194,8 @@ namespace Squidex.Domain.Apps.Entities.Backup } } + await AssignContributorAsync(); + CurrentJob.Status = JobStatus.Completed; Log("Completed, Yeah!"); @@ -252,6 +254,8 @@ namespace Squidex.Domain.Apps.Entities.Backup FromRestore = true, Role = Role.Owner }); + + Log("Assigned current user."); } private async Task CleanupAsync() @@ -283,7 +287,7 @@ namespace Squidex.Domain.Apps.Entities.Backup await HandleEventAsync(reader, storedEvent.Stream, storedEvent.Event); }); - Log("Reading events completed."); + Log($"Reading {reader.ReadEvents} events and {reader.ReadAttachments} attachments completed.", true); } private async Task HandleEventAsync(BackupReader reader, string stream, Envelope @event) From 86eeef2662752291fc873ae422aed13dbb9f0e11 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 4 Dec 2018 17:36:43 +0100 Subject: [PATCH 23/33] Open close all array items. --- .../shared/array-editor.component.html | 2 + .../content/shared/array-editor.component.ts | 6 ++ .../content/shared/array-item.component.html | 9 +- .../content/shared/array-item.component.scss | 10 ++ .../content/shared/array-item.component.ts | 6 ++ .../app/theme/icomoon/demo-files/demo.css | 2 +- src/Squidex/app/theme/icomoon/demo.html | 98 +++++++++++++++++- .../app/theme/icomoon/fonts/icomoon.eot | Bin 26364 -> 27384 bytes .../app/theme/icomoon/fonts/icomoon.svg | 6 ++ .../app/theme/icomoon/fonts/icomoon.ttf | Bin 26200 -> 27220 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 26276 -> 27296 bytes .../app/theme/icomoon/icons/hide-all.svg | 70 +++++++++++++ src/Squidex/app/theme/icomoon/icons/hide.svg | 62 +++++++++++ .../app/theme/icomoon/icons/show-all.svg | 70 +++++++++++++ src/Squidex/app/theme/icomoon/icons/show.svg | 62 +++++++++++ src/Squidex/app/theme/icomoon/selection.json | 2 +- src/Squidex/app/theme/icomoon/style.css | 28 ++++- 17 files changed, 424 insertions(+), 9 deletions(-) create mode 100644 src/Squidex/app/theme/icomoon/icons/hide-all.svg create mode 100644 src/Squidex/app/theme/icomoon/icons/hide.svg create mode 100644 src/Squidex/app/theme/icomoon/icons/show-all.svg create mode 100644 src/Squidex/app/theme/icomoon/icons/show.svg diff --git a/src/Squidex/app/features/content/shared/array-editor.component.html b/src/Squidex/app/features/content/shared/array-editor.component.html index d881c1d6d..7516160e0 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.html +++ b/src/Squidex/app/features/content/shared/array-editor.component.html @@ -5,10 +5,12 @@ diff --git a/src/Squidex/app/features/content/shared/array-editor.component.ts b/src/Squidex/app/features/content/shared/array-editor.component.ts index 4877c97db..aa1f9a47d 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.ts +++ b/src/Squidex/app/features/content/shared/array-editor.component.ts @@ -37,6 +37,12 @@ export class ArrayEditorComponent { @Input() public arrayControl: FormArray; + public isHidden = false; + + public hide(hide: boolean) { + this.isHidden = hide; + } + public removeItem(index: number) { this.form.removeArrayItem(this.field, this.language, index); } diff --git a/src/Squidex/app/features/content/shared/array-item.component.html b/src/Squidex/app/features/content/shared/array-item.component.html index 337033cfa..583ae798b 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.html +++ b/src/Squidex/app/features/content/shared/array-item.component.html @@ -4,6 +4,13 @@ Item #{{index + 1}} + + + + + + + -
+
(); + @Input() public form: EditContentForm; @Input() public field: RootFieldDto; + @Input() + public isHidden = false; + @Input() public index: number; diff --git a/src/Squidex/app/theme/icomoon/demo-files/demo.css b/src/Squidex/app/theme/icomoon/demo-files/demo.css index 3ecabc189..e74013014 100644 --- a/src/Squidex/app/theme/icomoon/demo-files/demo.css +++ b/src/Squidex/app/theme/icomoon/demo-files/demo.css @@ -150,7 +150,7 @@ p { font-size: 24px; } .fs2 { - font-size: 32px; + font-size: 24px; } .fs3 { font-size: 20px; diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index 07508b600..10b155143 100644 --- a/src/Squidex/app/theme/icomoon/demo.html +++ b/src/Squidex/app/theme/icomoon/demo.html @@ -9,10 +9,42 @@
-

Font Name: icomoon (Glyphs: 103)

+

Font Name: icomoon (Glyphs: 109)

Grid Size: 24

+
+
+ + + + icon-minus-square +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-plus-square +
+
+ + +
+
+ liga: + +
+
@@ -112,6 +144,70 @@

Grid Size: 16

+
+
+ + + + icon-show +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-show-all +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-hide +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-hide-all +
+
+ + +
+
+ liga: + +
+
diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 72467e8885537c0ecc2039befc1652854caf5d91..4591299f2be956ea1ee177ab7bbc5339187fbc0e 100644 GIT binary patch delta 1229 zcmbu8Pe>GT6vy9h#$6MO-QhR0zX5e@oz;aDSDSSQD#0L#_0+-HVhe0nS2t;MEi>t| zdyo+8pllbr7MOny!h&?Di15&%J#+{Hmrh34A_^&Y?9E8IMw!v!_kQz!@Au<<=KJ2; zERc=Y#JMp9&@(jS3{`~VQedX*hOi0%k8xe>OU2S_r`G7qi`vZm$wQw2$TUFTMluoW z7gxT{10*K#UMPtNRh;80`p?k!B~zp0b5CkcqrZ-CRxc0t#qKUHJp~wii1GDQY&;E< zBnptcgZ|+wu~cHVyXqVIOL+fQdidHX@EC!ipcMz6C$Dn-Z*WS2CU_;$bDRiXK@~)g<~*IyL1Rm{JD^e0)^#Yyp8;Nil)EG=m;R@o>K4x$EZpOyk5v zW88d)Cf*1R8)lkcwqe>qht9v^AZ;DdI=oC!C2bp$?u*d;g6tU*e94%{qORHxF;Nvs zmJ8c|>noO4ck#nNtC>++3_VqLu5?cf~>V=85LR9I?ghYQicPyo2%90it=6?#~zfuDNGxPAP}Q_Ww-KTMwUO& z+r!reqcHrS6G7$Z(7caKla>sTqh&><@kLf6);@B4D^lMnf|wO>vF&yhy+&J W+-;Gz&Gtv_n>dsJBl%;A=j1zqX(X-y delta 281 zcmexymGRG6Mz%j`3=9!z6WPpIR!)9-cd}!q$i$Fj!GjD8410h$Avrg(;I`du#)&6n z>VI<|15lk=22g;Li8Tkve*xsHWaO4q^zRkVWMD|* z0qR+klb@W(yjbc214Hr-p!|*8#EJrjCdMcRh7_QA3<`OPxv4X~IDZ5AK=T;e3i69f z7?^=F3~3f1c?M=?#&eTX7`qvhCx2j6W}PPx&%bc91k=Zu%@31;nPu+2oV+rg-{va= zHw#D;!wuPd9T+`1AkCaHdvizHV#dkN8Mnps1@zAt2rw`L<+B+h7{oy87?>tM%o5%l IoVk<{0H6|6CjbBd diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg index 4da0b7edc..dfd836760 100644 --- a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg +++ b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg @@ -107,6 +107,12 @@ + + + + + + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index ec3e7d32406bfad08cd4a0bc6f506a58a2d88664..e350edc09f58a3b6a20f5f324fe4e86fdc9442da 100644 GIT binary patch delta 1267 zcmbu9O-vI(6vyA}Qjh>?*WK+j0an{BG!a4zTe=4&k;KG6Ogv~SsYY!}KQyfrL4sbk z2Vw|%z|;#~)gT`Sk|xB18V?-l!Gr?|jVFv}V>CwT;@c%kF^U+Q%$xpacKUw(zc;(S zO4inh1_S`=AO|e?&YtsjSr0d?;K~aeS7Vt-cH`6r4?vnwr<0M9EY3F6lQ)W4Vd?HEMS%Gde!|vhg(PO+2%b9*Xrw9xg1t z0!Ti?2R1X2@hnV|FhJ@)>Z3OznfOe9?Kjkmc;Ie!Xk-*Y@pIj8>;ucbdGPukxt2de zWXls<+&WtrB_A$nRZxUhR$;@?2okvA7@l@ji=4taMZtcYa86F<1iRww3UqTGr-jO_ zN2N6$4x>s5h>}7SNqnROMh0a`FA-&ItSC=Sxf4@zGT~;!l6@Q9n-L`)$g1wQOOl;& zmj-U>@3oeRiI%AT4nwpBEGEn}yJW(2f(ku<#X;I;qI5ecCyUAsB!3`6{WG#_#J@_Z z-Jq^L2r-c*(cviW{9AXayt0QM{@G1Uwi2p(YQ!3JQ~ggnvnI@i9WSB6O$+v|2TNkUSyg+lta*hf-Pw_hK5`IAh(H^CPQgHOqK=M5*l delta 301 zcmca|h4IE2#(D-u1_lOhh6V;^1_S?KeItG$-h)7qJwTk0oSRs1+wL|{1)~g*pOcvfP)UzfhKiM&nd9l<528QGvKm|8)6DtZBni!)P7*c=+GAQIF=BCc{ z;`|Nd0}W(sE66V{0Xh^2(kwvo49v{uCLZW!OrGq+sLVP~AfA8W<`Tw_F`I3Zf|+IR zzMQ-=p5Nvx12+pu3&RcBd>t4)c}=Q0WA^4Jsf!sW&riQCrZ1p>#y|iZ7}<;w3}Rpn POp_h6gg39xSjq?hO@dFf diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.woff b/src/Squidex/app/theme/icomoon/fonts/icomoon.woff index 1380b3b1859fefda391edf25c16359142d81652e..45212faf89dfdacf3bddf8bedecaf6f4ff8575cb 100644 GIT binary patch delta 1313 zcmbu9O-vI}5Xa~3QjmaYH@n-{1X*df&_oC=E_4q{qKU!4K`*qDYBX)>hlUCWB6?{L z#2CCt>Onk_h#`Onk|uZ+CwCpZ9h; zPo`cI>DKv<4j_QnwJE4F$L{PzT+B|z%O)D7^l~&69snRooa$q?er8=vgojw}6~>2t zm@UzFJC3;mKy-uI?CHZFld*6wK#Z;PGm{p-&L%Ml5U8YNIV?)l)A z*;&Wq9nY_3tI2(GHT#IDmT6neI+J@zK3qzdK^_`-jSoQ$C`fe-U*js51x;|ulKlh` zoPsJycFlR*-zIpR7OL_domO}R^g1OVD;m)h`LO}$ISdO%foLNmd3Ai;9UoT{aW@}Q z>|3bwq^uY~R*Y7=qS!fiq35RYK3zXHRv$6mp^Mam#e{jlFPJbbphNp#ager_Xl+g^ zsIs;VDISQ>_=4~Q3_zt&wSF7M%oe^xWCS_#!X6>( z118LcZ7rchO$+XB54M)6iG_B`xysY~b^15blF40_jFCSz-;{P&S+2GOjJs318=6YD z!!P3Eu7v=)c|HJEI0~n-ONuMat8J|fDr-7AbBm(G#xg`}qu?V34H6Yx-S3EN(KN+abFNFoD=mrQgFP6HHn^*y~I0a}4g8~>gF-GMj z=B5J0fR-?}f$&T(&ff+3#U((Ww7}Id16j<>=O*(ob~7eVp24WhI!_>;f8pi>j2~k* zcP0fh%iMiAd1XAm%~u9)kc~k5Wb<`k^yD9@=8V~!4bm1fPJW$!n@3+j|BQhEIJmMm J-^)0}2mqVDQ-uHk diff --git a/src/Squidex/app/theme/icomoon/icons/hide-all.svg b/src/Squidex/app/theme/icomoon/icons/hide-all.svg new file mode 100644 index 000000000..69ed451c1 --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/hide-all.svg @@ -0,0 +1,70 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/icons/hide.svg b/src/Squidex/app/theme/icomoon/icons/hide.svg new file mode 100644 index 000000000..e86579ac2 --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/hide.svg @@ -0,0 +1,62 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/icons/show-all.svg b/src/Squidex/app/theme/icomoon/icons/show-all.svg new file mode 100644 index 000000000..afd55db27 --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/show-all.svg @@ -0,0 +1,70 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/icons/show.svg b/src/Squidex/app/theme/icomoon/icons/show.svg new file mode 100644 index 000000000..eb6d4a386 --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/show.svg @@ -0,0 +1,62 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/selection.json b/src/Squidex/app/theme/icomoon/selection.json index f6ba2db56..6d1ad4ebe 100644 --- a/src/Squidex/app/theme/icomoon/selection.json +++ b/src/Squidex/app/theme/icomoon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":0,"setId":6,"iconIdx":0},{"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":1,"id":0,"name":"comments","prevSize":24,"code":59743},"setIdx":0,"setId":6,"iconIdx":1},{"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":2,"prevSize":24,"code":59739,"name":"backup"},"setIdx":5,"setId":1,"iconIdx":24},{"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":0,"prevSize":24,"code":59738,"name":"support"},"setIdx":5,"setId":1,"iconIdx":25},{"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":0,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":5,"setId":1,"iconIdx":26},{"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":0,"prevSize":24,"code":59710,"name":"download"},"setIdx":5,"setId":1,"iconIdx":27},{"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":0,"prevSize":32,"code":59737,"name":"spinner2"},"setIdx":1,"setId":5,"iconIdx":0},{"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":2,"prevSize":32,"code":59741,"name":"star-full"},"setIdx":5,"setId":1,"iconIdx":6},{"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":1,"prevSize":32,"code":59742,"name":"star-empty"},"setIdx":5,"setId":1,"iconIdx":7},{"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":0,"prevSize":32,"code":59740,"name":"twitter"},"setIdx":5,"setId":1,"iconIdx":8},{"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":1,"prevSize":32,"code":59732,"name":"hour-glass"},"setIdx":5,"setId":1,"iconIdx":9},{"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":0,"prevSize":32,"code":59731,"name":"spinner"},"setIdx":5,"setId":1,"iconIdx":10},{"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":0,"prevSize":32,"code":59728,"name":"clock"},"setIdx":5,"setId":1,"iconIdx":11},{"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":0,"name":"bin2","prevSize":32,"code":59650},"setIdx":5,"setId":1,"iconIdx":12},{"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":202,"order":91,"prevSize":32,"code":59850},"setIdx":5,"setId":1,"iconIdx":13},{"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":2,"prevSize":32,"code":59715,"name":"elapsed"},"setIdx":5,"setId":1,"iconIdx":14},{"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":0,"prevSize":32,"code":59707,"name":"google"},"setIdx":5,"setId":1,"iconIdx":15},{"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":0,"prevSize":32,"code":59700,"name":"lock"},"setIdx":5,"setId":1,"iconIdx":16},{"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":1,"prevSize":32,"code":59712,"name":"microsoft"},"setIdx":5,"setId":1,"iconIdx":17},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":1,"prevSize":32,"code":59695,"name":"pause"},"setIdx":5,"setId":1,"iconIdx":18},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":0,"prevSize":32,"code":59696,"name":"play"},"setIdx":5,"setId":1,"iconIdx":19},{"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":2,"prevSize":32,"code":59694,"name":"reset"},"setIdx":5,"setId":1,"iconIdx":20},{"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":1,"prevSize":32,"code":59693,"name":"settings2"},"setIdx":5,"setId":1,"iconIdx":21},{"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":1,"prevSize":32,"code":59716,"name":"timeout"},"setIdx":5,"setId":1,"iconIdx":22},{"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":1,"prevSize":32,"code":59699,"name":"unlocked"},"setIdx":5,"setId":1,"iconIdx":23},{"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":1,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":2,"setId":4,"iconIdx":0},{"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":0,"name":"list","prevSize":20,"code":59726},"setIdx":2,"setId":4,"iconIdx":1},{"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":0,"prevSize":20,"code":59708,"name":"info"},"setIdx":5,"setId":1,"iconIdx":103},{"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":3,"setId":3,"iconIdx":0},{"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"],"attrs":[{}],"width":1344,"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59701,"name":"browser"},"setIdx":5,"setId":1,"iconIdx":100},{"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":0,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":5,"setId":1,"iconIdx":101},{"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":0,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":5,"setId":1,"iconIdx":102},{"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,"grid":0,"tags":["prerender"]},"attrs":[{},{},{}],"properties":{"order":114,"id":1,"name":"prerender","prevSize":32,"code":59724},"setIdx":4,"setId":2,"iconIdx":0},{"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,"grid":0,"tags":["circle"]},"attrs":[{}],"properties":{"order":106,"id":0,"name":"circle","prevSize":32,"code":59729},"setIdx":5,"setId":1,"iconIdx":29},{"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,"grid":0,"tags":["control-Slug"]},"attrs":[{},{}],"properties":{"order":103,"id":0,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":5,"setId":1,"iconIdx":31},{"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,"grid":0,"tags":["Tags"]},"attrs":[{},{},{},{}],"properties":{"order":98,"id":0,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":5,"setId":1,"iconIdx":33},{"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,"grid":0,"tags":["activity"]},"attrs":[{}],"properties":{"order":12,"id":36,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":5,"setId":1,"iconIdx":34},{"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,"grid":0,"tags":["add"]},"attrs":[{}],"properties":{"order":13,"id":35,"name":"add, plus","prevSize":32,"code":59653},"setIdx":5,"setId":1,"iconIdx":35},{"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,"grid":0,"tags":["check-circle"]},"attrs":[{}],"properties":{"order":14,"id":34,"name":"check-circle","prevSize":32,"code":59654},"setIdx":5,"setId":1,"iconIdx":36},{"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,"grid":0,"tags":["check-circle-filled"]},"attrs":[{}],"properties":{"order":27,"id":33,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":5,"setId":1,"iconIdx":37},{"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,"grid":0,"tags":["close"]},"attrs":[{}],"properties":{"order":28,"id":32,"name":"close","prevSize":32,"code":59656},"setIdx":5,"setId":1,"iconIdx":38},{"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,"grid":0,"tags":["content"]},"attrs":[{}],"properties":{"order":37,"id":31,"name":"type-References","prevSize":32,"code":59657},"setIdx":5,"setId":1,"iconIdx":39},{"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,"grid":0,"tags":["control-checkbox"]},"attrs":[{}],"properties":{"order":38,"id":30,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":5,"setId":1,"iconIdx":40},{"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,"grid":0,"tags":["control-dropdown"]},"attrs":[{}],"properties":{"order":39,"id":29,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":5,"setId":1,"iconIdx":41},{"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,"grid":0,"tags":["control-input"]},"attrs":[{}],"properties":{"order":41,"id":28,"name":"control-Input","prevSize":32,"code":59660},"setIdx":5,"setId":1,"iconIdx":42},{"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,"grid":0,"tags":["control-radio"]},"attrs":[{}],"properties":{"order":42,"id":27,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":5,"setId":1,"iconIdx":43},{"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,"grid":0,"tags":["control-textarea"]},"attrs":[{}],"properties":{"order":17,"id":26,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":5,"setId":1,"iconIdx":44},{"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,"grid":0,"tags":["control-toggle"]},"attrs":[{}],"properties":{"order":16,"id":25,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":5,"setId":1,"iconIdx":45},{"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,"grid":0,"tags":["copy"]},"attrs":[{}],"properties":{"order":90,"id":24,"name":"copy","prevSize":32,"code":59664},"setIdx":5,"setId":1,"iconIdx":46},{"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,"grid":0,"tags":["dashboard"]},"attrs":[{},{},{}],"properties":{"order":26,"id":23,"name":"dashboard","prevSize":32,"code":59665},"setIdx":5,"setId":1,"iconIdx":47},{"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,"grid":0,"tags":["delete"]},"attrs":[{}],"properties":{"order":29,"id":22,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":5,"setId":1,"iconIdx":48},{"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,"grid":0,"tags":["delete-filled"]},"attrs":[{}],"properties":{"order":36,"id":21,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":5,"setId":1,"iconIdx":49},{"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,"grid":0,"tags":["document-delete"]},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":5,"setId":1,"iconIdx":50},{"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,"grid":0,"tags":["document-disable"]},"attrs":[{}],"properties":{"order":40,"id":19,"name":"document-disable","prevSize":32,"code":59669},"setIdx":5,"setId":1,"iconIdx":51},{"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,"grid":0,"tags":["document-publish"]},"attrs":[{}],"properties":{"order":44,"id":18,"name":"document-publish","prevSize":32,"code":59670},"setIdx":5,"setId":1,"iconIdx":52},{"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,"grid":0,"tags":["drag"]},"attrs":[{}],"properties":{"order":43,"id":17,"name":"drag","prevSize":32,"code":59671},"setIdx":5,"setId":1,"iconIdx":53},{"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,"grid":0,"tags":["filter"]},"attrs":[{}],"properties":{"order":18,"id":16,"name":"filter","prevSize":32,"code":59672},"setIdx":5,"setId":1,"iconIdx":54},{"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":0,"name":"github","prevSize":32,"code":59713},"setIdx":5,"setId":1,"iconIdx":55},{"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,"grid":0,"tags":["help"]},"attrs":[{}],"properties":{"order":19,"id":15,"name":"help","prevSize":32,"code":59673},"setIdx":5,"setId":1,"iconIdx":56},{"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,"grid":0,"tags":["location"]},"attrs":[{}],"properties":{"order":25,"id":13,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":5,"setId":1,"iconIdx":57},{"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,"grid":0,"tags":["logo"]},"attrs":[{}],"properties":{"order":31,"id":12,"name":"logo","prevSize":32,"code":59676},"setIdx":5,"setId":1,"iconIdx":58},{"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,"grid":0,"tags":["media"]},"attrs":[{}],"properties":{"order":30,"id":11,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":5,"setId":1,"iconIdx":59},{"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,"grid":0,"tags":["more"]},"attrs":[{}],"properties":{"order":34,"id":10,"name":"more, dots","prevSize":32,"code":59678},"setIdx":5,"setId":1,"iconIdx":60},{"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,"grid":0,"tags":["pencil"]},"attrs":[{}],"properties":{"order":47,"id":9,"name":"pencil","prevSize":32,"code":59679},"setIdx":5,"setId":1,"iconIdx":61},{"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,"grid":0,"tags":["reference"]},"attrs":[{}],"properties":{"order":45,"id":8,"name":"reference","prevSize":32,"code":59680},"setIdx":5,"setId":1,"iconIdx":62},{"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,"grid":0,"tags":["schemas"]},"attrs":[{},{},{},{}],"properties":{"order":46,"id":7,"name":"schemas","prevSize":32,"code":59681},"setIdx":5,"setId":1,"iconIdx":63},{"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,"grid":0,"tags":["search"]},"attrs":[{}],"properties":{"order":23,"id":6,"name":"search","prevSize":32,"code":59682},"setIdx":5,"setId":1,"iconIdx":64},{"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,"grid":0,"tags":["settings"]},"attrs":[{}],"properties":{"order":22,"id":5,"name":"settings","prevSize":32,"code":59683},"setIdx":5,"setId":1,"iconIdx":65},{"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,"grid":0,"tags":["type-boolean"]},"attrs":[{}],"properties":{"order":21,"id":4,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":5,"setId":1,"iconIdx":66},{"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,"grid":0,"tags":["type-datetime"]},"attrs":[{}],"properties":{"order":24,"id":3,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":5,"setId":1,"iconIdx":67},{"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,"grid":0,"tags":["json"]},"attrs":[{}],"properties":{"order":20,"id":14,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":5,"setId":1,"iconIdx":68},{"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,"grid":0,"tags":["type-number"]},"attrs":[{}],"properties":{"order":32,"id":2,"name":"type-Number","prevSize":32,"code":59686},"setIdx":5,"setId":1,"iconIdx":69},{"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,"grid":0,"tags":["type-string"]},"attrs":[{}],"properties":{"order":48,"id":1,"name":"type-String","prevSize":32,"code":59687},"setIdx":5,"setId":1,"iconIdx":70},{"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,"grid":0,"tags":["user"]},"attrs":[{}],"properties":{"order":33,"id":0,"name":"user","prevSize":32,"code":59688},"setIdx":5,"setId":1,"iconIdx":71},{"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"],"attrs":[{},{},{}],"width":1140,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["control-Tags"]},"attrs":[{},{},{}],"properties":{"order":119,"id":220,"name":"control-Tags","prevSize":32,"code":59747},"setIdx":5,"setId":1,"iconIdx":0},{"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,"grid":14,"tags":["control-Checkboxes"]},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":219,"name":"control-Checkboxes","prevSize":32,"code":59746},"setIdx":5,"setId":1,"iconIdx":1},{"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,"grid":14,"tags":["control-Html"]},"attrs":[{},{},{},{}],"properties":{"order":116,"id":217,"name":"control-Html","prevSize":32,"code":59744},"setIdx":5,"setId":1,"iconIdx":3},{"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"],"attrs":[{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["single-content"]},"attrs":[{},{},{},{}],"properties":{"order":112,"id":214,"name":"single-content","prevSize":32,"code":59736},"setIdx":5,"setId":1,"iconIdx":72},{"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"],"attrs":[{},{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["multiple-content"]},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":213,"name":"multiple-content","prevSize":32,"code":59735},"setIdx":5,"setId":1,"iconIdx":73},{"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,"grid":14,"tags":["type-Array"]},"attrs":[{},{},{},{}],"properties":{"order":108,"id":211,"name":"type-Array","prevSize":32,"code":59734},"setIdx":5,"setId":1,"iconIdx":74},{"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"],"attrs":[{}],"width":366,"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59733,"name":"exclamation"},"setIdx":5,"setId":1,"iconIdx":75},{"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,"grid":14,"tags":["orleans"]},"attrs":[{}],"properties":{"order":99,"id":209,"name":"orleans","prevSize":32,"code":59723},"setIdx":5,"setId":1,"iconIdx":78},{"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,"grid":14,"tags":["document-lock"]},"attrs":[{},{}],"properties":{"order":97,"id":208,"name":"document-lock","prevSize":32,"code":59721},"setIdx":5,"setId":1,"iconIdx":79},{"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,"grid":14,"tags":["document-unpublish"]},"attrs":[{},{}],"properties":{"order":96,"id":207,"name":"document-unpublish","prevSize":32,"code":59711},"setIdx":5,"setId":1,"iconIdx":80},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59648,"name":"angle-down"},"setIdx":5,"setId":1,"iconIdx":81},{"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"],"attrs":[{}],"width":384,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":32,"code":59649,"name":"angle-left"},"setIdx":5,"setId":1,"iconIdx":82},{"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"],"attrs":[{}],"width":347,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":0,"prevSize":32,"code":59697,"name":"angle-right"},"setIdx":5,"setId":1,"iconIdx":83},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":2,"prevSize":32,"code":59651,"name":"angle-up"},"setIdx":5,"setId":1,"iconIdx":84},{"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,"grid":14,"tags":["api"]},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":206,"name":"api","prevSize":32,"code":59717},"setIdx":5,"setId":1,"iconIdx":85},{"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,"grid":14,"tags":["assets"]},"attrs":[{},{},{}],"properties":{"order":95,"id":205,"name":"assets","prevSize":32,"code":59720},"setIdx":5,"setId":1,"iconIdx":86},{"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"],"attrs":[{}],"width":951,"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59709,"name":"bug"},"setIdx":5,"setId":1,"iconIdx":87},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":4,"prevSize":32,"code":59692,"name":"caret-down"},"setIdx":5,"setId":1,"iconIdx":88},{"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"],"attrs":[{}],"width":402,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":6,"prevSize":32,"code":59690,"name":"caret-left"},"setIdx":5,"setId":1,"iconIdx":89},{"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"],"attrs":[{}],"width":329,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59689,"name":"caret-right"},"setIdx":5,"setId":1,"iconIdx":90},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":5,"prevSize":32,"code":59691,"name":"caret-up"},"setIdx":5,"setId":1,"iconIdx":91},{"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,"grid":14,"tags":["content"]},"attrs":[{},{},{},{}],"properties":{"order":93,"id":204,"name":"contents, trigger-ContentChanged","prevSize":32,"code":59718},"setIdx":5,"setId":1,"iconIdx":92},{"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,"grid":14,"tags":["control-date"]},"attrs":[{}],"properties":{"order":71,"id":42,"name":"control-Date","prevSize":32,"code":59702},"setIdx":5,"setId":1,"iconIdx":93},{"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,"grid":14,"tags":["control-date-time"]},"attrs":[{}],"properties":{"order":70,"id":41,"name":"control-DateTime","prevSize":32,"code":59703},"setIdx":5,"setId":1,"iconIdx":94},{"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,"grid":14,"tags":["control-Markdown"]},"attrs":[{}],"properties":{"order":72,"id":43,"name":"control-Markdown","prevSize":32,"code":59704},"setIdx":5,"setId":1,"iconIdx":95},{"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":14,"order":83,"prevSize":32,"code":61450},"setIdx":5,"setId":1,"iconIdx":96},{"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":178,"order":89,"prevSize":32,"code":61641},"setIdx":5,"setId":1,"iconIdx":97},{"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,"grid":14,"tags":["user-o"]},"attrs":[{}],"properties":{"order":64,"id":38,"name":"user-o","prevSize":32,"code":59698},"setIdx":5,"setId":1,"iconIdx":98},{"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,"grid":14,"tags":["webhooks"]},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":203,"name":"rules","prevSize":32,"code":59719},"setIdx":5,"setId":1,"iconIdx":99}],"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,"classSelector":".icon","name":"icomoon"},"historySize":100,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"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":1,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":0,"setId":2,"iconIdx":0},{"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":0,"name":"plus-square","prevSize":24,"code":59752},"setIdx":0,"setId":2,"iconIdx":1},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":1,"setId":1,"iconIdx":4},{"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":1,"id":0,"name":"comments","prevSize":24,"code":59743},"setIdx":1,"setId":1,"iconIdx":5},{"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":2,"prevSize":24,"code":59739,"name":"backup"},"setIdx":1,"setId":1,"iconIdx":6},{"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":0,"prevSize":24,"code":59738,"name":"support"},"setIdx":1,"setId":1,"iconIdx":7},{"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":0,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":1,"setId":1,"iconIdx":8},{"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":0,"prevSize":24,"code":59710,"name":"download"},"setIdx":1,"setId":1,"iconIdx":9},{"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,"grid":16,"tags":["show"]},"attrs":[{},{},{}],"properties":{"order":123,"id":224,"name":"show","prevSize":24,"code":59748},"setIdx":1,"setId":1,"iconIdx":0},{"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,"grid":16,"tags":["show-all"]},"attrs":[{},{},{},{}],"properties":{"order":122,"id":223,"name":"show-all","prevSize":24,"code":59749},"setIdx":1,"setId":1,"iconIdx":1},{"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,"grid":16,"tags":["hide"]},"attrs":[{},{},{}],"properties":{"order":121,"id":222,"name":"hide","prevSize":24,"code":59750},"setIdx":1,"setId":1,"iconIdx":2},{"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,"grid":16,"tags":["hide-all"]},"attrs":[{},{},{},{}],"properties":{"order":120,"id":221,"name":"hide-all","prevSize":24,"code":59751},"setIdx":1,"setId":1,"iconIdx":3},{"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":0,"prevSize":24,"code":59737,"name":"spinner2"},"setIdx":1,"setId":1,"iconIdx":10},{"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":2,"prevSize":24,"code":59741,"name":"star-full"},"setIdx":1,"setId":1,"iconIdx":11},{"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":1,"prevSize":24,"code":59742,"name":"star-empty"},"setIdx":1,"setId":1,"iconIdx":12},{"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":0,"prevSize":24,"code":59740,"name":"twitter"},"setIdx":1,"setId":1,"iconIdx":13},{"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":1,"prevSize":24,"code":59732,"name":"hour-glass"},"setIdx":1,"setId":1,"iconIdx":14},{"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":0,"prevSize":24,"code":59731,"name":"spinner"},"setIdx":1,"setId":1,"iconIdx":15},{"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":0,"prevSize":24,"code":59728,"name":"clock"},"setIdx":1,"setId":1,"iconIdx":16},{"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":0,"name":"bin2","prevSize":24,"code":59650},"setIdx":1,"setId":1,"iconIdx":17},{"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":202,"order":91,"prevSize":24,"code":59850},"setIdx":1,"setId":1,"iconIdx":18},{"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":2,"prevSize":24,"code":59715,"name":"elapsed"},"setIdx":1,"setId":1,"iconIdx":19},{"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":0,"prevSize":24,"code":59707,"name":"google"},"setIdx":1,"setId":1,"iconIdx":20},{"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":0,"prevSize":24,"code":59700,"name":"lock"},"setIdx":1,"setId":1,"iconIdx":21},{"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":1,"prevSize":24,"code":59712,"name":"microsoft"},"setIdx":1,"setId":1,"iconIdx":22},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":1,"prevSize":24,"code":59695,"name":"pause"},"setIdx":1,"setId":1,"iconIdx":23},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":0,"prevSize":24,"code":59696,"name":"play"},"setIdx":1,"setId":1,"iconIdx":24},{"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":2,"prevSize":24,"code":59694,"name":"reset"},"setIdx":1,"setId":1,"iconIdx":25},{"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":1,"prevSize":24,"code":59693,"name":"settings2"},"setIdx":1,"setId":1,"iconIdx":26},{"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":1,"prevSize":24,"code":59716,"name":"timeout"},"setIdx":1,"setId":1,"iconIdx":27},{"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":1,"prevSize":24,"code":59699,"name":"unlocked"},"setIdx":1,"setId":1,"iconIdx":28},{"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":1,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":1,"setId":1,"iconIdx":29},{"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":0,"name":"list","prevSize":20,"code":59726},"setIdx":1,"setId":1,"iconIdx":30},{"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":0,"prevSize":20,"code":59708,"name":"info"},"setIdx":1,"setId":1,"iconIdx":31},{"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":1,"setId":1,"iconIdx":32},{"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"],"attrs":[{}],"width":1344,"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59701,"name":"browser"},"setIdx":1,"setId":1,"iconIdx":33},{"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":0,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":1,"setId":1,"iconIdx":34},{"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":0,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":1,"setId":1,"iconIdx":35},{"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,"grid":0,"tags":["prerender"]},"attrs":[{},{},{}],"properties":{"order":114,"id":1,"name":"prerender","prevSize":32,"code":59724},"setIdx":1,"setId":1,"iconIdx":36},{"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,"grid":0,"tags":["circle"]},"attrs":[{}],"properties":{"order":106,"id":0,"name":"circle","prevSize":32,"code":59729},"setIdx":1,"setId":1,"iconIdx":37},{"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,"grid":0,"tags":["control-Slug"]},"attrs":[{},{}],"properties":{"order":103,"id":0,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":1,"setId":1,"iconIdx":38},{"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,"grid":0,"tags":["Tags"]},"attrs":[{},{},{},{}],"properties":{"order":98,"id":0,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":1,"setId":1,"iconIdx":39},{"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,"grid":0,"tags":["activity"]},"attrs":[{}],"properties":{"order":12,"id":36,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":1,"setId":1,"iconIdx":40},{"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,"grid":0,"tags":["add"]},"attrs":[{}],"properties":{"order":13,"id":35,"name":"add, plus","prevSize":32,"code":59653},"setIdx":1,"setId":1,"iconIdx":41},{"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,"grid":0,"tags":["check-circle"]},"attrs":[{}],"properties":{"order":14,"id":34,"name":"check-circle","prevSize":32,"code":59654},"setIdx":1,"setId":1,"iconIdx":42},{"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,"grid":0,"tags":["check-circle-filled"]},"attrs":[{}],"properties":{"order":27,"id":33,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":1,"setId":1,"iconIdx":43},{"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,"grid":0,"tags":["close"]},"attrs":[{}],"properties":{"order":28,"id":32,"name":"close","prevSize":32,"code":59656},"setIdx":1,"setId":1,"iconIdx":44},{"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,"grid":0,"tags":["content"]},"attrs":[{}],"properties":{"order":37,"id":31,"name":"type-References","prevSize":32,"code":59657},"setIdx":1,"setId":1,"iconIdx":45},{"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,"grid":0,"tags":["control-checkbox"]},"attrs":[{}],"properties":{"order":38,"id":30,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":1,"setId":1,"iconIdx":46},{"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,"grid":0,"tags":["control-dropdown"]},"attrs":[{}],"properties":{"order":39,"id":29,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":1,"setId":1,"iconIdx":47},{"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,"grid":0,"tags":["control-input"]},"attrs":[{}],"properties":{"order":41,"id":28,"name":"control-Input","prevSize":32,"code":59660},"setIdx":1,"setId":1,"iconIdx":48},{"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,"grid":0,"tags":["control-radio"]},"attrs":[{}],"properties":{"order":42,"id":27,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":1,"setId":1,"iconIdx":49},{"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,"grid":0,"tags":["control-textarea"]},"attrs":[{}],"properties":{"order":17,"id":26,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":1,"setId":1,"iconIdx":50},{"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,"grid":0,"tags":["control-toggle"]},"attrs":[{}],"properties":{"order":16,"id":25,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":1,"setId":1,"iconIdx":51},{"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,"grid":0,"tags":["copy"]},"attrs":[{}],"properties":{"order":90,"id":24,"name":"copy","prevSize":32,"code":59664},"setIdx":1,"setId":1,"iconIdx":52},{"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,"grid":0,"tags":["dashboard"]},"attrs":[{},{},{}],"properties":{"order":26,"id":23,"name":"dashboard","prevSize":32,"code":59665},"setIdx":1,"setId":1,"iconIdx":53},{"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,"grid":0,"tags":["delete"]},"attrs":[{}],"properties":{"order":29,"id":22,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":1,"setId":1,"iconIdx":54},{"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,"grid":0,"tags":["delete-filled"]},"attrs":[{}],"properties":{"order":36,"id":21,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":1,"setId":1,"iconIdx":55},{"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,"grid":0,"tags":["document-delete"]},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":1,"setId":1,"iconIdx":56},{"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,"grid":0,"tags":["document-disable"]},"attrs":[{}],"properties":{"order":40,"id":19,"name":"document-disable","prevSize":32,"code":59669},"setIdx":1,"setId":1,"iconIdx":57},{"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,"grid":0,"tags":["document-publish"]},"attrs":[{}],"properties":{"order":44,"id":18,"name":"document-publish","prevSize":32,"code":59670},"setIdx":1,"setId":1,"iconIdx":58},{"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,"grid":0,"tags":["drag"]},"attrs":[{}],"properties":{"order":43,"id":17,"name":"drag","prevSize":32,"code":59671},"setIdx":1,"setId":1,"iconIdx":59},{"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,"grid":0,"tags":["filter"]},"attrs":[{}],"properties":{"order":18,"id":16,"name":"filter","prevSize":32,"code":59672},"setIdx":1,"setId":1,"iconIdx":60},{"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":0,"name":"github","prevSize":32,"code":59713},"setIdx":1,"setId":1,"iconIdx":61},{"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,"grid":0,"tags":["help"]},"attrs":[{}],"properties":{"order":19,"id":15,"name":"help","prevSize":32,"code":59673},"setIdx":1,"setId":1,"iconIdx":62},{"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,"grid":0,"tags":["location"]},"attrs":[{}],"properties":{"order":25,"id":13,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":1,"setId":1,"iconIdx":63},{"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,"grid":0,"tags":["logo"]},"attrs":[{}],"properties":{"order":31,"id":12,"name":"logo","prevSize":32,"code":59676},"setIdx":1,"setId":1,"iconIdx":64},{"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,"grid":0,"tags":["media"]},"attrs":[{}],"properties":{"order":30,"id":11,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":1,"setId":1,"iconIdx":65},{"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,"grid":0,"tags":["more"]},"attrs":[{}],"properties":{"order":34,"id":10,"name":"more, dots","prevSize":32,"code":59678},"setIdx":1,"setId":1,"iconIdx":66},{"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,"grid":0,"tags":["pencil"]},"attrs":[{}],"properties":{"order":47,"id":9,"name":"pencil","prevSize":32,"code":59679},"setIdx":1,"setId":1,"iconIdx":67},{"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,"grid":0,"tags":["reference"]},"attrs":[{}],"properties":{"order":45,"id":8,"name":"reference","prevSize":32,"code":59680},"setIdx":1,"setId":1,"iconIdx":68},{"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,"grid":0,"tags":["schemas"]},"attrs":[{},{},{},{}],"properties":{"order":46,"id":7,"name":"schemas","prevSize":32,"code":59681},"setIdx":1,"setId":1,"iconIdx":69},{"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,"grid":0,"tags":["search"]},"attrs":[{}],"properties":{"order":23,"id":6,"name":"search","prevSize":32,"code":59682},"setIdx":1,"setId":1,"iconIdx":70},{"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,"grid":0,"tags":["settings"]},"attrs":[{}],"properties":{"order":22,"id":5,"name":"settings","prevSize":32,"code":59683},"setIdx":1,"setId":1,"iconIdx":71},{"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,"grid":0,"tags":["type-boolean"]},"attrs":[{}],"properties":{"order":21,"id":4,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":1,"setId":1,"iconIdx":72},{"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,"grid":0,"tags":["type-datetime"]},"attrs":[{}],"properties":{"order":24,"id":3,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":1,"setId":1,"iconIdx":73},{"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,"grid":0,"tags":["json"]},"attrs":[{}],"properties":{"order":20,"id":14,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":1,"setId":1,"iconIdx":74},{"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,"grid":0,"tags":["type-number"]},"attrs":[{}],"properties":{"order":32,"id":2,"name":"type-Number","prevSize":32,"code":59686},"setIdx":1,"setId":1,"iconIdx":75},{"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,"grid":0,"tags":["type-string"]},"attrs":[{}],"properties":{"order":48,"id":1,"name":"type-String","prevSize":32,"code":59687},"setIdx":1,"setId":1,"iconIdx":76},{"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,"grid":0,"tags":["user"]},"attrs":[{}],"properties":{"order":33,"id":0,"name":"user","prevSize":32,"code":59688},"setIdx":1,"setId":1,"iconIdx":77},{"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"],"attrs":[{},{},{}],"width":1140,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["control-Tags"]},"attrs":[{},{},{}],"properties":{"order":119,"id":220,"name":"control-Tags","prevSize":32,"code":59747},"setIdx":1,"setId":1,"iconIdx":78},{"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,"grid":14,"tags":["control-Checkboxes"]},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":219,"name":"control-Checkboxes","prevSize":32,"code":59746},"setIdx":1,"setId":1,"iconIdx":79},{"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,"grid":14,"tags":["control-Html"]},"attrs":[{},{},{},{}],"properties":{"order":116,"id":217,"name":"control-Html","prevSize":32,"code":59744},"setIdx":1,"setId":1,"iconIdx":80},{"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"],"attrs":[{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["single-content"]},"attrs":[{},{},{},{}],"properties":{"order":112,"id":214,"name":"single-content","prevSize":32,"code":59736},"setIdx":1,"setId":1,"iconIdx":81},{"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"],"attrs":[{},{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["multiple-content"]},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":213,"name":"multiple-content","prevSize":32,"code":59735},"setIdx":1,"setId":1,"iconIdx":82},{"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,"grid":14,"tags":["type-Array"]},"attrs":[{},{},{},{}],"properties":{"order":108,"id":211,"name":"type-Array","prevSize":32,"code":59734},"setIdx":1,"setId":1,"iconIdx":83},{"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"],"attrs":[{}],"width":366,"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59733,"name":"exclamation"},"setIdx":1,"setId":1,"iconIdx":84},{"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,"grid":14,"tags":["orleans"]},"attrs":[{}],"properties":{"order":99,"id":209,"name":"orleans","prevSize":32,"code":59723},"setIdx":1,"setId":1,"iconIdx":85},{"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,"grid":14,"tags":["document-lock"]},"attrs":[{},{}],"properties":{"order":97,"id":208,"name":"document-lock","prevSize":32,"code":59721},"setIdx":1,"setId":1,"iconIdx":86},{"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,"grid":14,"tags":["document-unpublish"]},"attrs":[{},{}],"properties":{"order":96,"id":207,"name":"document-unpublish","prevSize":32,"code":59711},"setIdx":1,"setId":1,"iconIdx":87},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59648,"name":"angle-down"},"setIdx":1,"setId":1,"iconIdx":88},{"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"],"attrs":[{}],"width":384,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":32,"code":59649,"name":"angle-left"},"setIdx":1,"setId":1,"iconIdx":89},{"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"],"attrs":[{}],"width":347,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":0,"prevSize":32,"code":59697,"name":"angle-right"},"setIdx":1,"setId":1,"iconIdx":90},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":2,"prevSize":32,"code":59651,"name":"angle-up"},"setIdx":1,"setId":1,"iconIdx":91},{"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,"grid":14,"tags":["api"]},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":206,"name":"api","prevSize":32,"code":59717},"setIdx":1,"setId":1,"iconIdx":92},{"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,"grid":14,"tags":["assets"]},"attrs":[{},{},{}],"properties":{"order":95,"id":205,"name":"assets","prevSize":32,"code":59720},"setIdx":1,"setId":1,"iconIdx":93},{"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"],"attrs":[{}],"width":951,"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59709,"name":"bug"},"setIdx":1,"setId":1,"iconIdx":94},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":4,"prevSize":32,"code":59692,"name":"caret-down"},"setIdx":1,"setId":1,"iconIdx":95},{"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"],"attrs":[{}],"width":402,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":6,"prevSize":32,"code":59690,"name":"caret-left"},"setIdx":1,"setId":1,"iconIdx":96},{"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"],"attrs":[{}],"width":329,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59689,"name":"caret-right"},"setIdx":1,"setId":1,"iconIdx":97},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":5,"prevSize":32,"code":59691,"name":"caret-up"},"setIdx":1,"setId":1,"iconIdx":98},{"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,"grid":14,"tags":["content"]},"attrs":[{},{},{},{}],"properties":{"order":93,"id":204,"name":"contents, trigger-ContentChanged","prevSize":32,"code":59718},"setIdx":1,"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,"grid":14,"tags":["control-date"]},"attrs":[{}],"properties":{"order":71,"id":42,"name":"control-Date","prevSize":32,"code":59702},"setIdx":1,"setId":1,"iconIdx":100},{"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,"grid":14,"tags":["control-date-time"]},"attrs":[{}],"properties":{"order":70,"id":41,"name":"control-DateTime","prevSize":32,"code":59703},"setIdx":1,"setId":1,"iconIdx":101},{"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,"grid":14,"tags":["control-Markdown"]},"attrs":[{}],"properties":{"order":72,"id":43,"name":"control-Markdown","prevSize":32,"code":59704},"setIdx":1,"setId":1,"iconIdx":102},{"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":14,"order":83,"prevSize":32,"code":61450},"setIdx":1,"setId":1,"iconIdx":103},{"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":178,"order":89,"prevSize":32,"code":61641},"setIdx":1,"setId":1,"iconIdx":104},{"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,"grid":14,"tags":["user-o"]},"attrs":[{}],"properties":{"order":64,"id":38,"name":"user-o","prevSize":32,"code":59698},"setIdx":1,"setId":1,"iconIdx":105},{"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,"grid":14,"tags":["webhooks"]},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":203,"name":"rules","prevSize":32,"code":59719},"setIdx":1,"setId":1,"iconIdx":106}],"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,"classSelector":".icon","name":"icomoon"},"historySize":100,"gridSize":16}} \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/style.css b/src/Squidex/app/theme/icomoon/style.css index b527fd1a2..99bf1be8f 100644 --- a/src/Squidex/app/theme/icomoon/style.css +++ b/src/Squidex/app/theme/icomoon/style.css @@ -1,10 +1,10 @@ @font-face { font-family: 'icomoon'; - src: url('fonts/icomoon.eot?2tmnw3'); - src: url('fonts/icomoon.eot?2tmnw3#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?2tmnw3') format('truetype'), - url('fonts/icomoon.woff?2tmnw3') format('woff'), - url('fonts/icomoon.svg?2tmnw3#icomoon') format('svg'); + src: url('fonts/icomoon.eot?5dzhok'); + src: url('fonts/icomoon.eot?5dzhok#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?5dzhok') format('truetype'), + url('fonts/icomoon.woff?5dzhok') format('woff'), + url('fonts/icomoon.svg?5dzhok#icomoon') format('svg'); font-weight: normal; font-style: normal; } @@ -24,6 +24,12 @@ -moz-osx-font-smoothing: grayscale; } +.icon-minus-square:before { + content: "\e969"; +} +.icon-plus-square:before { + content: "\e968"; +} .icon-drag2:before { content: "\e961"; } @@ -42,6 +48,18 @@ .icon-download:before { content: "\e93e"; } +.icon-show:before { + content: "\e964"; +} +.icon-show-all:before { + content: "\e965"; +} +.icon-hide:before { + content: "\e966"; +} +.icon-hide-all:before { + content: "\e967"; +} .icon-spinner2:before { content: "\e959"; } From 61821367eb1839f09398243f8878d969fe5fd76a Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 4 Dec 2018 19:02:14 +0100 Subject: [PATCH 24/33] Clone button for array item. --- .../shared/array-editor.component.html | 1 + .../content/shared/array-editor.component.ts | 4 +- .../content/shared/array-item.component.html | 21 +- .../content/shared/array-item.component.ts | 3 + .../app/shared/state/contents.forms.ts | 8 +- .../app/theme/icomoon/demo-files/demo.css | 6 +- src/Squidex/app/theme/icomoon/demo.html | 1418 ++++++++++------- .../app/theme/icomoon/fonts/icomoon.eot | Bin 27384 -> 27568 bytes .../app/theme/icomoon/fonts/icomoon.svg | 1 + .../app/theme/icomoon/fonts/icomoon.ttf | Bin 27220 -> 27404 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 27296 -> 27480 bytes src/Squidex/app/theme/icomoon/selection.json | 2 +- src/Squidex/app/theme/icomoon/style.css | 241 +-- 13 files changed, 1020 insertions(+), 685 deletions(-) diff --git a/src/Squidex/app/features/content/shared/array-editor.component.html b/src/Squidex/app/features/content/shared/array-editor.component.html index 7516160e0..61ccd1eda 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.html +++ b/src/Squidex/app/features/content/shared/array-editor.component.html @@ -11,6 +11,7 @@ [language]="language" [languages]="languages" (toggle)="hide($event)" + (cloning)="addItem(itemForm.value)" (removing)="removeItem(i)">
diff --git a/src/Squidex/app/features/content/shared/array-editor.component.ts b/src/Squidex/app/features/content/shared/array-editor.component.ts index aa1f9a47d..b4164bcde 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.ts +++ b/src/Squidex/app/features/content/shared/array-editor.component.ts @@ -47,8 +47,8 @@ export class ArrayEditorComponent { this.form.removeArrayItem(this.field, this.language, index); } - public addItem() { - this.form.insertArrayItem(this.field, this.language); + public addItem(value: {}) { + this.form.insertArrayItem(this.field, this.language, value); } public sort(controls: AbstractControl[]) { diff --git a/src/Squidex/app/features/content/shared/array-item.component.html b/src/Squidex/app/features/content/shared/array-item.component.html index 583ae798b..85a98ef24 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.html +++ b/src/Squidex/app/features/content/shared/array-item.component.html @@ -5,17 +5,24 @@ Item #{{index + 1}} - + + - + + + + + +
diff --git a/src/Squidex/app/features/content/shared/array-item.component.ts b/src/Squidex/app/features/content/shared/array-item.component.ts index 1aeb77d69..dab7b366a 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.ts +++ b/src/Squidex/app/features/content/shared/array-item.component.ts @@ -28,6 +28,9 @@ export class ArrayItemComponent implements OnChanges { @Output() public removing = new EventEmitter(); + @Output() + public cloning = new EventEmitter(); + @Output() public toggle = new EventEmitter(); diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index 9d01a9c1c..cb8c61445 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -374,22 +374,22 @@ export class EditContentForm extends Form { this.findArrayItemForm(field, language).removeAt(index); } - public insertArrayItem(field: RootFieldDto, language: AppLanguageDto) { + public insertArrayItem(field: RootFieldDto, language: AppLanguageDto, value?: {}) { if (field.nested.length > 0) { const formControl = this.findArrayItemForm(field, language); - this.addArrayItem(field, language, formControl); + this.addArrayItem(field, language, formControl, value); } } - private addArrayItem(field: RootFieldDto, language: AppLanguageDto | null, partitionForm: FormArray) { + private addArrayItem(field: RootFieldDto, language: AppLanguageDto | null, partitionForm: FormArray, value?: {}) { const itemForm = new FormGroup({}); let isOptional = field.isLocalizable && !!language && language.isOptional; for (let nested of field.nested) { const nestedValidators = FieldValidatorsFactory.createValidators(nested, isOptional); - const nestedDefault = FieldDefaultValue.get(nested); + const nestedDefault = value ? value[nested.name] : FieldDefaultValue.get(nested); itemForm.setControl(nested.name, new FormControl(nestedDefault, nestedValidators)); } diff --git a/src/Squidex/app/theme/icomoon/demo-files/demo.css b/src/Squidex/app/theme/icomoon/demo-files/demo.css index e74013014..1d2e3901d 100644 --- a/src/Squidex/app/theme/icomoon/demo-files/demo.css +++ b/src/Squidex/app/theme/icomoon/demo-files/demo.css @@ -147,16 +147,16 @@ p { font-size: 16px; } .fs1 { - font-size: 24px; + font-size: 28px; } .fs2 { font-size: 24px; } .fs3 { - font-size: 20px; + font-size: 24px; } .fs4 { - font-size: 32px; + font-size: 20px; } .fs5 { font-size: 32px; diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index 10b155143..037a4ed76 100644 --- a/src/Squidex/app/theme/icomoon/demo.html +++ b/src/Squidex/app/theme/icomoon/demo.html @@ -9,20 +9,20 @@
-

Font Name: icomoon (Glyphs: 109)

+

Font Name: icomoon (Glyphs: 110)

-

Grid Size: 24

+

Grid Size: 14

- + - icon-minus-square + icon-clone
- - + +
liga: @@ -31,14 +31,14 @@
- + - icon-plus-square + icon-control-Tags
- - + +
liga: @@ -47,14 +47,14 @@
- + - icon-drag2 + icon-control-Checkboxes
- - + +
liga: @@ -63,14 +63,14 @@
- + - icon-comments + icon-control-Html
- - + +
liga: @@ -79,14 +79,14 @@
- + - icon-backup + icon-single-content
- - + +
liga: @@ -95,14 +95,14 @@
- + - icon-support + icon-multiple-content
- - + +
liga: @@ -111,14 +111,14 @@
- + - icon-control-RichText + icon-type-Array
- - + +
liga: @@ -127,337 +127,401 @@
- + - icon-download + icon-exclamation
- - + +
liga:
-
-
-

Grid Size: 16

-
+
- + - icon-show + icon-orleans
- - + +
liga:
-
+
- + - icon-show-all + icon-document-lock
- - + +
liga:
-
+
- + - icon-hide + icon-document-unpublish
- - + +
liga:
-
+
- + - icon-hide-all + icon-angle-down
- - + +
liga:
-
+
- + - icon-spinner2 + icon-angle-left
- - + +
liga:
-
+
- + - icon-star-full + icon-angle-right
- - + +
liga:
-
+
- + - icon-star-empty + icon-angle-up
- - + +
liga:
-
+
- + - icon-twitter + icon-api
- - + +
liga:
-
+
- + - icon-hour-glass + icon-assets
- - + +
liga:
-
+
- + - icon-spinner + icon-bug
- - + +
liga:
-
+
- + - icon-clock + icon-caret-down
- - + +
liga:
-
+
- + - icon-bin2 + icon-caret-left
- - + +
liga:
-
+
- + - icon-earth + icon-caret-right
- - + +
liga: - +
-
+
- + - icon-elapsed + icon-caret-up
- - + +
liga:
-
+
- + - icon-google + icon-contents
- - + +
liga:
-
+
- + - icon-lock + icon-trigger-ContentChanged
- - + +
liga:
-
+
- + - icon-microsoft + icon-control-Date
- - + +
liga:
-
+
- + - icon-pause + icon-control-DateTime
- - + +
liga:
-
+
- + - icon-play + icon-control-Markdown
- - -
+ + +
liga:
+
+
+ + + + icon-grid +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-list1 +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-user-o +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-rules +
+
+ + +
+
+ liga: + +
+
+
+
+

Grid Size: 24

- + - icon-reset + icon-minus-square
- - + +
liga: @@ -466,14 +530,14 @@
- + - icon-settings2 + icon-plus-square
- - + +
liga: @@ -482,14 +546,14 @@
- + - icon-timeout + icon-drag2
- - + +
liga: @@ -498,132 +562,318 @@
- + - icon-unlocked + icon-comments
- - + +
liga:
-
-
-

Grid Size: 20

-
+
- + - icon-grid1 + icon-backup
- - + +
liga:
-
+
- + - icon-list + icon-support
- - + +
liga:
-
+
- + - icon-info + icon-control-RichText
- - + +
liga:
-
-
-

Grid Size: 32

-
+
- + - icon-control-Color + icon-download
- - + +
liga:
-
+
- + - icon-browser + icon-hour-glass
- - + +
liga:
-
+
- + - icon-checkmark + icon-spinner
- - + +
liga:
-
+
- + - icon-control-Stars + icon-clock
- - + + +
+
+ liga: + +
+
+
+
+ + + + icon-bin2 +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-earth +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-elapsed +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-google +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-lock +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-microsoft +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-pause +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-play +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-reset +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-settings2 +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-timeout +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-unlocked +
+
+ +
liga: @@ -632,433 +882,455 @@
-

Grid Size: Unknown

-
+

Grid Size: 16

+
+
+ + + + icon-show +
+
+ + +
+
+ liga: + +
+
+
- + - icon-prerender + icon-show-all
- - + +
liga:
-
+
- + - icon-circle + icon-hide
- - + +
liga:
-
+
- + - icon-control-Slug + icon-hide-all
- - + +
liga:
-
+
- + - icon-type-Tags + icon-spinner2
- - + +
liga:
-
+
- + - icon-activity + icon-star-full
- - + +
liga:
-
+
- + - icon-history + icon-star-empty
- - + +
liga:
-
+
- + - icon-time + icon-twitter
- - + +
liga:
-
+
- + - icon-add + icon-hour-glass
- - + +
liga:
-
+
- + - icon-plus + icon-spinner
- - + +
liga:
-
+
- + - icon-check-circle + icon-clock
- - + +
liga:
-
+
- + - icon-check-circle-filled + icon-bin2
- - + +
liga:
-
+
- + - icon-close + icon-earth
- - + +
liga: - +
-
+
- + - icon-type-References + icon-elapsed
- - + +
liga:
-
+
- + - icon-control-Checkbox + icon-google
- - + +
liga:
-
+
- + - icon-control-Dropdown + icon-lock
- - + +
liga:
-
+
- + - icon-control-Input + icon-microsoft
- - + +
liga:
-
+
- + - icon-control-Radio + icon-pause
- - + +
liga:
-
+
- + - icon-control-TextArea + icon-play
- - + +
liga:
-
+
- + - icon-control-Toggle + icon-reset
- - + +
liga:
-
+
- + - icon-copy + icon-settings2
- - + +
liga:
-
+
- + - icon-dashboard + icon-timeout
- - + +
liga:
-
+
- + - icon-delete + icon-unlocked
- - + +
liga:
-
+
+
+

Grid Size: 20

+
- + - icon-bin + icon-grid1
- - + +
liga:
-
+
- + - icon-delete-filled + icon-list
- - + +
liga:
-
+
- + - icon-document-delete + icon-info
- - + +
liga:
-
+
- + - icon-document-disable + icon-control-Stars
- - + +
liga:
+
+
+

Grid Size: 32

- + - icon-document-publish + icon-control-Color
- - + +
liga: @@ -1067,14 +1339,14 @@
- + - icon-drag + icon-browser
- - + +
liga: @@ -1083,14 +1355,14 @@
- + - icon-filter + icon-checkmark
- - + +
liga: @@ -1099,385 +1371,385 @@
- + - icon-github + icon-control-Stars
- - + +
liga:
-
+
+
+

Grid Size: Unknown

+
- + - icon-help + icon-prerender
- - + +
liga:
-
+
- + - icon-location + icon-circle
- - + +
liga:
-
+
- + - icon-control-Map + icon-control-Slug
- - + +
liga:
-
+
- + - icon-type-Geolocation + icon-type-Tags
- - + +
liga:
-
+
-
- - + +
liga:
-
+
- + - icon-media + icon-history
- - + +
liga:
-
+
- + - icon-type-Assets + icon-time
- - + +
liga:
-
+
- + - icon-trigger-AssetChanged + icon-add
- - + +
liga:
-
+
- + - icon-more + icon-plus
- - + +
liga:
-
+
- + - icon-dots + icon-check-circle
- - + +
liga:
-
+
- + - icon-pencil + icon-check-circle-filled
- - + +
liga:
-
+
- + - icon-reference + icon-close
- - + +
liga:
-
+
- + - icon-schemas + icon-type-References
- - + +
liga:
-
+
- + - icon-search + icon-control-Checkbox
- - + +
liga:
-
+
- + - icon-settings + icon-control-Dropdown
- - + +
liga:
-
+
- + - icon-type-Boolean + icon-control-Input
- - + +
liga:
-
+
- + - icon-type-DateTime + icon-control-Radio
- - + +
liga:
-
+
- + - icon-type-Json + icon-control-TextArea
- - + +
liga:
-
+
- + - icon-json + icon-control-Toggle
- - + +
liga:
-
+
- + - icon-type-Number + icon-copy
- - + +
liga:
-
+
- + - icon-type-String + icon-dashboard
-
- - +
+ +
liga:
-
+
- + - icon-user + icon-delete
- - + +
liga:
-
-
-

Grid Size: 14

- + - icon-control-Tags + icon-bin
- - + +
liga: @@ -1486,14 +1758,14 @@
- + - icon-control-Checkboxes + icon-delete-filled
- - + +
liga: @@ -1502,14 +1774,14 @@
- + - icon-control-Html + icon-document-delete
- - + +
liga: @@ -1518,14 +1790,14 @@
- + - icon-single-content + icon-document-disable
- - + +
liga: @@ -1534,14 +1806,14 @@
- + - icon-multiple-content + icon-document-publish
- - + +
liga: @@ -1550,14 +1822,14 @@
- + - icon-type-Array + icon-drag
- - + +
liga: @@ -1566,14 +1838,14 @@
- + - icon-exclamation + icon-filter
- - + +
liga: @@ -1582,14 +1854,14 @@
- + - icon-orleans + icon-github
- - + +
liga: @@ -1598,14 +1870,14 @@
- + - icon-document-lock + icon-help
- - + +
liga: @@ -1614,14 +1886,14 @@
- + - icon-document-unpublish + icon-location
- - + +
liga: @@ -1630,14 +1902,14 @@
- + - icon-angle-down + icon-control-Map
- - + +
liga: @@ -1646,14 +1918,14 @@
- + - icon-angle-left + icon-type-Geolocation
- - + +
liga: @@ -1662,14 +1934,14 @@
- + - icon-angle-right + icon-logo
- - + +
liga: @@ -1678,14 +1950,14 @@
- + - icon-angle-up + icon-media
- - + +
liga: @@ -1694,14 +1966,14 @@
- + - icon-api + icon-type-Assets
- - + +
liga: @@ -1710,14 +1982,14 @@
- + - icon-assets + icon-trigger-AssetChanged
- - + +
liga: @@ -1726,14 +1998,14 @@
- + - icon-bug + icon-more
- - + +
liga: @@ -1742,14 +2014,14 @@
- + - icon-caret-down + icon-dots
- - + +
liga: @@ -1758,14 +2030,14 @@
- + - icon-caret-left + icon-pencil
- - + +
liga: @@ -1774,14 +2046,14 @@
- + - icon-caret-right + icon-reference
- - + +
liga: @@ -1790,14 +2062,14 @@
- + - icon-caret-up + icon-schemas
- - + +
liga: @@ -1806,14 +2078,14 @@
- + - icon-contents + icon-search
- - + +
liga: @@ -1822,14 +2094,14 @@
- + - icon-trigger-ContentChanged + icon-settings
- - + +
liga: @@ -1838,14 +2110,14 @@
- + - icon-control-Date + icon-type-Boolean
- - + +
liga: @@ -1854,14 +2126,14 @@
- + - icon-control-DateTime + icon-type-DateTime
- - + +
liga: @@ -1870,14 +2142,14 @@
- + - icon-control-Markdown + icon-type-Json
- - + +
liga: @@ -1886,14 +2158,14 @@
- + - icon-grid + icon-json
- - + +
liga: @@ -1902,14 +2174,14 @@
- + - icon-list1 + icon-type-Number
- - + +
liga: @@ -1918,14 +2190,14 @@
- + - icon-user-o + icon-type-String
- - + +
liga: @@ -1934,14 +2206,14 @@
- + - icon-rules + icon-user
- - + +
liga: diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 4591299f2be956ea1ee177ab7bbc5339187fbc0e..92b70c720a01cb89f1d5431525444963cee75cf6 100644 GIT binary patch delta 445 zcmexym2ty$Mz#&v3=BNk6WPpIKF^#zYqDde$i$FBX4l(d6Hmz0+jbvqWnf^Oz`&5Q zA|o|1MP$3mat4Mp3kC)TvkagBClhNikY51gt7PPsRIJ`B?GEHm0qQxClb@V;Z1$QK z28N6np!~Dk#EJrjPR1w(hD;YAUm-6sH+7~L=WifC1*pEQAiubTff*>nko5*6&%n$) zIhnDCF>CS%MrGEe0%`m!HcK#_OsEH{`M;fofq6TF0D~ffEdzt9poyBYq7s{^poo~U zqLG=Yu%HMVP(aO8(8LTVASS9Vs%(l-W6db4jF4pB&dvUJ5<53HJ5wGzx2Kuv-$`m_ zW@=1%s%E#nU{WzLs%B=YOnGW%LIxmZFma~5zmuRcrlxAQqoX;vxjFt$<^Y`AJeOQ&7-A$~ d6atiH1mYsb2nI2bQU<2U53__f2WKv21OOYnaX!N9;^mH`ytWMVA>@(%#{DjB&Y70dTZy94=8fO?MPRiS-oZ-14H@> zp!}2E#EJrj4#p@3hKwE{Um-6sH+7~L=Wif?4N!esL4I)w12a&DA~? + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index e350edc09f58a3b6a20f5f324fe4e86fdc9442da..db00583bc2e07b4c3aceb67f05d65152cd56b30e 100644 GIT binary patch delta 442 zcmca|g|X)v;{?Te*V|$Y42&`i3=BExiNys#S^&uJ0MZ=kIhAR)-A7x2{0R&UDJwEk z6H`RCt1M?=NV5RSn`Hn6IGI?BfqalYm5khyiq(6i-GTfmKs_gN@{<#f&0f>Oz>pCG zlz*0+SW&>x$r#1Jkm&;CE952Srb^88;`|L1NC9eSE66V{VPFPIF=V}&xMMP7)?^<> zW!9wvY5XfTmoT18s0YgZ-_F9oydCIBMFv|2230{5HDyI5Hc>$lF=Is|GgDzf5jLQJ znyH|P8Bjn>R9#fr6rskNQB)Zr$-JGL{qH1pZfeb8vHW{GH4JG)Ijo7ibR98=GyCLYQS{ z&7S!=p5Nvx12+rEZwxnd3WQ87coXK T0HX&8m?k@B32$DXv6K-2&Gl^$ delta 247 zcmeCV#(3ol;{?Tem)pV&42&`i3=BExiNys#S^&uJ0MZ=kIhAQE9eFpN`?ZpRAr&NVmH`ytWMVA>@(%#{DjB&Y70dTZy94=8fO?MPRiS-oZ-14H@> zp!}2E#EJrj4#p@3hKwE{Um-6sH&tS$7w2!Fz#5>2wu1cP5(Z|V6hoHD#2u3vGbj5n zDzh#TNabI?xrFg#!sfS0!OSxHqDh|d{5D@1xLH6-8E)uAi@@l~F=^(Eg`20O9blXs Xk@1-OkKqo(KMagO>B7xknTHqwgzZT! diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.woff b/src/Squidex/app/theme/icomoon/fonts/icomoon.woff index 45212faf89dfdacf3bddf8bedecaf6f4ff8575cb..7da959a152921e5c76b34465f2c29cc9e610e1a2 100644 GIT binary patch delta 470 zcmZ2*mGQs@b)r6(2_FfcG)0SaX~|8jD9~YG$eaKaPypjj#;Cl++*F|02B5|^5T5D9 z`MV&$xCH2Ki-~_`GiFVm!Klo-R3MFi#pVNyCll(K85sU=XJKI8&LF^`$Y9IBpeksh zrmU#MCMqZ*W~^vrW-2Tw!UhyjGZi#30}6_KkjR(kA0bx!i)}oBuk_w=h z0Z{)D5MI7l+C3*f8K^G(3sB7y5T3Gn&A!~kiUJ)5hKw6P0R=GbV2sL3%uNM~0WD>0 z1L2uooWBe5i%WoRZ Date: Tue, 4 Dec 2018 19:51:39 +0100 Subject: [PATCH 25/33] Fix cloning. --- .../shared/array-editor.component.html | 4 ++-- .../content/shared/array-editor.component.ts | 4 ++-- .../app/shared/state/contents.forms.ts | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Squidex/app/features/content/shared/array-editor.component.html b/src/Squidex/app/features/content/shared/array-editor.component.html index 61ccd1eda..035a0aaf2 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.html +++ b/src/Squidex/app/features/content/shared/array-editor.component.html @@ -11,12 +11,12 @@ [language]="language" [languages]="languages" (toggle)="hide($event)" - (cloning)="addItem(itemForm.value)" + (cloning)="addItem(itemForm)" (removing)="removeItem(i)">
- \ No newline at end of file diff --git a/src/Squidex/app/features/content/shared/array-editor.component.ts b/src/Squidex/app/features/content/shared/array-editor.component.ts index b4164bcde..cef18bf2a 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.ts +++ b/src/Squidex/app/features/content/shared/array-editor.component.ts @@ -6,7 +6,7 @@ */ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { AbstractControl, FormArray } from '@angular/forms'; +import { AbstractControl, FormArray, FormGroup } from '@angular/forms'; import { AppLanguageDto, @@ -47,7 +47,7 @@ export class ArrayEditorComponent { this.form.removeArrayItem(this.field, this.language, index); } - public addItem(value: {}) { + public addItem(value?: FormGroup) { this.form.insertArrayItem(this.field, this.language, value); } diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index cb8c61445..932a85fcc 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -374,24 +374,33 @@ export class EditContentForm extends Form { this.findArrayItemForm(field, language).removeAt(index); } - public insertArrayItem(field: RootFieldDto, language: AppLanguageDto, value?: {}) { + public insertArrayItem(field: RootFieldDto, language: AppLanguageDto, source?: FormGroup) { if (field.nested.length > 0) { const formControl = this.findArrayItemForm(field, language); - this.addArrayItem(field, language, formControl, value); + this.addArrayItem(field, language, formControl, source); } } - private addArrayItem(field: RootFieldDto, language: AppLanguageDto | null, partitionForm: FormArray, value?: {}) { + private addArrayItem(field: RootFieldDto, language: AppLanguageDto | null, partitionForm: FormArray, source?: FormGroup) { const itemForm = new FormGroup({}); let isOptional = field.isLocalizable && !!language && language.isOptional; for (let nested of field.nested) { const nestedValidators = FieldValidatorsFactory.createValidators(nested, isOptional); - const nestedDefault = value ? value[nested.name] : FieldDefaultValue.get(nested); - itemForm.setControl(nested.name, new FormControl(nestedDefault, nestedValidators)); + let value = FieldDefaultValue.get(nested); + + if (source) { + const sourceField = source.get(nested.name); + + if (sourceField) { + value = sourceField.value; + } + } + + itemForm.setControl(nested.name, new FormControl(value, nestedValidators)); } partitionForm.push(itemForm); From 3c9be8e4cec0695cbfbeb9aa0067cd4b77d902e1 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 5 Dec 2018 08:44:34 +0100 Subject: [PATCH 26/33] Just some refactoring. --- src/Squidex/Config/Domain/StoreServices.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index eb5c8065f..be1309092 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -65,8 +65,11 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); - services.AddSingletonAs() - .As(); + services.AddTransientAs() + .As(); + + services.AddTransientAs(c => new DeleteContentCollections(mongoContentDatabase)) + .As(); services.AddSingletonAs() .As(); @@ -74,12 +77,15 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); - services.AddSingletonAs() - .As>(); - services.AddSingletonAs() .As(); + services.AddSingletonAs() + .As(); + + services.AddSingletonAs() + .As>(); + services.AddSingletonAs() .As>() .As(); @@ -92,12 +98,6 @@ namespace Squidex.Config.Domain .As() .As>() .As(); - - services.AddTransientAs() - .As(); - - services.AddTransientAs(c => new DeleteContentCollections(mongoContentDatabase)) - .As(); } }); From f15fed3f56001cfa0c1b6ec260db58823bd14788 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 5 Dec 2018 14:58:32 +0100 Subject: [PATCH 27/33] Uniqueness validator. --- .../Schemas/Json/SchemaConverter.cs | 1 - .../Schemas/NumberFieldProperties.cs | 2 + .../Schemas/StringFieldProperties.cs | 2 + .../ValidateContent/ValidationContext.cs | 46 ++++++--- .../Validators/ReferencesValidator.cs | 15 ++- .../Validators/UniqueValidator.cs | 51 ++++++++++ .../ValidateContent/ValidatorsFactory.cs | 10 ++ .../Contents/MongoContentCollection.cs | 2 +- .../Contents/MongoContentDraftCollection.cs | 10 +- .../Contents/MongoContentEntity.cs | 2 +- .../Contents/MongoContentRepository.cs | 4 +- .../Contents/Visitors/AdaptionVisitor.cs | 50 ++++++++++ .../Contents/Visitors/FindExtensions.cs | 66 ++++++------- .../Contents/ContentGrain.cs | 13 ++- .../Contents/ContentOperationContext.cs | 13 ++- .../Repositories/IContentRepository.cs | 2 +- .../MongoDb/Queries/FilterBuilder.cs | 7 +- .../Models/Fields/NumberFieldPropertiesDto.cs | 5 + .../Models/Fields/StringFieldPropertiesDto.cs | 5 + .../types/number-validation.component.html | 11 +++ .../types/number-validation.component.ts | 16 +++- .../types/string-validation.component.html | 11 +++ .../types/string-validation.component.ts | 13 ++- .../app/shared/services/schemas.types.ts | 2 + .../ValidateContent/ArrayFieldTests.cs | 10 +- .../ValidateContent/AssetsFieldTests.cs | 12 +-- .../ValidateContent/BooleanFieldTests.cs | 4 +- .../ValidateContent/DateTimeFieldTests.cs | 10 +- .../ValidateContent/GeolocationFieldTests.cs | 8 +- .../ValidateContent/JsonFieldTests.cs | 2 +- .../ValidateContent/NumberFieldTests.cs | 22 ++++- .../ValidateContent/ReferencesFieldTests.cs | 26 +++--- .../ValidateContent/StringFieldTests.cs | 24 +++-- .../ValidateContent/TagsFieldTests.cs | 12 +-- .../ValidationTestExtensions.cs | 14 +-- .../Validators/UniqueValidatorTests.cs | 93 +++++++++++++++++++ 36 files changed, 462 insertions(+), 134 deletions(-) create mode 100644 src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValidator.cs create mode 100644 src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/AdaptionVisitor.cs create mode 100644 tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/UniqueValidatorTests.cs diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs index 3ca34038b..40623440c 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Json/SchemaConverter.cs @@ -7,7 +7,6 @@ using System; using Newtonsoft.Json; -using Squidex.Infrastructure; using Squidex.Infrastructure.Json; namespace Squidex.Domain.Apps.Core.Schemas.Json diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs index f4df67c4d..b97c73409 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs @@ -21,6 +21,8 @@ namespace Squidex.Domain.Apps.Core.Schemas public double? DefaultValue { get; set; } + public bool IsUnique { get; set; } + public bool InlineEditable { get; set; } public NumberFieldEditor Editor { get; set; } diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs index e5c6d3fd6..909e72b21 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs @@ -19,6 +19,8 @@ namespace Squidex.Domain.Apps.Core.Schemas public int? MaxLength { get; set; } + public bool IsUnique { get; set; } + public bool InlineEditable { get; set; } public string DefaultValue { get; set; } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidationContext.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidationContext.cs index 5db995c34..bc12a33dd 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidationContext.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidationContext.cs @@ -10,13 +10,20 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; using Squidex.Infrastructure; +using Squidex.Infrastructure.Queries; namespace Squidex.Domain.Apps.Core.ValidateContent { + public delegate Task> CheckContents(Guid schemaId, FilterNode filter); + + public delegate Task> CheckAssets(IEnumerable ids); + public sealed class ValidationContext { - private readonly Func, Guid, Task>> checkContent; - private readonly Func, Task>> checkAsset; + private readonly Guid contentId; + private readonly Guid schemaId; + private readonly CheckContents checkContent; + private readonly CheckAssets checkAsset; private readonly ImmutableQueue propertyPath; public ImmutableQueue Path @@ -24,18 +31,32 @@ namespace Squidex.Domain.Apps.Core.ValidateContent get { return propertyPath; } } + public Guid ContentId + { + get { return contentId; } + } + + public Guid SchemaId + { + get { return schemaId; } + } + public bool IsOptional { get; } public ValidationContext( - Func, Guid, Task>> checkContent, - Func, Task>> checkAsset) - : this(checkContent, checkAsset, ImmutableQueue.Empty, false) + Guid contentId, + Guid schemaId, + CheckContents checkContent, + CheckAssets checkAsset) + : this(contentId, schemaId, checkContent, checkAsset, ImmutableQueue.Empty, false) { } private ValidationContext( - Func, Guid, Task>> checkContent, - Func, Task>> checkAsset, + Guid contentId, + Guid schemaId, + CheckContents checkContent, + CheckAssets checkAsset, ImmutableQueue propertyPath, bool isOptional) { @@ -46,23 +67,26 @@ namespace Squidex.Domain.Apps.Core.ValidateContent this.checkContent = checkContent; this.checkAsset = checkAsset; + this.contentId = contentId; + + this.schemaId = schemaId; IsOptional = isOptional; } public ValidationContext Optional(bool isOptional) { - return isOptional == IsOptional ? this : new ValidationContext(checkContent, checkAsset, propertyPath, isOptional); + return isOptional == IsOptional ? this : new ValidationContext(contentId, schemaId, checkContent, checkAsset, propertyPath, isOptional); } public ValidationContext Nested(string property) { - return new ValidationContext(checkContent, checkAsset, propertyPath.Enqueue(property), IsOptional); + return new ValidationContext(contentId, schemaId, checkContent, checkAsset, propertyPath.Enqueue(property), IsOptional); } - public Task> GetInvalidContentIdsAsync(IEnumerable contentIds, Guid schemaId) + public Task> GetContentIdsAsync(Guid schemaId, FilterNode filter) { - return checkContent(contentIds, schemaId); + return checkContent(schemaId, filter); } public Task> GetAssetInfosAsync(IEnumerable assetId) diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs index 9fd97bc02..fa388d365 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs @@ -7,12 +7,16 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using Squidex.Infrastructure.Queries; namespace Squidex.Domain.Apps.Core.ValidateContent.Validators { public sealed class ReferencesValidator : IValidator { + private static readonly IReadOnlyList Path = new List { "Id" }; + private readonly Guid schemaId; public ReferencesValidator(Guid schemaId) @@ -24,11 +28,16 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators { if (value is ICollection contentIds) { - var invalidIds = await context.GetInvalidContentIdsAsync(contentIds, schemaId); + var filter = new FilterComparison(Path, FilterOperator.In, new FilterValue(contentIds.ToList())); + + var foundIds = await context.GetContentIdsAsync(schemaId, filter); - foreach (var invalidId in invalidIds) + foreach (var id in contentIds) { - addError(context.Path, $"Contains invalid reference '{invalidId}'."); + if (!foundIds.Contains(id)) + { + addError(context.Path, $"Contains invalid reference '{id}'."); + } } } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValidator.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValidator.cs new file mode 100644 index 000000000..3c2b8f14a --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/UniqueValidator.cs @@ -0,0 +1,51 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Squidex.Infrastructure.Queries; + +namespace Squidex.Domain.Apps.Core.ValidateContent.Validators +{ + public sealed class UniqueValidator : IValidator + { + public async Task ValidateAsync(object value, ValidationContext context, AddError addError) + { + var count = context.Path.Count(); + + if (value != null && (count == 0 || (count == 2 && context.Path.Last() == InvariantPartitioning.Instance.Master.Key))) + { + FilterNode filter = null; + + if (value is string s) + { + filter = new FilterComparison(Path(context), FilterOperator.Equals, new FilterValue(s)); + } + else if (value is double d) + { + filter = new FilterComparison(Path(context), FilterOperator.Equals, new FilterValue(d)); + } + + if (filter != null) + { + var found = await context.GetContentIdsAsync(context.SchemaId, filter); + + if (found.Any(x => x != context.ContentId)) + { + addError(context.Path, "Another content with the same value exists."); + } + } + } + } + + private static List Path(ValidationContext context) + { + return Enumerable.Repeat("Data", 1).Union(context.Path).ToList(); + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs index fc104e7e5..21037210f 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidatorsFactory.cs @@ -111,6 +111,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { yield return new AllowedValuesValidator(field.Properties.AllowedValues); } + + if (field.Properties.IsUnique) + { + yield return new UniqueValidator(); + } } public IEnumerable Visit(IField field) @@ -147,6 +152,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent { yield return new AllowedValuesValidator(field.Properties.AllowedValues); } + + if (field.Properties.IsUnique) + { + yield return new UniqueValidator(); + } } public IEnumerable Visit(IField field) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs index c9eec5756..3a5365ccf 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs @@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { query = query.AdjustToModel(schema.SchemaDef, useDraft); - var filter = FindExtensions.BuildQuery(query, schema.Id, status); + var filter = query.ToFilter(schema.Id, status); var contentCount = Collection.Find(filter).CountDocumentsAsync(); var contentItems = diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs index 2c80690f7..12feef7f8 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentDraftCollection.cs @@ -16,9 +16,11 @@ using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.State; +using Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; using Squidex.Infrastructure.MongoDb; +using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.States; @@ -52,13 +54,15 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents await base.SetupCollectionAsync(collection, ct); } - public async Task> QueryNotFoundAsync(Guid appId, Guid schemaId, IList ids) + public async Task> QueryIdsAsync(Guid appId, ISchemaEntity schema, FilterNode filterNode) { + var filter = filterNode.AdjustToModel(schema.SchemaDef, true).ToFilter(schema.Id); + var contentEntities = - await Collection.Find(x => x.IndexedSchemaId == schemaId && ids.Contains(x.Id) && x.IsDeleted != true).Only(x => x.Id) + await Collection.Find(filter).Only(x => x.Id) .ToListAsync(); - return ids.Except(contentEntities.Select(x => Guid.Parse(x["_id"].AsString))).ToList(); + return contentEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); } public async Task> QueryIdsAsync(Guid appId) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs index b758c7919..f07adc44e 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs @@ -24,7 +24,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents private NamedContentData dataDraft; [BsonId] - [BsonElement] + [BsonElement("_id")] [BsonRepresentation(BsonType.String)] public Guid Id { get; set; } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs index 71c81e3aa..f1218532c 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs @@ -91,11 +91,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents } } - public async Task> QueryNotFoundAsync(Guid appId, Guid schemaId, IList ids) + public async Task> QueryIdsAsync(Guid appId, Guid schemaId, FilterNode filterNode) { using (Profiler.TraceMethod()) { - return await contentsDraft.QueryNotFoundAsync(appId, schemaId, ids); + return await contentsDraft.QueryIdsAsync(appId, await appProvider.GetSchemaAsync(appId, schemaId), filterNode); } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/AdaptionVisitor.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/AdaptionVisitor.cs new file mode 100644 index 000000000..396971e84 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/AdaptionVisitor.cs @@ -0,0 +1,50 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using NodaTime; +using Squidex.Infrastructure.Queries; + +namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors +{ + internal sealed class AdaptionVisitor : TransformVisitor + { + private readonly Func, IReadOnlyList> pathConverter; + + public AdaptionVisitor(Func, IReadOnlyList> pathConverter) + { + this.pathConverter = pathConverter; + } + + public override FilterNode Visit(FilterComparison nodeIn) + { + FilterComparison result; + + var value = nodeIn.Rhs.Value; + + if (value is Instant && + !string.Equals(nodeIn.Lhs[0], "mt", StringComparison.OrdinalIgnoreCase) && + !string.Equals(nodeIn.Lhs[0], "ct", StringComparison.OrdinalIgnoreCase)) + { + result = new FilterComparison(pathConverter(nodeIn.Lhs), nodeIn.Operator, new FilterValue(value.ToString())); + } + else + { + result = new FilterComparison(pathConverter(nodeIn.Lhs), nodeIn.Operator, nodeIn.Rhs); + } + + if (result.Lhs.Count == 1 && result.Lhs[0] == "_id" && result.Rhs.Value is List guidList) + { + result = new FilterComparison(nodeIn.Lhs, nodeIn.Operator, new FilterValue(guidList.Select(x => x.ToString()).ToList())); + } + + return result; + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/FindExtensions.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/FindExtensions.cs index 8fe06f208..0f57dacfa 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/FindExtensions.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Visitors/FindExtensions.cs @@ -11,7 +11,6 @@ using System.Linq; using System.Reflection; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; -using NodaTime; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.GenerateEdmSchema; using Squidex.Domain.Apps.Core.Schemas; @@ -28,33 +27,30 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors typeof(MongoContentEntity).GetProperties() .ToDictionary(x => x.Name, x => x.GetCustomAttribute()?.ElementName ?? x.Name, StringComparer.OrdinalIgnoreCase); - private sealed class AdaptionVisitor : TransformVisitor + public static Query AdjustToModel(this Query query, Schema schema, bool useDraft) { - private readonly Func, IReadOnlyList> pathConverter; + var pathConverter = PathConverter(schema, useDraft); - public AdaptionVisitor(Func, IReadOnlyList> pathConverter) + if (query.Filter != null) { - this.pathConverter = pathConverter; + query.Filter = query.Filter.Accept(new AdaptionVisitor(pathConverter)); } - public override FilterNode Visit(FilterComparison nodeIn) - { - var value = nodeIn.Rhs.Value; + query.Sort = query.Sort.Select(x => new SortNode(pathConverter(x.Path), x.SortOrder)).ToList(); - if (value is Instant && - !string.Equals(nodeIn.Lhs[0], "mt", StringComparison.OrdinalIgnoreCase) && - !string.Equals(nodeIn.Lhs[0], "ct", StringComparison.OrdinalIgnoreCase)) - { - return new FilterComparison(pathConverter(nodeIn.Lhs), nodeIn.Operator, new FilterValue(value.ToString())); - } + return query; + } - return new FilterComparison(pathConverter(nodeIn.Lhs), nodeIn.Operator, nodeIn.Rhs); - } + public static FilterNode AdjustToModel(this FilterNode filterNode, Schema schema, bool useDraft) + { + var pathConverter = PathConverter(schema, useDraft); + + return filterNode.Accept(new AdaptionVisitor(pathConverter)); } - public static Query AdjustToModel(this Query query, Schema schema, bool useDraft) + private static Func, IReadOnlyList> PathConverter(Schema schema, bool useDraft) { - var pathConverter = new Func, IReadOnlyList>(propertyNames => + return new Func, IReadOnlyList>(propertyNames => { var result = new List(propertyNames); @@ -96,15 +92,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors return result; }); - - if (query.Filter != null) - { - query.Filter = query.Filter.Accept(new AdaptionVisitor(pathConverter)); - } - - query.Sort = query.Sort.Select(x => new SortNode(pathConverter(x.Path), x.SortOrder)).ToList(); - - return query; } public static IFindFluent ContentSort(this IFindFluent cursor, Query query) @@ -122,16 +109,16 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors return cursor.Skip(query); } - public static FilterDefinition BuildQuery(Query query, Guid schemaId, Status[] status) + public static FilterDefinition ToFilter(this Query query, Guid schemaId, Status[] status) { var filters = new List> { - Filter.Eq(x => x.IndexedSchemaId, schemaId) + Filter.Eq(x => x.IndexedSchemaId, schemaId), + Filter.Ne(x => x.IsDeleted, true) }; if (status != null) { - filters.Add(Filter.Ne(x => x.IsDeleted, true)); filters.Add(Filter.In(x => x.Status, status)); } @@ -149,14 +136,19 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors } } - if (filters.Count == 1) - { - return filters[0]; - } - else + return Filter.And(filters); + } + + public static FilterDefinition ToFilter(this FilterNode filterNode, Guid schemaId) + { + var filters = new List> { - return Filter.And(filters); - } + Filter.Eq(x => x.IndexedSchemaId, schemaId), + Filter.Ne(x => x.IsDeleted, true), + filterNode.BuildFilter() + }; + + return Filter.And(filters); } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs index 85d847e62..06cb8efb6 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs @@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Entities.Contents case CreateContent createContent: return CreateReturnAsync(createContent, async c => { - var ctx = await CreateContext(c.AppId.Id, c.SchemaId.Id, () => "Failed to create content."); + var ctx = await CreateContext(c.AppId.Id, c.SchemaId.Id, Guid.Empty, () => "Failed to create content."); GuardContent.CanCreate(ctx.Schema, c); @@ -105,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Contents { try { - var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, () => "Failed to change content."); + var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to change content."); GuardContent.CanChangeContentStatus(ctx.Schema, Snapshot.IsPending, Snapshot.Status, c); @@ -162,7 +162,7 @@ namespace Squidex.Domain.Apps.Entities.Contents case DeleteContent deleteContent: return UpdateAsync(deleteContent, async c => { - var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, () => "Failed to delete content."); + var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to delete content."); GuardContent.CanDelete(ctx.Schema, c); @@ -197,7 +197,7 @@ namespace Squidex.Domain.Apps.Entities.Contents if (!currentData.Equals(newData)) { - var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, () => "Failed to update content."); + var ctx = await CreateContext(Snapshot.AppId.Id, Snapshot.SchemaId.Id, Snapshot.Id, () => "Failed to update content."); if (partial) { @@ -301,11 +301,10 @@ namespace Squidex.Domain.Apps.Entities.Contents return Snapshot.Apply(@event); } - private async Task CreateContext(Guid appId, Guid schemaId, Func message) + private async Task CreateContext(Guid appId, Guid schemaId, Guid contentId, Func message) { var operationContext = - await ContentOperationContext.CreateAsync( - appId, schemaId, + await ContentOperationContext.CreateAsync(appId, schemaId, contentId, appProvider, assetRepository, contentRepository, scriptEngine, message); return operationContext; diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs index 5ca66b9ef..6613a5276 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.EnrichContent; @@ -18,6 +17,7 @@ using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.Repositories; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Tasks; namespace Squidex.Domain.Apps.Entities.Contents @@ -29,6 +29,8 @@ namespace Squidex.Domain.Apps.Entities.Contents private IScriptEngine scriptEngine; private ISchemaEntity schemaEntity; private IAppEntity appEntity; + private Guid contentId; + private Guid schemaId; private Func message; public ISchemaEntity Schema @@ -39,6 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Contents public static async Task CreateAsync( Guid appId, Guid schemaId, + Guid contentId, IAppProvider appProvider, IAssetRepository assetRepository, IContentRepository contentRepository, @@ -51,8 +54,10 @@ namespace Squidex.Domain.Apps.Entities.Contents { appEntity = appEntity, assetRepository = assetRepository, + contentId = contentId, contentRepository = contentRepository, message = message, + schemaId = schemaId, schemaEntity = schemaEntity, scriptEngine = scriptEngine }; @@ -106,7 +111,7 @@ namespace Squidex.Domain.Apps.Entities.Contents private ValidationContext CreateValidationContext() { - return new ValidationContext((contentIds, schemaId) => QueryContentsAsync(schemaId, contentIds), QueryAssetsAsync); + return new ValidationContext(contentId, schemaId, (sid, filterNode) => QueryContentsAsync(sid, filterNode), QueryAssetsAsync); } private async Task> QueryAssetsAsync(IEnumerable assetIds) @@ -114,9 +119,9 @@ namespace Squidex.Domain.Apps.Entities.Contents return await assetRepository.QueryAsync(appEntity.Id, new HashSet(assetIds)); } - private async Task> QueryContentsAsync(Guid schemaId, IEnumerable contentIds) + private async Task> QueryContentsAsync(Guid filterSchemaId, FilterNode filterNode) { - return await contentRepository.QueryNotFoundAsync(appEntity.Id, schemaId, contentIds.ToList()); + return await contentRepository.QueryIdsAsync(appEntity.Id, filterSchemaId, filterNode); } } } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs b/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs index 9f65e239b..e82d39932 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs @@ -23,7 +23,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Repositories Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, Query query); - Task> QueryNotFoundAsync(Guid appId, Guid schemaId, IList ids); + Task> QueryIdsAsync(Guid appId, Guid schemaId, FilterNode filterNode); Task FindContentAsync(IAppEntity app, ISchemaEntity schema, Status[] status, Guid id); diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterBuilder.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterBuilder.cs index aaa0e7c55..3b76605e0 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterBuilder.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/Queries/FilterBuilder.cs @@ -26,10 +26,15 @@ namespace Squidex.Infrastructure.MongoDb.Queries if (query.Filter != null) { - return (FilterVisitor.Visit(query.Filter), true); + return (query.Filter.BuildFilter(), true); } return (null, false); } + + public static FilterDefinition BuildFilter(this FilterNode filterNode) + { + return FilterVisitor.Visit(filterNode); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs index 4a7861b04..01fe437a6 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs @@ -37,6 +37,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// public double[] AllowedValues { get; set; } + /// + /// Indicates if the field value must be unique. Ignored for nested fields and localized fields. + /// + public bool IsUnique { get; set; } + /// /// Indicates that the inline editor is enabled for this field. /// diff --git a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs index 0722fec99..e5f3c72f5 100644 --- a/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs @@ -47,6 +47,11 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields /// public string[] AllowedValues { get; set; } + /// + /// Indicates if the field value must be unique. Ignored for nested fields and localized fields. + /// + public bool IsUnique { get; set; } + /// /// Indicates that the inline editor is enabled for this field. /// diff --git a/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.html b/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.html index 699d5654c..c2a03efb7 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.html @@ -1,4 +1,15 @@
+
+
+
+ + +
+
+
+
diff --git a/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts index 18cd9e1bf..489010653 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/number-validation.component.ts @@ -10,7 +10,12 @@ import { FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; -import { FieldDto, NumberFieldPropertiesDto } from '@app/shared'; +import { + FieldDto, + NumberFieldPropertiesDto, + RootFieldDto, + Types +} from '@app/shared'; @Component({ selector: 'sqx-number-validation', @@ -27,9 +32,18 @@ export class NumberValidationComponent implements OnInit { @Input() public properties: NumberFieldPropertiesDto; + public showUnique: boolean; + public showDefaultValue: Observable; public ngOnInit() { + this.showUnique = Types.is(this.field, RootFieldDto) && !this.field.isLocalizable; + + if (this.showUnique) { + this.editForm.setControl('isUnique', + new FormControl(this.properties.isUnique)); + } + this.editForm.setControl('maxValue', new FormControl(this.properties.maxValue)); diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html index bf6e7b214..b81865ed6 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html @@ -1,4 +1,15 @@
+
+
+
+ + +
+
+
+
diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts index 22f64ffaa..3f1c137a0 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts @@ -15,7 +15,9 @@ import { FieldDto, ImmutableArray, ModalModel, - StringFieldPropertiesDto + RootFieldDto, + StringFieldPropertiesDto, + Types } from '@app/shared'; @Component({ @@ -45,11 +47,20 @@ export class StringValidationComponent implements OnDestroy, OnInit { public patternName: string; public patternsModal = new ModalModel(); + public showUnique: boolean; + public ngOnDestroy() { this.patternSubscription.unsubscribe(); } public ngOnInit() { + this.showUnique = Types.is(this.field, RootFieldDto) && !this.field.isLocalizable; + + if (this.showUnique) { + this.editForm.setControl('isUnique', + new FormControl(this.properties.isUnique)); + } + this.editForm.setControl('maxLength', new FormControl(this.properties.maxLength)); diff --git a/src/Squidex/app/shared/services/schemas.types.ts b/src/Squidex/app/shared/services/schemas.types.ts index 8ec7a5a6a..5e47756ba 100644 --- a/src/Squidex/app/shared/services/schemas.types.ts +++ b/src/Squidex/app/shared/services/schemas.types.ts @@ -241,6 +241,7 @@ export class NumberFieldPropertiesDto extends FieldPropertiesDto { public readonly fieldType = 'Number'; public readonly inlineEditable: boolean = false; + public readonly isUnique: boolean = false; public readonly defaultValue?: number; public readonly maxValue?: number; public readonly minValue?: number; @@ -279,6 +280,7 @@ export class StringFieldPropertiesDto extends FieldPropertiesDto { public readonly fieldType = 'String'; public readonly inlineEditable = false; + public readonly isUnique: boolean = false; public readonly defaultValue?: string; public readonly pattern?: string; public readonly patternMessage?: string; diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs index 44ee87e03..2a29a9496 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ArrayFieldTests.cs @@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_tags_are_required_and_null() + public async Task Should_add_error_if_tags_are_required_and_null() { var sut = Field(new ArrayFieldProperties { IsRequired = true }); @@ -59,7 +59,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_tags_are_required_and_empty() + public async Task Should_add_error_if_tags_are_required_and_empty() { var sut = Field(new ArrayFieldProperties { IsRequired = true }); @@ -70,7 +70,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new ArrayFieldProperties()); @@ -81,7 +81,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_not_enough_items() + public async Task Should_add_error_if_value_has_not_enough_items() { var sut = Field(new ArrayFieldProperties { MinItems = 3 }); @@ -92,7 +92,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_too_much_items() + public async Task Should_add_error_if_value_has_too_much_items() { var sut = Field(new ArrayFieldProperties { MaxItems = 1 }); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs index 36aa3c0e0..50a46549d 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs @@ -93,7 +93,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_assets_are_required_and_null() + public async Task Should_add_error_if_assets_are_required_and_null() { var sut = Field(new AssetsFieldProperties { IsRequired = true }); @@ -104,7 +104,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_assets_are_required_and_empty() + public async Task Should_add_error_if_assets_are_required_and_empty() { var sut = Field(new AssetsFieldProperties { IsRequired = true }); @@ -115,7 +115,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new AssetsFieldProperties()); @@ -126,7 +126,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_not_enough_items() + public async Task Should_add_error_if_value_has_not_enough_items() { var sut = Field(new AssetsFieldProperties { MinItems = 3 }); @@ -137,7 +137,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_too_much_items() + public async Task Should_add_error_if_value_has_too_much_items() { var sut = Field(new AssetsFieldProperties { MaxItems = 1 }); @@ -148,7 +148,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_asset_are_not_valid() + public async Task Should_add_error_if_asset_are_not_valid() { var assetId = Guid.NewGuid(); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs index 537f8d9a7..76ff5ee9b 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/BooleanFieldTests.cs @@ -47,7 +47,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_boolean_is_required() + public async Task Should_add_error_if_boolean_is_required() { var sut = Field(new BooleanFieldProperties { IsRequired = true }); @@ -58,7 +58,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new BooleanFieldProperties()); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs index ac74d57ad..5cc7df545 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/DateTimeFieldTests.cs @@ -39,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_datetime_is_required() + public async Task Should_add_error_if_datetime_is_required() { var sut = Field(new DateTimeFieldProperties { IsRequired = true }); @@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_datetime_is_less_than_min() + public async Task Should_add_error_if_datetime_is_less_than_min() { var sut = Field(new DateTimeFieldProperties { MinValue = FutureDays(10) }); @@ -61,7 +61,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_datetime_is_greater_than_max() + public async Task Should_add_error_if_datetime_is_greater_than_max() { var sut = Field(new DateTimeFieldProperties { MaxValue = FutureDays(10) }); @@ -72,7 +72,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new DateTimeFieldProperties()); @@ -83,7 +83,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_another_type() + public async Task Should_add_error_if_value_is_another_type() { var sut = Field(new DateTimeFieldProperties()); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs index c19149e6b..570631fdf 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/GeolocationFieldTests.cs @@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_geolocation_has_invalid_latitude() + public async Task Should_add_error_if_geolocation_has_invalid_latitude() { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); @@ -66,7 +66,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_geolocation_has_invalid_longitude() + public async Task Should_add_error_if_geolocation_has_invalid_longitude() { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); @@ -81,7 +81,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_geolocation_has_too_many_properties() + public async Task Should_add_error_if_geolocation_has_too_many_properties() { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); @@ -97,7 +97,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_geolocation_is_required() + public async Task Should_add_error_if_geolocation_is_required() { var sut = Field(new GeolocationFieldProperties { IsRequired = true }); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs index b6cb06f80..36509dc83 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/JsonFieldTests.cs @@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_json_is_required() + public async Task Should_add_error_if_json_is_required() { var sut = Field(new JsonFieldProperties { IsRequired = true }); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs index d236198f9..a4d5ea592 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; @@ -38,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_number_is_required() + public async Task Should_add_error_if_number_is_required() { var sut = Field(new NumberFieldProperties { IsRequired = true }); @@ -49,7 +50,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_number_is_less_than_min() + public async Task Should_add_error_if_number_is_less_than_min() { var sut = Field(new NumberFieldProperties { MinValue = 10 }); @@ -60,7 +61,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_number_is_greater_than_max() + public async Task Should_add_error_if_number_is_greater_than_max() { var sut = Field(new NumberFieldProperties { MaxValue = 10 }); @@ -71,7 +72,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_number_is_not_allowed() + public async Task Should_add_error_if_number_is_not_allowed() { var sut = Field(new NumberFieldProperties { AllowedValues = ReadOnlyCollection.Create(10d) }); @@ -82,7 +83,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new NumberFieldProperties()); @@ -92,6 +93,17 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new[] { "Not a valid value." }); } + [Fact] + public async Task Should_add_error_if_unique_constraint_failed() + { + var sut = Field(new NumberFieldProperties { IsUnique = true }); + + await sut.ValidateAsync(CreateValue(12.5), errors, ValidationTestExtensions.References(Guid.NewGuid())); + + errors.Should().BeEquivalentTo( + new[] { "Another content with the same value exists." }); + } + private static JValue CreateValue(object v) { return new JValue(v); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs index 768b781bc..559eec27a 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ReferencesFieldTests.cs @@ -20,6 +20,8 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { private readonly List errors = new List(); private readonly Guid schemaId = Guid.NewGuid(); + private readonly Guid ref1 = Guid.NewGuid(); + private readonly Guid ref2 = Guid.NewGuid(); [Fact] public void Should_instantiate_field() @@ -34,7 +36,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var sut = Field(new ReferencesFieldProperties()); - await sut.ValidateAsync(CreateValue(Guid.NewGuid()), errors, ValidationTestExtensions.ValidContext); + await sut.ValidateAsync(CreateValue(ref1), errors, ValidationTestExtensions.References(ref1)); Assert.Empty(errors); } @@ -50,7 +52,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_references_are_required_and_null() + public async Task Should_add_error_if_references_are_required_and_null() { var sut = Field(new ReferencesFieldProperties { SchemaId = schemaId, IsRequired = true }); @@ -61,7 +63,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_references_are_required_and_empty() + public async Task Should_add_error_if_references_are_required_and_empty() { var sut = Field(new ReferencesFieldProperties { SchemaId = schemaId, IsRequired = true }); @@ -72,7 +74,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new ReferencesFieldProperties()); @@ -83,38 +85,36 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_not_enough_items() + public async Task Should_add_error_if_value_has_not_enough_items() { var sut = Field(new ReferencesFieldProperties { SchemaId = schemaId, MinItems = 3 }); - await sut.ValidateAsync(CreateValue(Guid.NewGuid(), Guid.NewGuid()), errors); + await sut.ValidateAsync(CreateValue(ref1, ref2), errors, ValidationTestExtensions.References(ref1, ref2)); errors.Should().BeEquivalentTo( new[] { "Must have at least 3 item(s)." }); } [Fact] - public async Task Should_add_errors_if_value_has_too_much_items() + public async Task Should_add_error_if_value_has_too_much_items() { var sut = Field(new ReferencesFieldProperties { SchemaId = schemaId, MaxItems = 1 }); - await sut.ValidateAsync(CreateValue(Guid.NewGuid(), Guid.NewGuid()), errors); + await sut.ValidateAsync(CreateValue(ref1, ref2), errors, ValidationTestExtensions.References(ref1, ref2)); errors.Should().BeEquivalentTo( new[] { "Must have not more than 1 item(s)." }); } [Fact] - public async Task Should_add_errors_if_reference_are_not_valid() + public async Task Should_add_error_if_reference_are_not_valid() { - var referenceId = Guid.NewGuid(); - var sut = Field(new ReferencesFieldProperties { SchemaId = schemaId }); - await sut.ValidateAsync(CreateValue(referenceId), errors, ValidationTestExtensions.InvalidReferences(referenceId)); + await sut.ValidateAsync(CreateValue(ref1), errors, ValidationTestExtensions.References()); errors.Should().BeEquivalentTo( - new[] { $"Contains invalid reference '{referenceId}'." }); + new[] { $"Contains invalid reference '{ref1}'." }); } private static JToken CreateValue(params Guid[] ids) diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs index 46f9a17de..fcad0819c 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; @@ -38,7 +39,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_string_is_required() + public async Task Should_add_error_if_string_is_required() { var sut = Field(new StringFieldProperties { IsRequired = true }); @@ -49,7 +50,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_string_is_shorter_than_min_length() + public async Task Should_add_error_if_string_is_shorter_than_min_length() { var sut = Field(new StringFieldProperties { MinLength = 10 }); @@ -60,7 +61,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_string_is_longer_than_max_length() + public async Task Should_add_error_if_string_is_longer_than_max_length() { var sut = Field(new StringFieldProperties { MaxLength = 5 }); @@ -71,7 +72,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_string_not_allowed() + public async Task Should_add_error_if_string_not_allowed() { var sut = Field(new StringFieldProperties { AllowedValues = ReadOnlyCollection.Create("Foo") }); @@ -82,7 +83,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_number_is_not_valid_pattern() + public async Task Should_add_error_if_number_is_not_valid_pattern() { var sut = Field(new StringFieldProperties { Pattern = "[0-9]{3}" }); @@ -93,7 +94,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_number_is_not_valid_pattern_with_message() + public async Task Should_add_error_if_number_is_not_valid_pattern_with_message() { var sut = Field(new StringFieldProperties { Pattern = "[0-9]{3}", PatternMessage = "Custom Error Message." }); @@ -103,6 +104,17 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent new[] { "Custom Error Message." }); } + [Fact] + public async Task Should_add_error_if_unique_constraint_failed() + { + var sut = Field(new StringFieldProperties { IsUnique = true }); + + await sut.ValidateAsync(CreateValue("abc"), errors, ValidationTestExtensions.References(Guid.NewGuid())); + + errors.Should().BeEquivalentTo( + new[] { "Another content with the same value exists." }); + } + private static JValue CreateValue(object v) { return new JValue(v); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs index 3b2a4d3c2..832f2ebe9 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/TagsFieldTests.cs @@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_tags_are_required_and_null() + public async Task Should_add_error_if_tags_are_required_and_null() { var sut = Field(new TagsFieldProperties { IsRequired = true }); @@ -60,7 +60,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_tags_are_required_and_empty() + public async Task Should_add_error_if_tags_are_required_and_empty() { var sut = Field(new TagsFieldProperties { IsRequired = true }); @@ -71,7 +71,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_is_not_valid() + public async Task Should_add_error_if_value_is_not_valid() { var sut = Field(new TagsFieldProperties()); @@ -82,7 +82,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_not_enough_items() + public async Task Should_add_error_if_value_has_not_enough_items() { var sut = Field(new TagsFieldProperties { MinItems = 3 }); @@ -93,7 +93,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_has_too_much_items() + public async Task Should_add_error_if_value_has_too_much_items() { var sut = Field(new TagsFieldProperties { MaxItems = 1 }); @@ -104,7 +104,7 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent } [Fact] - public async Task Should_add_errors_if_value_contains_an_not_allowed_values() + public async Task Should_add_error_if_value_contains_an_not_allowed_values() { var sut = Field(new TagsFieldProperties { AllowedValues = ReadOnlyCollection.Create("tag-2", "tag-3") }); diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs index 3b1e1c454..482d288d5 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ValidationTestExtensions.cs @@ -18,10 +18,10 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { public static class ValidationTestExtensions { - private static readonly Task> ValidReferences = Task.FromResult>(new List()); - private static readonly Task> ValidAssets = Task.FromResult>(new List()); + private static readonly Task> EmptyReferences = Task.FromResult>(new List()); + private static readonly Task> EmptyAssets = Task.FromResult>(new List()); - public static readonly ValidationContext ValidContext = new ValidationContext((x, y) => ValidReferences, x => ValidAssets); + public static readonly ValidationContext ValidContext = new ValidationContext(Guid.NewGuid(), Guid.NewGuid(), (x, y) => EmptyReferences, x => EmptyAssets); public static Task ValidateAsync(this IValidator validator, object value, IList errors, ValidationContext context = null) { @@ -75,14 +75,14 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent { var actual = Task.FromResult>(assets.ToList()); - return new ValidationContext((x, y) => ValidReferences, x => actual); + return new ValidationContext(Guid.NewGuid(), Guid.NewGuid(), (x, y) => EmptyReferences, x => actual); } - public static ValidationContext InvalidReferences(Guid referencesIds) + public static ValidationContext References(params Guid[] referencesIds) { - var actual = Task.FromResult>(new List { referencesIds }); + var actual = Task.FromResult>(referencesIds.ToList()); - return new ValidationContext((x, y) => actual, x => ValidAssets); + return new ValidationContext(Guid.NewGuid(), Guid.NewGuid(), (x, y) => actual, x => EmptyAssets); } } } diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/UniqueValidatorTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/UniqueValidatorTests.cs new file mode 100644 index 000000000..3c8e72881 --- /dev/null +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/Validators/UniqueValidatorTests.cs @@ -0,0 +1,93 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; +using Squidex.Domain.Apps.Core.ValidateContent; +using Squidex.Domain.Apps.Core.ValidateContent.Validators; +using Xunit; + +namespace Squidex.Domain.Apps.Core.Operations.ValidateContent.Validators +{ + public class UniqueValidatorTests + { + private readonly List errors = new List(); + private readonly Guid contentId = Guid.NewGuid(); + private readonly Guid schemaId = Guid.NewGuid(); + + [Fact] + public async Task Should_add_error_if_string_value_not_found() + { + var sut = new UniqueValidator(); + + var filter = string.Empty; + + await sut.ValidateAsync("hi", errors, Context(Guid.NewGuid(), f => filter = f)); + + errors.Should().BeEquivalentTo( + new[] { "property: Another content with the same value exists." }); + + Assert.Equal("Data.property.iv == 'hi'", filter); + } + + [Fact] + public async Task Should_add_error_if_double_value_not_found() + { + var sut = new UniqueValidator(); + + var filter = string.Empty; + + await sut.ValidateAsync(12.5, errors, Context(Guid.NewGuid(), f => filter = f)); + + errors.Should().BeEquivalentTo( + new[] { "property: Another content with the same value exists." }); + + Assert.Equal("Data.property.iv == 12.5", filter); + } + + [Fact] + public async Task Should_not_add_error_if_string_value_found() + { + var sut = new UniqueValidator(); + + var filter = string.Empty; + + await sut.ValidateAsync("hi", errors, Context(contentId, f => filter = f)); + + Assert.Empty(errors); + } + + [Fact] + public async Task Should_not_add_error_if_double_value_found() + { + var sut = new UniqueValidator(); + + var filter = string.Empty; + + await sut.ValidateAsync(12.5, errors, Context(contentId, f => filter = f)); + + Assert.Empty(errors); + } + + private ValidationContext Context(Guid id, Action filter) + { + return new ValidationContext(contentId, schemaId, + (schema, filterNode) => + { + filter(filterNode.ToString()); + + return Task.FromResult>(new List { id }); + }, + ids => + { + return Task.FromResult>(new List()); + }).Nested("property").Nested("iv"); + } + } +} From 9f933b1cb3f1cabc05c9aa85b9d641513430c21b Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 5 Dec 2018 17:46:18 +0100 Subject: [PATCH 28/33] Sort buttons. --- .../shared/array-editor.component.html | 3 + .../content/shared/array-editor.component.ts | 9 + .../content/shared/array-item.component.html | 12 + .../content/shared/array-item.component.scss | 9 +- .../content/shared/array-item.component.ts | 25 ++ src/Squidex/app/theme/icomoon/demo.html | 252 +----------------- .../app/theme/icomoon/fonts/icomoon.eot | Bin 27568 -> 27868 bytes .../app/theme/icomoon/fonts/icomoon.svg | 2 + .../app/theme/icomoon/fonts/icomoon.ttf | Bin 27404 -> 27704 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 27480 -> 27780 bytes .../app/theme/icomoon/icons/caret-bottom.svg | 66 +++++ .../app/theme/icomoon/icons/caret-top.svg | 66 +++++ src/Squidex/app/theme/icomoon/selection.json | 2 +- src/Squidex/app/theme/icomoon/style.css | 60 +---- 14 files changed, 215 insertions(+), 291 deletions(-) create mode 100644 src/Squidex/app/theme/icomoon/icons/caret-bottom.svg create mode 100644 src/Squidex/app/theme/icomoon/icons/caret-top.svg diff --git a/src/Squidex/app/features/content/shared/array-editor.component.html b/src/Squidex/app/features/content/shared/array-editor.component.html index 035a0aaf2..5d898d963 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.html +++ b/src/Squidex/app/features/content/shared/array-editor.component.html @@ -6,11 +6,14 @@ [form]="form" [field]="field" [isHidden]="isHidden" + [isFirst]="i === 0" + [isLast]="i === arrayControl.controls.length - 1" [index]="i" [itemForm]="itemForm" [language]="language" [languages]="languages" (toggle)="hide($event)" + (moving)="move(itemForm, $event)" (cloning)="addItem(itemForm)" (removing)="removeItem(i)"> diff --git a/src/Squidex/app/features/content/shared/array-editor.component.ts b/src/Squidex/app/features/content/shared/array-editor.component.ts index cef18bf2a..64c957e14 100644 --- a/src/Squidex/app/features/content/shared/array-editor.component.ts +++ b/src/Squidex/app/features/content/shared/array-editor.component.ts @@ -56,4 +56,13 @@ export class ArrayEditorComponent { this.arrayControl.setControl(i, controls[i]); } } + + public move(control: AbstractControl, index: number) { + let controls = [...this.arrayControl.controls]; + + controls.splice(controls.indexOf(control), 1); + controls.splice(index, 0, control); + + this.sort(controls); + } } \ No newline at end of file diff --git a/src/Squidex/app/features/content/shared/array-item.component.html b/src/Squidex/app/features/content/shared/array-item.component.html index 85a98ef24..baf0868c1 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.html +++ b/src/Squidex/app/features/content/shared/array-item.component.html @@ -5,6 +5,18 @@ Item #{{index + 1}} + + + + diff --git a/src/Squidex/app/features/content/shared/array-item.component.scss b/src/Squidex/app/features/content/shared/array-item.component.scss index 1727458d9..7de363cb8 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.scss +++ b/src/Squidex/app/features/content/shared/array-item.component.scss @@ -19,7 +19,14 @@ } .btn-link { - padding: .375rem; + & { + padding: .375rem; + } + + &:disabled, + &.disabled { + background: transparent; + } } .remove { diff --git a/src/Squidex/app/features/content/shared/array-item.component.ts b/src/Squidex/app/features/content/shared/array-item.component.ts index dab7b366a..16e95b0bc 100644 --- a/src/Squidex/app/features/content/shared/array-item.component.ts +++ b/src/Squidex/app/features/content/shared/array-item.component.ts @@ -28,6 +28,9 @@ export class ArrayItemComponent implements OnChanges { @Output() public removing = new EventEmitter(); + @Output() + public moving = new EventEmitter(); + @Output() public cloning = new EventEmitter(); @@ -43,6 +46,12 @@ export class ArrayItemComponent implements OnChanges { @Input() public isHidden = false; + @Input() + public isFirst = false; + + @Input() + public isLast = false; + @Input() public index: number; @@ -68,4 +77,20 @@ export class ArrayItemComponent implements OnChanges { this.fieldControls = this.field.nested.map(field => ({ field, control: this.itemForm.get(field.name)! })).filter(x => !!x.control); } } + + public moveTop() { + this.moving.emit(0); + } + + public moveUp() { + this.moving.emit(this.index - 1); + } + + public moveDown() { + this.moving.emit(this.index + 1); + } + + public moveBottom() { + this.moving.emit(99999); + } } \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index 037a4ed76..bf9c46c99 100644 --- a/src/Squidex/app/theme/icomoon/demo.html +++ b/src/Squidex/app/theme/icomoon/demo.html @@ -9,7 +9,7 @@
-

Font Name: icomoon (Glyphs: 110)

+

Font Name: icomoon (Glyphs: 112)

Grid Size: 14

@@ -640,249 +640,41 @@
-
-
- - - - icon-hour-glass -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-spinner -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-clock -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-bin2 -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-earth -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-elapsed -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-google -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-lock -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-microsoft -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-pause -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-play -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-reset -
-
- - -
-
- liga: - -
-
-
-
- - - - icon-settings2 -
-
- - -
-
- liga: - -
-
-
+
+
+

Grid Size: 16

+
- + - icon-timeout + icon-caret-bottom
- - + +
liga:
-
+
- + - icon-unlocked + icon-caret-top
- - + +
liga:
-
-
-

Grid Size: 16

@@ -1302,22 +1094,6 @@
-
-
- - - - icon-control-Stars -
-
- - -
-
- liga: - -
-

Grid Size: 32

diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 92b70c720a01cb89f1d5431525444963cee75cf6..3e1296635ec31f472c44f203146300022e7531e6 100644 GIT binary patch delta 482 zcmdmRo$=01Mz%XS3=9@I6WPpIF59`6O>`(1+{?hgum^|}l5-OaZoA)>nRr5`UXtB@ z4Fdz?1O|rG6B((ADIz-;E@fayj{vGO%K!>+GO?Bd`9OIFm5khyiVgnK?m+$)pq>jk z`N@etHr@+jV90C%%D>7@tSDgUW{hHB$SMHx74i~uQ)hZ{{s!`a`Wf2_@{3Ctn1M13 zIT9dw24-f)Qker)XaNG5^*u)bu^|swd zTNxM_ConLitjI`BOcB|xvYde-%>t;-ECVRO$;4U=DjB&Y6|473y94=CfO<~k zQ{o4uxmfgvLXDE}-sv7&&XlQD{cA=3rOSIA4uO`Yk*`5VYj0jh5+$S*EoUr#O<{uP@gm}(L?Z%GMYmYFqs=I3~Ro39MqEFet` rH*^YwVf18$40Fb!%@G-U7$?hQz2P$qF%mEe0m?E0anWX}>_dzIuJ2A5 diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg index 30c6b6c2f..a43377165 100644 --- a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg +++ b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg @@ -114,6 +114,8 @@ + + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index db00583bc2e07b4c3aceb67f05d65152cd56b30e..72ac12c4be721caa1c82c103ce281e871732ceee 100644 GIT binary patch delta 526 zcmeCV#<=4KV?6^S0|Ns$LjwadgMojrz7f9=?_QwD9w1Ig&P^=1?S5N^fq@Z-8FJDS ziwl6X0Fd7Sq&d=aD$^v{?biVL6Brm$Ph_MfrikoZxRik*Jpw3imH`ytWMVA^@`3UU zDjB&Y6&w7e-GTfqKs^_7@{=7Ce{8%L#K4f*0#xuSH?g9Cp_?&^fguZIkwRW#Zt6@g z&fh>j&;Z7^g8bqVphJNmM*<|zz|4GV;(>0)oXI|n%B;%;GWb_*E@7-m@ z5M|Jw9HT42C^$J@SG%5#^*;kEFFOY>h-MSxXJX(NWt`0p;j*zZf+YFH#P}J#ph_TO z9Q>l9{6O27fEaEp1B0pvo3f&knyHDIIinq;v5}ZKqa35CAXZT(Pf`AVJ`DU~P!oZ6 z0&Qah3Sx-O2H6I*A0!WPFbAU-$W>51P)}@rnH0_}Q|4}WIiBC(##o4Hcv_0!^p delta 303 zcmdmSgR$otV?6^S0|Ns$LjwadgMojrz7f9=?-8KL9w1Ig&P^=1?Rr~`fq_v5$j?bn zEG_`j0ziHTkmg9wsZ6u&KH3W8Phen3S&@;Nm?E-WWjO;wngvkaECVRO$;4U=N$~0)tjRu%%B)KT()d?wE@7-m+$@k1z$`Os z_RP=m{5D@1xLH727;fkk2*c>fHRqe!{Gn;Qco0}$l2FmQuui^-1J;uEz+>h~t+CKfO-FlK;cLHM@&ZJG4M zVvyJsAfE$@1=4dW(|}@k7#LDdfUqRH{hEx_#1saG^d&$wW*{uGbK%kqpde5TsE$De zggKd5OEYpyDi|0*Rxn-w;SK)M?m79%Ky`kZKmmqVApB$Fy`bF03ZTVVdw_feFz#lI z%1g{m1&RR;WNZWBnO>Z~3-XIgfNlj^4pqktWHB?Jn#{x4&6qQJ2BR|Ta)Au~Rhthm z)+8!3lrwoUb25lBXan_&u(31pF)AymsWa*^nwppyD;kN33Qk_Ft6k5=`k#T7mz{$b zM6-$UGcoXsGR|g)aM@THL6ZDpV*HF=P$dvC4t`NlexUtKK#XLQstB91qLLcW3Ufv~ zMq?u}aYi{tQ9-PtOrE0r|9lwu#h@kv?F8D!1{A~)n+>uJXg^3E;$RL&FOaLCdZ3=z zY?>U-EK}xgcR8Nl<|_j?3(#>43^#PwO@h&rSEQLUmTZ2Iwuh08$rI>&&&jhg-pLqz jGqf{&Vzj{M2~Z&;5SK7UFo=OPF)#rWjqv8pnM)Y~3?_E( delta 348 zcmZp<$#~-$qe!{Gn;Qco0}y0KFmQuup2>wd!jl_vSSD(V)E`OCO)OwwV9WqY<$&;Q z*V|(0iNzqXD?mO66bq#1RHgyN?l3Tx#?xU?4sfj5J3~4PuHD(|zvR!3)22cp0bx!i*5ZuZk_w>M1EBsBAiR37w0ll|GEkjg2GB5uXCQoR_L`R5#0sFrnG=9~ z1u*VpjLJ*QO$CZ=0BURl;hA2XzYFqWYYZ5odqy#X_%$hy(b3DJzR|aktpjrlo8#)ETFnaQdbaTd{O&NO_Cm+dtBVia~ dBw!Q*lw<_rBE|>?F_1zACQ!I-zMr*}5dam + + + + + + + image/svg+xml + + + + + + + caret-down + + + + + diff --git a/src/Squidex/app/theme/icomoon/icons/caret-top.svg b/src/Squidex/app/theme/icomoon/icons/caret-top.svg new file mode 100644 index 000000000..714f0cc5b --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/caret-top.svg @@ -0,0 +1,66 @@ + + + + + + + + image/svg+xml + + + + + + + caret-up + + + + + diff --git a/src/Squidex/app/theme/icomoon/selection.json b/src/Squidex/app/theme/icomoon/selection.json index fe5af0d25..c419be8cd 100644 --- a/src/Squidex/app/theme/icomoon/selection.json +++ b/src/Squidex/app/theme/icomoon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"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":28,"code":59754,"name":"clone"},"setIdx":0,"setId":3,"iconIdx":0},{"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"],"attrs":[{},{},{}],"width":1140,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["control-Tags"]},"attrs":[{},{},{}],"properties":{"order":119,"id":220,"name":"control-Tags","prevSize":28,"code":59747},"setIdx":2,"setId":1,"iconIdx":78},{"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,"grid":14,"tags":["control-Checkboxes"]},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":219,"name":"control-Checkboxes","prevSize":28,"code":59746},"setIdx":2,"setId":1,"iconIdx":79},{"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,"grid":14,"tags":["control-Html"]},"attrs":[{},{},{},{}],"properties":{"order":116,"id":217,"name":"control-Html","prevSize":28,"code":59744},"setIdx":2,"setId":1,"iconIdx":80},{"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"],"attrs":[{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["single-content"]},"attrs":[{},{},{},{}],"properties":{"order":112,"id":214,"name":"single-content","prevSize":28,"code":59736},"setIdx":2,"setId":1,"iconIdx":81},{"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"],"attrs":[{},{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["multiple-content"]},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":213,"name":"multiple-content","prevSize":28,"code":59735},"setIdx":2,"setId":1,"iconIdx":82},{"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,"grid":14,"tags":["type-Array"]},"attrs":[{},{},{},{}],"properties":{"order":108,"id":211,"name":"type-Array","prevSize":28,"code":59734},"setIdx":2,"setId":1,"iconIdx":83},{"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"],"attrs":[{}],"width":366,"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":28,"code":59733,"name":"exclamation"},"setIdx":2,"setId":1,"iconIdx":84},{"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,"grid":14,"tags":["orleans"]},"attrs":[{}],"properties":{"order":99,"id":209,"name":"orleans","prevSize":28,"code":59723},"setIdx":2,"setId":1,"iconIdx":85},{"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,"grid":14,"tags":["document-lock"]},"attrs":[{},{}],"properties":{"order":97,"id":208,"name":"document-lock","prevSize":28,"code":59721},"setIdx":2,"setId":1,"iconIdx":86},{"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,"grid":14,"tags":["document-unpublish"]},"attrs":[{},{}],"properties":{"order":96,"id":207,"name":"document-unpublish","prevSize":28,"code":59711},"setIdx":2,"setId":1,"iconIdx":87},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":28,"code":59648,"name":"angle-down"},"setIdx":2,"setId":1,"iconIdx":88},{"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"],"attrs":[{}],"width":384,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":28,"code":59649,"name":"angle-left"},"setIdx":2,"setId":1,"iconIdx":89},{"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"],"attrs":[{}],"width":347,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":0,"prevSize":28,"code":59697,"name":"angle-right"},"setIdx":2,"setId":1,"iconIdx":90},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":2,"prevSize":28,"code":59651,"name":"angle-up"},"setIdx":2,"setId":1,"iconIdx":91},{"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,"grid":14,"tags":["api"]},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":206,"name":"api","prevSize":28,"code":59717},"setIdx":2,"setId":1,"iconIdx":92},{"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,"grid":14,"tags":["assets"]},"attrs":[{},{},{}],"properties":{"order":95,"id":205,"name":"assets","prevSize":28,"code":59720},"setIdx":2,"setId":1,"iconIdx":93},{"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"],"attrs":[{}],"width":951,"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":28,"code":59709,"name":"bug"},"setIdx":2,"setId":1,"iconIdx":94},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":4,"prevSize":28,"code":59692,"name":"caret-down"},"setIdx":2,"setId":1,"iconIdx":95},{"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"],"attrs":[{}],"width":402,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":6,"prevSize":28,"code":59690,"name":"caret-left"},"setIdx":2,"setId":1,"iconIdx":96},{"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"],"attrs":[{}],"width":329,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":28,"code":59689,"name":"caret-right"},"setIdx":2,"setId":1,"iconIdx":97},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":5,"prevSize":28,"code":59691,"name":"caret-up"},"setIdx":2,"setId":1,"iconIdx":98},{"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,"grid":14,"tags":["content"]},"attrs":[{},{},{},{}],"properties":{"order":93,"id":204,"name":"contents, trigger-ContentChanged","prevSize":28,"code":59718},"setIdx":2,"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,"grid":14,"tags":["control-date"]},"attrs":[{}],"properties":{"order":71,"id":42,"name":"control-Date","prevSize":28,"code":59702},"setIdx":2,"setId":1,"iconIdx":100},{"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,"grid":14,"tags":["control-date-time"]},"attrs":[{}],"properties":{"order":70,"id":41,"name":"control-DateTime","prevSize":28,"code":59703},"setIdx":2,"setId":1,"iconIdx":101},{"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,"grid":14,"tags":["control-Markdown"]},"attrs":[{}],"properties":{"order":72,"id":43,"name":"control-Markdown","prevSize":28,"code":59704},"setIdx":2,"setId":1,"iconIdx":102},{"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":14,"order":83,"prevSize":28,"code":61450},"setIdx":2,"setId":1,"iconIdx":103},{"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":178,"order":89,"prevSize":28,"code":61641},"setIdx":2,"setId":1,"iconIdx":104},{"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,"grid":14,"tags":["user-o"]},"attrs":[{}],"properties":{"order":64,"id":38,"name":"user-o","prevSize":28,"code":59698},"setIdx":2,"setId":1,"iconIdx":105},{"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,"grid":14,"tags":["webhooks"]},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":203,"name":"rules","prevSize":28,"code":59719},"setIdx":2,"setId":1,"iconIdx":106},{"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":1,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":1,"setId":2,"iconIdx":0},{"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":0,"name":"plus-square","prevSize":24,"code":59752},"setIdx":1,"setId":2,"iconIdx":1},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":2,"setId":1,"iconIdx":4},{"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":1,"id":0,"name":"comments","prevSize":24,"code":59743},"setIdx":2,"setId":1,"iconIdx":5},{"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":2,"prevSize":24,"code":59739,"name":"backup"},"setIdx":2,"setId":1,"iconIdx":6},{"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":0,"prevSize":24,"code":59738,"name":"support"},"setIdx":2,"setId":1,"iconIdx":7},{"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":0,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":2,"setId":1,"iconIdx":8},{"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":0,"prevSize":24,"code":59710,"name":"download"},"setIdx":2,"setId":1,"iconIdx":9},{"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,"grid":16,"tags":["show"]},"attrs":[{},{},{}],"properties":{"order":123,"id":224,"name":"show","prevSize":24,"code":59748},"setIdx":2,"setId":1,"iconIdx":0},{"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,"grid":16,"tags":["show-all"]},"attrs":[{},{},{},{}],"properties":{"order":122,"id":223,"name":"show-all","prevSize":24,"code":59749},"setIdx":2,"setId":1,"iconIdx":1},{"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,"grid":16,"tags":["hide"]},"attrs":[{},{},{}],"properties":{"order":121,"id":222,"name":"hide","prevSize":24,"code":59750},"setIdx":2,"setId":1,"iconIdx":2},{"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,"grid":16,"tags":["hide-all"]},"attrs":[{},{},{},{}],"properties":{"order":120,"id":221,"name":"hide-all","prevSize":24,"code":59751},"setIdx":2,"setId":1,"iconIdx":3},{"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":0,"prevSize":24,"code":59737,"name":"spinner2"},"setIdx":2,"setId":1,"iconIdx":10},{"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":2,"prevSize":24,"code":59741,"name":"star-full"},"setIdx":2,"setId":1,"iconIdx":11},{"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":1,"prevSize":24,"code":59742,"name":"star-empty"},"setIdx":2,"setId":1,"iconIdx":12},{"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":0,"prevSize":24,"code":59740,"name":"twitter"},"setIdx":2,"setId":1,"iconIdx":13},{"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":1,"prevSize":24,"code":59732,"name":"hour-glass"},"setIdx":2,"setId":1,"iconIdx":14},{"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":0,"prevSize":24,"code":59731,"name":"spinner"},"setIdx":2,"setId":1,"iconIdx":15},{"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":0,"prevSize":24,"code":59728,"name":"clock"},"setIdx":2,"setId":1,"iconIdx":16},{"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":0,"name":"bin2","prevSize":24,"code":59650},"setIdx":2,"setId":1,"iconIdx":17},{"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":202,"order":91,"prevSize":24,"code":59850},"setIdx":2,"setId":1,"iconIdx":18},{"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":2,"prevSize":24,"code":59715,"name":"elapsed"},"setIdx":2,"setId":1,"iconIdx":19},{"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":0,"prevSize":24,"code":59707,"name":"google"},"setIdx":2,"setId":1,"iconIdx":20},{"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":0,"prevSize":24,"code":59700,"name":"lock"},"setIdx":2,"setId":1,"iconIdx":21},{"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":1,"prevSize":24,"code":59712,"name":"microsoft"},"setIdx":2,"setId":1,"iconIdx":22},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":1,"prevSize":24,"code":59695,"name":"pause"},"setIdx":2,"setId":1,"iconIdx":23},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":0,"prevSize":24,"code":59696,"name":"play"},"setIdx":2,"setId":1,"iconIdx":24},{"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":2,"prevSize":24,"code":59694,"name":"reset"},"setIdx":2,"setId":1,"iconIdx":25},{"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":1,"prevSize":24,"code":59693,"name":"settings2"},"setIdx":2,"setId":1,"iconIdx":26},{"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":1,"prevSize":24,"code":59716,"name":"timeout"},"setIdx":2,"setId":1,"iconIdx":27},{"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":1,"prevSize":24,"code":59699,"name":"unlocked"},"setIdx":2,"setId":1,"iconIdx":28},{"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":1,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":2,"setId":1,"iconIdx":29},{"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":0,"name":"list","prevSize":20,"code":59726},"setIdx":2,"setId":1,"iconIdx":30},{"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":0,"prevSize":20,"code":59708,"name":"info"},"setIdx":2,"setId":1,"iconIdx":31},{"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":2,"setId":1,"iconIdx":32},{"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"],"attrs":[{}],"width":1344,"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59701,"name":"browser"},"setIdx":2,"setId":1,"iconIdx":33},{"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":0,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":2,"setId":1,"iconIdx":34},{"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":0,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":2,"setId":1,"iconIdx":35},{"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,"grid":0,"tags":["prerender"]},"attrs":[{},{},{}],"properties":{"order":114,"id":1,"name":"prerender","prevSize":32,"code":59724},"setIdx":2,"setId":1,"iconIdx":36},{"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,"grid":0,"tags":["circle"]},"attrs":[{}],"properties":{"order":106,"id":0,"name":"circle","prevSize":32,"code":59729},"setIdx":2,"setId":1,"iconIdx":37},{"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,"grid":0,"tags":["control-Slug"]},"attrs":[{},{}],"properties":{"order":103,"id":0,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":2,"setId":1,"iconIdx":38},{"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,"grid":0,"tags":["Tags"]},"attrs":[{},{},{},{}],"properties":{"order":98,"id":0,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":2,"setId":1,"iconIdx":39},{"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,"grid":0,"tags":["activity"]},"attrs":[{}],"properties":{"order":12,"id":36,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":2,"setId":1,"iconIdx":40},{"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,"grid":0,"tags":["add"]},"attrs":[{}],"properties":{"order":13,"id":35,"name":"add, plus","prevSize":32,"code":59653},"setIdx":2,"setId":1,"iconIdx":41},{"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,"grid":0,"tags":["check-circle"]},"attrs":[{}],"properties":{"order":14,"id":34,"name":"check-circle","prevSize":32,"code":59654},"setIdx":2,"setId":1,"iconIdx":42},{"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,"grid":0,"tags":["check-circle-filled"]},"attrs":[{}],"properties":{"order":27,"id":33,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":2,"setId":1,"iconIdx":43},{"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,"grid":0,"tags":["close"]},"attrs":[{}],"properties":{"order":28,"id":32,"name":"close","prevSize":32,"code":59656},"setIdx":2,"setId":1,"iconIdx":44},{"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,"grid":0,"tags":["content"]},"attrs":[{}],"properties":{"order":37,"id":31,"name":"type-References","prevSize":32,"code":59657},"setIdx":2,"setId":1,"iconIdx":45},{"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,"grid":0,"tags":["control-checkbox"]},"attrs":[{}],"properties":{"order":38,"id":30,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":2,"setId":1,"iconIdx":46},{"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,"grid":0,"tags":["control-dropdown"]},"attrs":[{}],"properties":{"order":39,"id":29,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":2,"setId":1,"iconIdx":47},{"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,"grid":0,"tags":["control-input"]},"attrs":[{}],"properties":{"order":41,"id":28,"name":"control-Input","prevSize":32,"code":59660},"setIdx":2,"setId":1,"iconIdx":48},{"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,"grid":0,"tags":["control-radio"]},"attrs":[{}],"properties":{"order":42,"id":27,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":2,"setId":1,"iconIdx":49},{"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,"grid":0,"tags":["control-textarea"]},"attrs":[{}],"properties":{"order":17,"id":26,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":2,"setId":1,"iconIdx":50},{"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,"grid":0,"tags":["control-toggle"]},"attrs":[{}],"properties":{"order":16,"id":25,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":2,"setId":1,"iconIdx":51},{"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,"grid":0,"tags":["copy"]},"attrs":[{}],"properties":{"order":90,"id":24,"name":"copy","prevSize":32,"code":59664},"setIdx":2,"setId":1,"iconIdx":52},{"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,"grid":0,"tags":["dashboard"]},"attrs":[{},{},{}],"properties":{"order":26,"id":23,"name":"dashboard","prevSize":32,"code":59665},"setIdx":2,"setId":1,"iconIdx":53},{"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,"grid":0,"tags":["delete"]},"attrs":[{}],"properties":{"order":29,"id":22,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":2,"setId":1,"iconIdx":54},{"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,"grid":0,"tags":["delete-filled"]},"attrs":[{}],"properties":{"order":36,"id":21,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":2,"setId":1,"iconIdx":55},{"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,"grid":0,"tags":["document-delete"]},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":2,"setId":1,"iconIdx":56},{"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,"grid":0,"tags":["document-disable"]},"attrs":[{}],"properties":{"order":40,"id":19,"name":"document-disable","prevSize":32,"code":59669},"setIdx":2,"setId":1,"iconIdx":57},{"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,"grid":0,"tags":["document-publish"]},"attrs":[{}],"properties":{"order":44,"id":18,"name":"document-publish","prevSize":32,"code":59670},"setIdx":2,"setId":1,"iconIdx":58},{"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,"grid":0,"tags":["drag"]},"attrs":[{}],"properties":{"order":43,"id":17,"name":"drag","prevSize":32,"code":59671},"setIdx":2,"setId":1,"iconIdx":59},{"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,"grid":0,"tags":["filter"]},"attrs":[{}],"properties":{"order":18,"id":16,"name":"filter","prevSize":32,"code":59672},"setIdx":2,"setId":1,"iconIdx":60},{"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":0,"name":"github","prevSize":32,"code":59713},"setIdx":2,"setId":1,"iconIdx":61},{"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,"grid":0,"tags":["help"]},"attrs":[{}],"properties":{"order":19,"id":15,"name":"help","prevSize":32,"code":59673},"setIdx":2,"setId":1,"iconIdx":62},{"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,"grid":0,"tags":["location"]},"attrs":[{}],"properties":{"order":25,"id":13,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":2,"setId":1,"iconIdx":63},{"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,"grid":0,"tags":["logo"]},"attrs":[{}],"properties":{"order":31,"id":12,"name":"logo","prevSize":32,"code":59676},"setIdx":2,"setId":1,"iconIdx":64},{"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,"grid":0,"tags":["media"]},"attrs":[{}],"properties":{"order":30,"id":11,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":2,"setId":1,"iconIdx":65},{"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,"grid":0,"tags":["more"]},"attrs":[{}],"properties":{"order":34,"id":10,"name":"more, dots","prevSize":32,"code":59678},"setIdx":2,"setId":1,"iconIdx":66},{"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,"grid":0,"tags":["pencil"]},"attrs":[{}],"properties":{"order":47,"id":9,"name":"pencil","prevSize":32,"code":59679},"setIdx":2,"setId":1,"iconIdx":67},{"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,"grid":0,"tags":["reference"]},"attrs":[{}],"properties":{"order":45,"id":8,"name":"reference","prevSize":32,"code":59680},"setIdx":2,"setId":1,"iconIdx":68},{"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,"grid":0,"tags":["schemas"]},"attrs":[{},{},{},{}],"properties":{"order":46,"id":7,"name":"schemas","prevSize":32,"code":59681},"setIdx":2,"setId":1,"iconIdx":69},{"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,"grid":0,"tags":["search"]},"attrs":[{}],"properties":{"order":23,"id":6,"name":"search","prevSize":32,"code":59682},"setIdx":2,"setId":1,"iconIdx":70},{"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,"grid":0,"tags":["settings"]},"attrs":[{}],"properties":{"order":22,"id":5,"name":"settings","prevSize":32,"code":59683},"setIdx":2,"setId":1,"iconIdx":71},{"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,"grid":0,"tags":["type-boolean"]},"attrs":[{}],"properties":{"order":21,"id":4,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":2,"setId":1,"iconIdx":72},{"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,"grid":0,"tags":["type-datetime"]},"attrs":[{}],"properties":{"order":24,"id":3,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":2,"setId":1,"iconIdx":73},{"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,"grid":0,"tags":["json"]},"attrs":[{}],"properties":{"order":20,"id":14,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":2,"setId":1,"iconIdx":74},{"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,"grid":0,"tags":["type-number"]},"attrs":[{}],"properties":{"order":32,"id":2,"name":"type-Number","prevSize":32,"code":59686},"setIdx":2,"setId":1,"iconIdx":75},{"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,"grid":0,"tags":["type-string"]},"attrs":[{}],"properties":{"order":48,"id":1,"name":"type-String","prevSize":32,"code":59687},"setIdx":2,"setId":1,"iconIdx":76},{"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,"grid":0,"tags":["user"]},"attrs":[{}],"properties":{"order":33,"id":0,"name":"user","prevSize":32,"code":59688},"setIdx":2,"setId":1,"iconIdx":77}],"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,"classSelector":".icon","name":"icomoon"},"historySize":100,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"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":28,"code":59754,"name":"clone"},"setIdx":0,"setId":3,"iconIdx":0},{"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"],"attrs":[{},{},{}],"width":1140,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["control-Tags"]},"attrs":[{},{},{}],"properties":{"order":119,"id":220,"name":"control-Tags","prevSize":28,"code":59747},"setIdx":2,"setId":1,"iconIdx":80},{"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,"grid":14,"tags":["control-Checkboxes"]},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":219,"name":"control-Checkboxes","prevSize":28,"code":59746},"setIdx":2,"setId":1,"iconIdx":81},{"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,"grid":14,"tags":["control-Html"]},"attrs":[{},{},{},{}],"properties":{"order":116,"id":217,"name":"control-Html","prevSize":28,"code":59744},"setIdx":2,"setId":1,"iconIdx":82},{"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"],"attrs":[{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["single-content"]},"attrs":[{},{},{},{}],"properties":{"order":112,"id":214,"name":"single-content","prevSize":28,"code":59736},"setIdx":2,"setId":1,"iconIdx":83},{"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"],"attrs":[{},{},{},{},{}],"width":1029,"isMulticolor":false,"isMulticolor2":false,"grid":14,"tags":["multiple-content"]},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":213,"name":"multiple-content","prevSize":28,"code":59735},"setIdx":2,"setId":1,"iconIdx":84},{"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,"grid":14,"tags":["type-Array"]},"attrs":[{},{},{},{}],"properties":{"order":108,"id":211,"name":"type-Array","prevSize":28,"code":59734},"setIdx":2,"setId":1,"iconIdx":85},{"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"],"attrs":[{}],"width":366,"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":28,"code":59733,"name":"exclamation"},"setIdx":2,"setId":1,"iconIdx":86},{"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,"grid":14,"tags":["orleans"]},"attrs":[{}],"properties":{"order":99,"id":209,"name":"orleans","prevSize":28,"code":59723},"setIdx":2,"setId":1,"iconIdx":87},{"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,"grid":14,"tags":["document-lock"]},"attrs":[{},{}],"properties":{"order":97,"id":208,"name":"document-lock","prevSize":28,"code":59721},"setIdx":2,"setId":1,"iconIdx":88},{"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,"grid":14,"tags":["document-unpublish"]},"attrs":[{},{}],"properties":{"order":96,"id":207,"name":"document-unpublish","prevSize":28,"code":59711},"setIdx":2,"setId":1,"iconIdx":89},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":28,"code":59648,"name":"angle-down"},"setIdx":2,"setId":1,"iconIdx":90},{"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"],"attrs":[{}],"width":384,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":0,"prevSize":28,"code":59649,"name":"angle-left"},"setIdx":2,"setId":1,"iconIdx":91},{"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"],"attrs":[{}],"width":347,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":0,"prevSize":28,"code":59697,"name":"angle-right"},"setIdx":2,"setId":1,"iconIdx":92},{"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"],"attrs":[{}],"width":658,"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":2,"prevSize":28,"code":59651,"name":"angle-up"},"setIdx":2,"setId":1,"iconIdx":93},{"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,"grid":14,"tags":["api"]},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":206,"name":"api","prevSize":28,"code":59717},"setIdx":2,"setId":1,"iconIdx":94},{"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,"grid":14,"tags":["assets"]},"attrs":[{},{},{}],"properties":{"order":95,"id":205,"name":"assets","prevSize":28,"code":59720},"setIdx":2,"setId":1,"iconIdx":95},{"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"],"attrs":[{}],"width":951,"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":28,"code":59709,"name":"bug"},"setIdx":2,"setId":1,"iconIdx":96},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":4,"prevSize":28,"code":59692,"name":"caret-down"},"setIdx":2,"setId":1,"iconIdx":97},{"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"],"attrs":[{}],"width":402,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":6,"prevSize":28,"code":59690,"name":"caret-left"},"setIdx":2,"setId":1,"iconIdx":98},{"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"],"attrs":[{}],"width":329,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":28,"code":59689,"name":"caret-right"},"setIdx":2,"setId":1,"iconIdx":99},{"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"],"attrs":[{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":5,"prevSize":28,"code":59691,"name":"caret-up"},"setIdx":2,"setId":1,"iconIdx":100},{"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,"grid":14,"tags":["content"]},"attrs":[{},{},{},{}],"properties":{"order":93,"id":204,"name":"contents, trigger-ContentChanged","prevSize":28,"code":59718},"setIdx":2,"setId":1,"iconIdx":101},{"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,"grid":14,"tags":["control-date"]},"attrs":[{}],"properties":{"order":71,"id":42,"name":"control-Date","prevSize":28,"code":59702},"setIdx":2,"setId":1,"iconIdx":102},{"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,"grid":14,"tags":["control-date-time"]},"attrs":[{}],"properties":{"order":70,"id":41,"name":"control-DateTime","prevSize":28,"code":59703},"setIdx":2,"setId":1,"iconIdx":103},{"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,"grid":14,"tags":["control-Markdown"]},"attrs":[{}],"properties":{"order":72,"id":43,"name":"control-Markdown","prevSize":28,"code":59704},"setIdx":2,"setId":1,"iconIdx":104},{"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":14,"order":83,"prevSize":28,"code":61450},"setIdx":2,"setId":1,"iconIdx":105},{"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":178,"order":89,"prevSize":28,"code":61641},"setIdx":2,"setId":1,"iconIdx":106},{"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,"grid":14,"tags":["user-o"]},"attrs":[{}],"properties":{"order":64,"id":38,"name":"user-o","prevSize":28,"code":59698},"setIdx":2,"setId":1,"iconIdx":107},{"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,"grid":14,"tags":["webhooks"]},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":203,"name":"rules","prevSize":28,"code":59719},"setIdx":2,"setId":1,"iconIdx":108},{"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":1,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":1,"setId":2,"iconIdx":0},{"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":0,"name":"plus-square","prevSize":24,"code":59752},"setIdx":1,"setId":2,"iconIdx":1},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":2,"setId":1,"iconIdx":6},{"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":1,"id":0,"name":"comments","prevSize":24,"code":59743},"setIdx":2,"setId":1,"iconIdx":7},{"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":2,"prevSize":24,"code":59739,"name":"backup"},"setIdx":2,"setId":1,"iconIdx":8},{"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":0,"prevSize":24,"code":59738,"name":"support"},"setIdx":2,"setId":1,"iconIdx":9},{"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":0,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":2,"setId":1,"iconIdx":10},{"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":0,"prevSize":24,"code":59710,"name":"download"},"setIdx":2,"setId":1,"iconIdx":11},{"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"],"attrs":[{},{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"grid":16,"tags":["caret-bottom"]},"attrs":[{},{}],"properties":{"order":125,"id":226,"name":"caret-bottom","prevSize":24,"code":59755},"setIdx":2,"setId":1,"iconIdx":0},{"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"],"attrs":[{},{}],"width":585,"isMulticolor":false,"isMulticolor2":false,"grid":16,"tags":["caret-top"]},"attrs":[{},{}],"properties":{"order":124,"id":225,"name":"caret-top","prevSize":24,"code":59756},"setIdx":2,"setId":1,"iconIdx":1},{"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,"grid":16,"tags":["show"]},"attrs":[{},{},{}],"properties":{"order":123,"id":224,"name":"show","prevSize":24,"code":59748},"setIdx":2,"setId":1,"iconIdx":2},{"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,"grid":16,"tags":["show-all"]},"attrs":[{},{},{},{}],"properties":{"order":122,"id":223,"name":"show-all","prevSize":24,"code":59749},"setIdx":2,"setId":1,"iconIdx":3},{"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,"grid":16,"tags":["hide"]},"attrs":[{},{},{}],"properties":{"order":121,"id":222,"name":"hide","prevSize":24,"code":59750},"setIdx":2,"setId":1,"iconIdx":4},{"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,"grid":16,"tags":["hide-all"]},"attrs":[{},{},{},{}],"properties":{"order":120,"id":221,"name":"hide-all","prevSize":24,"code":59751},"setIdx":2,"setId":1,"iconIdx":5},{"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":0,"prevSize":24,"code":59737,"name":"spinner2"},"setIdx":2,"setId":1,"iconIdx":12},{"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":2,"prevSize":24,"code":59741,"name":"star-full"},"setIdx":2,"setId":1,"iconIdx":13},{"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":1,"prevSize":24,"code":59742,"name":"star-empty"},"setIdx":2,"setId":1,"iconIdx":14},{"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":0,"prevSize":24,"code":59740,"name":"twitter"},"setIdx":2,"setId":1,"iconIdx":15},{"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":1,"prevSize":24,"code":59732,"name":"hour-glass"},"setIdx":2,"setId":1,"iconIdx":16},{"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":0,"prevSize":24,"code":59731,"name":"spinner"},"setIdx":2,"setId":1,"iconIdx":17},{"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":0,"prevSize":24,"code":59728,"name":"clock"},"setIdx":2,"setId":1,"iconIdx":18},{"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":0,"name":"bin2","prevSize":24,"code":59650},"setIdx":2,"setId":1,"iconIdx":19},{"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":202,"order":91,"prevSize":24,"code":59850},"setIdx":2,"setId":1,"iconIdx":20},{"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":2,"prevSize":24,"code":59715,"name":"elapsed"},"setIdx":2,"setId":1,"iconIdx":21},{"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":0,"prevSize":24,"code":59707,"name":"google"},"setIdx":2,"setId":1,"iconIdx":22},{"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":0,"prevSize":24,"code":59700,"name":"lock"},"setIdx":2,"setId":1,"iconIdx":23},{"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":1,"prevSize":24,"code":59712,"name":"microsoft"},"setIdx":2,"setId":1,"iconIdx":24},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":1,"prevSize":24,"code":59695,"name":"pause"},"setIdx":2,"setId":1,"iconIdx":25},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":0,"prevSize":24,"code":59696,"name":"play"},"setIdx":2,"setId":1,"iconIdx":26},{"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":2,"prevSize":24,"code":59694,"name":"reset"},"setIdx":2,"setId":1,"iconIdx":27},{"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":1,"prevSize":24,"code":59693,"name":"settings2"},"setIdx":2,"setId":1,"iconIdx":28},{"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":1,"prevSize":24,"code":59716,"name":"timeout"},"setIdx":2,"setId":1,"iconIdx":29},{"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":1,"prevSize":24,"code":59699,"name":"unlocked"},"setIdx":2,"setId":1,"iconIdx":30},{"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":1,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":2,"setId":1,"iconIdx":31},{"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":0,"name":"list","prevSize":20,"code":59726},"setIdx":2,"setId":1,"iconIdx":32},{"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":0,"prevSize":20,"code":59708,"name":"info"},"setIdx":2,"setId":1,"iconIdx":33},{"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":2,"setId":1,"iconIdx":34},{"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"],"attrs":[{}],"width":1344,"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59701,"name":"browser"},"setIdx":2,"setId":1,"iconIdx":35},{"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":0,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":2,"setId":1,"iconIdx":36},{"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":0,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":2,"setId":1,"iconIdx":37},{"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,"grid":0,"tags":["prerender"]},"attrs":[{},{},{}],"properties":{"order":114,"id":1,"name":"prerender","prevSize":32,"code":59724},"setIdx":2,"setId":1,"iconIdx":38},{"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,"grid":0,"tags":["circle"]},"attrs":[{}],"properties":{"order":106,"id":0,"name":"circle","prevSize":32,"code":59729},"setIdx":2,"setId":1,"iconIdx":39},{"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,"grid":0,"tags":["control-Slug"]},"attrs":[{},{}],"properties":{"order":103,"id":0,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":2,"setId":1,"iconIdx":40},{"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,"grid":0,"tags":["Tags"]},"attrs":[{},{},{},{}],"properties":{"order":98,"id":0,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":2,"setId":1,"iconIdx":41},{"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,"grid":0,"tags":["activity"]},"attrs":[{}],"properties":{"order":12,"id":36,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":2,"setId":1,"iconIdx":42},{"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,"grid":0,"tags":["add"]},"attrs":[{}],"properties":{"order":13,"id":35,"name":"add, plus","prevSize":32,"code":59653},"setIdx":2,"setId":1,"iconIdx":43},{"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,"grid":0,"tags":["check-circle"]},"attrs":[{}],"properties":{"order":14,"id":34,"name":"check-circle","prevSize":32,"code":59654},"setIdx":2,"setId":1,"iconIdx":44},{"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,"grid":0,"tags":["check-circle-filled"]},"attrs":[{}],"properties":{"order":27,"id":33,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":2,"setId":1,"iconIdx":45},{"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,"grid":0,"tags":["close"]},"attrs":[{}],"properties":{"order":28,"id":32,"name":"close","prevSize":32,"code":59656},"setIdx":2,"setId":1,"iconIdx":46},{"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,"grid":0,"tags":["content"]},"attrs":[{}],"properties":{"order":37,"id":31,"name":"type-References","prevSize":32,"code":59657},"setIdx":2,"setId":1,"iconIdx":47},{"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,"grid":0,"tags":["control-checkbox"]},"attrs":[{}],"properties":{"order":38,"id":30,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":2,"setId":1,"iconIdx":48},{"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,"grid":0,"tags":["control-dropdown"]},"attrs":[{}],"properties":{"order":39,"id":29,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":2,"setId":1,"iconIdx":49},{"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,"grid":0,"tags":["control-input"]},"attrs":[{}],"properties":{"order":41,"id":28,"name":"control-Input","prevSize":32,"code":59660},"setIdx":2,"setId":1,"iconIdx":50},{"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,"grid":0,"tags":["control-radio"]},"attrs":[{}],"properties":{"order":42,"id":27,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":2,"setId":1,"iconIdx":51},{"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,"grid":0,"tags":["control-textarea"]},"attrs":[{}],"properties":{"order":17,"id":26,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":2,"setId":1,"iconIdx":52},{"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,"grid":0,"tags":["control-toggle"]},"attrs":[{}],"properties":{"order":16,"id":25,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":2,"setId":1,"iconIdx":53},{"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,"grid":0,"tags":["copy"]},"attrs":[{}],"properties":{"order":90,"id":24,"name":"copy","prevSize":32,"code":59664},"setIdx":2,"setId":1,"iconIdx":54},{"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,"grid":0,"tags":["dashboard"]},"attrs":[{},{},{}],"properties":{"order":26,"id":23,"name":"dashboard","prevSize":32,"code":59665},"setIdx":2,"setId":1,"iconIdx":55},{"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,"grid":0,"tags":["delete"]},"attrs":[{}],"properties":{"order":29,"id":22,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":2,"setId":1,"iconIdx":56},{"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,"grid":0,"tags":["delete-filled"]},"attrs":[{}],"properties":{"order":36,"id":21,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":2,"setId":1,"iconIdx":57},{"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,"grid":0,"tags":["document-delete"]},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":2,"setId":1,"iconIdx":58},{"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,"grid":0,"tags":["document-disable"]},"attrs":[{}],"properties":{"order":40,"id":19,"name":"document-disable","prevSize":32,"code":59669},"setIdx":2,"setId":1,"iconIdx":59},{"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,"grid":0,"tags":["document-publish"]},"attrs":[{}],"properties":{"order":44,"id":18,"name":"document-publish","prevSize":32,"code":59670},"setIdx":2,"setId":1,"iconIdx":60},{"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,"grid":0,"tags":["drag"]},"attrs":[{}],"properties":{"order":43,"id":17,"name":"drag","prevSize":32,"code":59671},"setIdx":2,"setId":1,"iconIdx":61},{"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,"grid":0,"tags":["filter"]},"attrs":[{}],"properties":{"order":18,"id":16,"name":"filter","prevSize":32,"code":59672},"setIdx":2,"setId":1,"iconIdx":62},{"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":0,"name":"github","prevSize":32,"code":59713},"setIdx":2,"setId":1,"iconIdx":63},{"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,"grid":0,"tags":["help"]},"attrs":[{}],"properties":{"order":19,"id":15,"name":"help","prevSize":32,"code":59673},"setIdx":2,"setId":1,"iconIdx":64},{"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,"grid":0,"tags":["location"]},"attrs":[{}],"properties":{"order":25,"id":13,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":2,"setId":1,"iconIdx":65},{"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,"grid":0,"tags":["logo"]},"attrs":[{}],"properties":{"order":31,"id":12,"name":"logo","prevSize":32,"code":59676},"setIdx":2,"setId":1,"iconIdx":66},{"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,"grid":0,"tags":["media"]},"attrs":[{}],"properties":{"order":30,"id":11,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":2,"setId":1,"iconIdx":67},{"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,"grid":0,"tags":["more"]},"attrs":[{}],"properties":{"order":34,"id":10,"name":"more, dots","prevSize":32,"code":59678},"setIdx":2,"setId":1,"iconIdx":68},{"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,"grid":0,"tags":["pencil"]},"attrs":[{}],"properties":{"order":47,"id":9,"name":"pencil","prevSize":32,"code":59679},"setIdx":2,"setId":1,"iconIdx":69},{"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,"grid":0,"tags":["reference"]},"attrs":[{}],"properties":{"order":45,"id":8,"name":"reference","prevSize":32,"code":59680},"setIdx":2,"setId":1,"iconIdx":70},{"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,"grid":0,"tags":["schemas"]},"attrs":[{},{},{},{}],"properties":{"order":46,"id":7,"name":"schemas","prevSize":32,"code":59681},"setIdx":2,"setId":1,"iconIdx":71},{"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,"grid":0,"tags":["search"]},"attrs":[{}],"properties":{"order":23,"id":6,"name":"search","prevSize":32,"code":59682},"setIdx":2,"setId":1,"iconIdx":72},{"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,"grid":0,"tags":["settings"]},"attrs":[{}],"properties":{"order":22,"id":5,"name":"settings","prevSize":32,"code":59683},"setIdx":2,"setId":1,"iconIdx":73},{"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,"grid":0,"tags":["type-boolean"]},"attrs":[{}],"properties":{"order":21,"id":4,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":2,"setId":1,"iconIdx":74},{"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,"grid":0,"tags":["type-datetime"]},"attrs":[{}],"properties":{"order":24,"id":3,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":2,"setId":1,"iconIdx":75},{"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,"grid":0,"tags":["json"]},"attrs":[{}],"properties":{"order":20,"id":14,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":2,"setId":1,"iconIdx":76},{"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,"grid":0,"tags":["type-number"]},"attrs":[{}],"properties":{"order":32,"id":2,"name":"type-Number","prevSize":32,"code":59686},"setIdx":2,"setId":1,"iconIdx":77},{"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,"grid":0,"tags":["type-string"]},"attrs":[{}],"properties":{"order":48,"id":1,"name":"type-String","prevSize":32,"code":59687},"setIdx":2,"setId":1,"iconIdx":78},{"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,"grid":0,"tags":["user"]},"attrs":[{}],"properties":{"order":33,"id":0,"name":"user","prevSize":32,"code":59688},"setIdx":2,"setId":1,"iconIdx":79}],"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,"classSelector":".icon","name":"icomoon"},"historySize":100,"gridSize":16}} \ No newline at end of file diff --git a/src/Squidex/app/theme/icomoon/style.css b/src/Squidex/app/theme/icomoon/style.css index e9239e193..a64d962ae 100644 --- a/src/Squidex/app/theme/icomoon/style.css +++ b/src/Squidex/app/theme/icomoon/style.css @@ -1,10 +1,10 @@ @font-face { font-family: 'icomoon'; - src: url('fonts/icomoon.eot?mo2rwz'); - src: url('fonts/icomoon.eot?mo2rwz#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?mo2rwz') format('truetype'), - url('fonts/icomoon.woff?mo2rwz') format('woff'), - url('fonts/icomoon.svg?mo2rwz#icomoon') format('svg'); + src: url('fonts/icomoon.eot?vexzhv'); + src: url('fonts/icomoon.eot?vexzhv#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?vexzhv') format('truetype'), + url('fonts/icomoon.woff?vexzhv') format('woff'), + url('fonts/icomoon.svg?vexzhv#icomoon') format('svg'); font-weight: normal; font-style: normal; } @@ -141,50 +141,11 @@ .icon-download:before { content: "\e93e"; } -.icon-hour-glass:before { - content: "\e954"; -} -.icon-spinner:before { - content: "\e953"; -} -.icon-clock:before { - content: "\e950"; -} -.icon-bin2:before { - content: "\e902"; -} -.icon-earth:before { - content: "\e9ca"; -} -.icon-elapsed:before { - content: "\e943"; -} -.icon-google:before { - content: "\e93b"; -} -.icon-lock:before { - content: "\e934"; +.icon-caret-bottom:before { + content: "\e96b"; } -.icon-microsoft:before { - content: "\e940"; -} -.icon-pause:before { - content: "\e92f"; -} -.icon-play:before { - content: "\e930"; -} -.icon-reset:before { - content: "\e92e"; -} -.icon-settings2:before { - content: "\e92d"; -} -.icon-timeout:before { - content: "\e944"; -} -.icon-unlocked:before { - content: "\e933"; +.icon-caret-top:before { + content: "\e96c"; } .icon-show:before { content: "\e964"; @@ -264,9 +225,6 @@ .icon-info:before { content: "\e93c"; } -.icon-control-Stars:before { - content: "\e93a"; -} .icon-control-Color:before { content: "\e94d"; } From 6e048bc802675153526e61fbe63825437f33c4f6 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 5 Dec 2018 19:52:24 +0100 Subject: [PATCH 29/33] Build fix. --- .../EventSourcing/Grains/EventConsumerGrainTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs index 03e9fb905..6c3ae202b 100644 --- a/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs +++ b/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs @@ -330,7 +330,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains { var ex = new InvalidOperationException(); - A.CallTo(() => formatter.Parse(eventData, true, null)) + A.CallTo(() => formatter.Parse(eventData, null)) .Throws(ex); var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData); From a1b24a54e96f9a92e88d881e7c0322b443fe2aac Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 6 Dec 2018 07:51:01 +0100 Subject: [PATCH 30/33] Migration for Rule events. --- src/Squidex/Config/Domain/StoreServices.cs | 3 ++ tools/Migrate_01/MigrationPath.cs | 8 ++++- tools/Migrate_01/Migrations/AddPatterns.cs | 1 + .../Migrations/ConvertRuleEventsJson.cs | 34 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index 4d89d01de..0eb9fe2f6 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -69,6 +69,9 @@ namespace Squidex.Config.Domain services.AddTransientAs() .As(); + services.AddTransientAs() + .As(); + services.AddTransientAs(c => new DeleteContentCollections(mongoContentDatabase)) .As(); diff --git a/tools/Migrate_01/MigrationPath.cs b/tools/Migrate_01/MigrationPath.cs index 4573d5e06..4cf8354a0 100644 --- a/tools/Migrate_01/MigrationPath.cs +++ b/tools/Migrate_01/MigrationPath.cs @@ -16,7 +16,7 @@ namespace Migrate_01 { public sealed class MigrationPath : IMigrationPath { - private const int CurrentVersion = 12; + private const int CurrentVersion = 13; private readonly IServiceProvider serviceProvider; public MigrationPath(IServiceProvider serviceProvider) @@ -78,6 +78,12 @@ namespace Migrate_01 yield return serviceProvider.GetRequiredService(); } + // Version 13: Json refactoring + if (version < 13) + { + yield return serviceProvider.GetRequiredService(); + } + // Version 01: Introduce app patterns. if (version < 1) { diff --git a/tools/Migrate_01/Migrations/AddPatterns.cs b/tools/Migrate_01/Migrations/AddPatterns.cs index 4426982c6..14dd415ee 100644 --- a/tools/Migrate_01/Migrations/AddPatterns.cs +++ b/tools/Migrate_01/Migrations/AddPatterns.cs @@ -24,6 +24,7 @@ namespace Migrate_01.Migrations public AddPatterns(InitialPatterns initialPatterns, IGrainFactory grainFactory) { this.initialPatterns = initialPatterns; + this.grainFactory = grainFactory; } diff --git a/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs b/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs new file mode 100644 index 000000000..a3aa1a52a --- /dev/null +++ b/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs @@ -0,0 +1,34 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Threading.Tasks; +using MongoDB.Bson; +using MongoDB.Driver; +using Squidex.Infrastructure.Migrations; + +namespace Migrate_01.Migrations +{ + public sealed class ConvertRuleEventsJson : IMigration + { + private readonly IMongoCollection collection; + + public ConvertRuleEventsJson(IMongoDatabase database) + { + collection = database.GetCollection("RuleEvents"); + } + + public async Task UpdateAsync() + { + foreach (var document in collection.Find(new BsonDocument()).ToEnumerable()) + { + document["Job"]["actionData"] = document["Job"]["actionData"].ToBsonDocument().ToJson(); + + await collection.ReplaceOneAsync(Builders.Filter.Eq("_id", document["_id"].ToString()), document); + } + } + } +} From 47856e41448ebbc8428961b2b8060a69e7c540d5 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 6 Dec 2018 07:57:14 +0100 Subject: [PATCH 31/33] Small code improvement. --- tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs b/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs index a3aa1a52a..b543acddf 100644 --- a/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs +++ b/tools/Migrate_01/Migrations/ConvertRuleEventsJson.cs @@ -27,7 +27,9 @@ namespace Migrate_01.Migrations { document["Job"]["actionData"] = document["Job"]["actionData"].ToBsonDocument().ToJson(); - await collection.ReplaceOneAsync(Builders.Filter.Eq("_id", document["_id"].ToString()), document); + var filter = Builders.Filter.Eq("_id", document["_id"].ToString()); + + await collection.ReplaceOneAsync(filter, document); } } } From 695657a6252e1bd44938548e6200cb198bdb9713 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 6 Dec 2018 16:31:32 +0100 Subject: [PATCH 32/33] Also add build number to docker dev tags. --- .drone.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index c49d6846a..a9e87d61b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -18,12 +18,15 @@ pipeline: image: docker commands: - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD - - docker build -t squidex/squidex:dev . + - docker build -t squidex/squidex:dev -t squidex/squidex:dev-$BUILD_NUMBER . - docker push squidex/squidex:dev + - docker push squidex/squidex:dev-$BUILD_NUMBER volumes: - /var/run/docker.sock:/var/run/docker.sock - /var/lib/docker:/var/lib/docker secrets: [ docker_username, docker_password ] + environment: + - BUILD_NUMBER=${DRONE_BUILD_NUMBER} when: event: push branch: [ master ] From 3ad74da83f8cd252b5452e85dc5138f849fd4f46 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 6 Dec 2018 20:29:11 +0100 Subject: [PATCH 33/33] Made LRUCAche generic. --- .../Caching/LRUCache.cs | 44 +++++++------------ .../Caching/LRUCacheItem.cs | 7 +-- .../Caching/LRUCacheTests.cs | 2 +- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/src/Squidex.Infrastructure/Caching/LRUCache.cs b/src/Squidex.Infrastructure/Caching/LRUCache.cs index 4632d2ab0..7132eb1d3 100644 --- a/src/Squidex.Infrastructure/Caching/LRUCache.cs +++ b/src/Squidex.Infrastructure/Caching/LRUCache.cs @@ -9,23 +9,19 @@ using System.Collections.Generic; namespace Squidex.Infrastructure.Caching { - public sealed class LRUCache + public sealed class LRUCache { - private readonly Dictionary> cacheMap = new Dictionary>(); - private readonly LinkedList cacheHistory = new LinkedList(); + private readonly Dictionary>> cacheMap = new Dictionary>>(); + private readonly LinkedList> cacheHistory = new LinkedList>(); private readonly int capacity; public LRUCache(int capacity) { - Guard.GreaterThan(capacity, 0, nameof(capacity)); - this.capacity = capacity; } - public bool Set(object key, object value) + public bool Set(TKey key, TValue value) { - Guard.NotNull(key, nameof(key)); - if (cacheMap.TryGetValue(key, out var node)) { node.Value.Value = value; @@ -37,28 +33,24 @@ namespace Squidex.Infrastructure.Caching return true; } - else + + if (cacheMap.Count >= capacity) { - if (cacheMap.Count >= capacity) - { - RemoveFirst(); - } + RemoveFirst(); + } - var cacheItem = new LRUCacheItem { Key = key, Value = value }; + var cacheItem = new LRUCacheItem { Key = key, Value = value }; - node = new LinkedListNode(cacheItem); + node = new LinkedListNode>(cacheItem); - cacheMap.Add(key, node); - cacheHistory.AddLast(node); + cacheMap.Add(key, node); + cacheHistory.AddLast(node); - return false; - } + return false; } - public bool Remove(object key) + public bool Remove(TKey key) { - Guard.NotNull(key, nameof(key)); - if (cacheMap.TryGetValue(key, out var node)) { cacheMap.Remove(key); @@ -70,10 +62,8 @@ namespace Squidex.Infrastructure.Caching return false; } - public bool TryGetValue(object key, out object value) + public bool TryGetValue(TKey key, out object value) { - Guard.NotNull(key, nameof(key)); - value = null; if (cacheMap.TryGetValue(key, out var node)) @@ -89,10 +79,8 @@ namespace Squidex.Infrastructure.Caching return false; } - public bool Contains(object key) + public bool Contains(TKey key) { - Guard.NotNull(key, nameof(key)); - return cacheMap.ContainsKey(key); } diff --git a/src/Squidex.Infrastructure/Caching/LRUCacheItem.cs b/src/Squidex.Infrastructure/Caching/LRUCacheItem.cs index ddf885afd..ff9cb3eef 100644 --- a/src/Squidex.Infrastructure/Caching/LRUCacheItem.cs +++ b/src/Squidex.Infrastructure/Caching/LRUCacheItem.cs @@ -9,9 +9,10 @@ namespace Squidex.Infrastructure.Caching { - internal class LRUCacheItem + internal class LRUCacheItem { - public object Key; - public object Value; + public TKey Key; + + public TValue Value; } } \ No newline at end of file diff --git a/tests/Squidex.Infrastructure.Tests/Caching/LRUCacheTests.cs b/tests/Squidex.Infrastructure.Tests/Caching/LRUCacheTests.cs index 4551fbe57..52e029193 100644 --- a/tests/Squidex.Infrastructure.Tests/Caching/LRUCacheTests.cs +++ b/tests/Squidex.Infrastructure.Tests/Caching/LRUCacheTests.cs @@ -11,7 +11,7 @@ namespace Squidex.Infrastructure.Caching { public class LRUCacheTests { - private readonly LRUCache sut = new LRUCache(10); + private readonly LRUCache sut = new LRUCache(10); private readonly string key = "Key"; [Fact]