From 88d3b43e15345b621372f77924c648a931de56a9 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 26 Apr 2019 10:01:52 +0200 Subject: [PATCH 01/20] Temp --- .../ValidateContent/IAssetInfo.cs | 2 + .../Assets/MongoAssetEntity.cs | 4 + .../Assets/MongoAssetRepository.cs | 42 ++++++- .../Apps/State/AppState.cs | 2 + .../Assets/AssetCommandMiddleware.cs | 75 ++++++++++-- .../Assets/AssetCreatedResult.cs | 21 ++-- .../Assets/AssetGrain.cs | 40 ++++--- .../Assets/AssetQueryService.cs | 25 +++- .../Assets/AssetSavedResult.cs | 5 +- .../Assets/Commands/CreateAsset.cs | 2 + .../Assets/Commands/UpdateAsset.cs | 2 + .../Assets/Repositories/IAssetRepository.cs | 6 +- .../Assets/State/AssetState.cs | 5 + .../Contents/State/ContentState.cs | 2 + .../Rules/State/RuleState.cs | 2 + .../Schemas/State/SchemaState.cs | 2 + .../Assets/AssetCreated.cs | 2 + .../Assets/AssetUpdated.cs | 2 + .../Assets/HasherStream.cs | 96 +++++++++++++++ .../Assets/MemoryAssetStore.cs | 10 +- .../Commands/EntityCreatedResult{T}.cs | 2 +- src/Squidex.Infrastructure/RandomHash.cs | 8 +- .../Assets/AssetContentController.cs | 42 ++++++- .../Assets/Models/AssetCreatedDto.cs | 14 ++- .../Api/Controllers/Assets/Models/AssetDto.cs | 6 + .../Assets/Models/AssetReplacedDto.cs | 6 + src/Squidex/Squidex.csproj | 2 +- .../features/administration/declarations.ts | 1 + .../event-consumers-page.component.ts | 2 +- .../services/event-consumers.service.ts | 14 +-- .../administration/services/users.service.ts | 44 +++---- .../state/event-consumers.state.spec.ts | 4 +- .../administration/state/users.forms.ts | 60 ++++++++++ .../administration/state/users.state.spec.ts | 11 +- .../administration/state/users.state.ts | 60 +--------- src/Squidex/app/framework/state.ts | 23 +++- .../components/assets-list.component.ts | 12 +- .../services/app-clients.service.spec.ts | 6 +- .../shared/services/app-clients.service.ts | 32 ++--- .../services/app-contributors.service.spec.ts | 3 +- .../services/app-contributors.service.ts | 31 ++--- .../services/app-languages.service.spec.ts | 6 +- .../shared/services/app-languages.service.ts | 22 ++-- .../services/app-patterns.service.spec.ts | 5 +- .../shared/services/app-patterns.service.ts | 18 ++- .../shared/services/app-roles.service.spec.ts | 6 +- .../app/shared/services/app-roles.service.ts | 22 +--- .../app/shared/services/apps.service.spec.ts | 3 +- .../app/shared/services/apps.service.ts | 15 +-- .../shared/services/assets.service.spec.ts | 32 +++-- .../app/shared/services/assets.service.ts | 67 ++++------- .../shared/services/backups.service.spec.ts | 7 +- .../app/shared/services/backups.service.ts | 14 +-- .../shared/services/comments.service.spec.ts | 9 +- .../app/shared/services/comments.service.ts | 15 +-- .../app/shared/services/contents.service.ts | 21 +--- .../app/shared/services/plans.service.spec.ts | 5 +- .../app/shared/services/plans.service.ts | 20 ++-- .../app/shared/services/rules.service.spec.ts | 32 +++-- .../app/shared/services/rules.service.ts | 40 ++----- .../shared/services/schemas.service.spec.ts | 11 +- .../app/shared/services/schemas.service.ts | 47 ++------ .../app/shared/services/schemas.types.ts | 18 ++- .../services/translations.service.spec.ts | 7 +- .../shared/services/translations.service.ts | 11 +- src/Squidex/app/shared/services/ui.service.ts | 6 +- .../app/shared/state/apps.state.spec.ts | 11 +- .../app/shared/state/assets.state.spec.ts | 8 +- .../app/shared/state/clients.state.spec.ts | 12 +- .../app/shared/state/comments.state.spec.ts | 19 +-- .../app/shared/state/comments.state.ts | 11 +- .../shared/state/contributors.state.spec.ts | 3 +- .../app/shared/state/languages.state.spec.ts | 3 +- .../app/shared/state/languages.state.ts | 22 ++-- .../app/shared/state/patterns.state.spec.ts | 11 +- .../app/shared/state/patterns.state.ts | 2 +- .../app/shared/state/plans.state.spec.ts | 4 +- src/Squidex/app/shared/state/plans.state.ts | 9 +- .../app/shared/state/roles.state.spec.ts | 6 +- .../app/shared/state/rules.state.spec.ts | 3 +- src/Squidex/app/shared/state/rules.state.ts | 7 +- .../ValidateContent/AssetsFieldTests.cs | 2 + .../Assets/AssetCommandMiddlewareTests.cs | 112 ++++++++++++++++-- .../Assets/AssetGrainTests.cs | 15 ++- .../Assets/AssetQueryServiceTests.cs | 15 ++- .../Contents/TestData/FakeAssetEntity.cs | 2 + .../Assets/HasherStreamTests.cs | 47 ++++++++ .../DispatchingTests.cs | 10 +- 88 files changed, 933 insertions(+), 590 deletions(-) create mode 100644 src/Squidex.Infrastructure/Assets/HasherStream.cs create mode 100644 src/Squidex/app/features/administration/state/users.forms.ts create mode 100644 tests/Squidex.Infrastructure.Tests/Assets/HasherStreamTests.cs diff --git a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IAssetInfo.cs b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IAssetInfo.cs index 9e7ff611d..9c8923bda 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IAssetInfo.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/IAssetInfo.cs @@ -23,6 +23,8 @@ namespace Squidex.Domain.Apps.Core.ValidateContent string FileName { get; } + string FileHash { get; } + string Slug { get; } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetEntity.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetEntity.cs index 8850ef500..2aa7a672c 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetEntity.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetEntity.cs @@ -38,6 +38,10 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets [BsonElement] public string FileName { get; set; } + [BsonIgnoreIfDefault] + [BsonElement] + public string FileHash { get; set; } + [BsonIgnoreIfDefault] [BsonElement] public string Slug { get; set; } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index e203ac95d..07b7eb57e 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -46,7 +46,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets .Ascending(x => x.Tags) .Descending(x => x.LastModified)), new CreateIndexModel( - Index.Ascending(x => x.Slug)) + Index + .Ascending(x => x.AppId) + .Ascending(x => x.IsDeleted) + .Ascending(x => x.FileHash)), + new CreateIndexModel( + Index + .Ascending(x => x.AppId) + .Ascending(x => x.Slug)) }, ct); } @@ -102,19 +109,41 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets } } - public async Task FindAssetAsync(string slug) + public async Task FindAssetBySlugAsync(Guid appId, string slug) { using (Profiler.TraceMethod()) { var assetEntity = - await Collection.Find(x => x.Slug == slug) + await Collection.Find(x => x.IndexedAppId == appId && x.Slug == slug) .FirstOrDefaultAsync(); + if (assetEntity?.IsDeleted == true) + { + return null; + } + return assetEntity; } } - public async Task FindAssetAsync(Guid id) + public async Task FindAssetByHashAsync(Guid appId, string hash) + { + using (Profiler.TraceMethod()) + { + var assetEntity = + await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.FileHash == hash) + .FirstOrDefaultAsync(); + + if (assetEntity?.IsDeleted == true) + { + return null; + } + + return assetEntity; + } + } + + public async Task FindAssetAsync(Guid id, bool allowDeleted = false) { using (Profiler.TraceMethod()) { @@ -122,6 +151,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets await Collection.Find(x => x.Id == id) .FirstOrDefaultAsync(); + if (assetEntity?.IsDeleted == true && !allowDeleted) + { + return null; + } + return assetEntity; } } diff --git a/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs b/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs index 569ad468e..a1176be44 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs @@ -14,6 +14,8 @@ using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.States; +#pragma warning disable IDE0060 // Remove unused parameter + namespace Squidex.Domain.Apps.Entities.Apps.State { [CollectionName("Apps")] diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs index c1b217806..dd15cdd28 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs @@ -7,9 +7,11 @@ using System; using System.Collections.Generic; +using System.Security.Cryptography; using System.Threading.Tasks; using Orleans; using Squidex.Domain.Apps.Entities.Assets.Commands; +using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Entities.Tags; using Squidex.Infrastructure; using Squidex.Infrastructure.Assets; @@ -20,21 +22,25 @@ namespace Squidex.Domain.Apps.Entities.Assets public sealed class AssetCommandMiddleware : GrainCommandMiddleware { private readonly IAssetStore assetStore; + private readonly AssetQueryService assetQueryService; private readonly IAssetThumbnailGenerator assetThumbnailGenerator; private readonly IEnumerable> tagGenerators; public AssetCommandMiddleware( IGrainFactory grainFactory, + AssetQueryService assetQueryService, IAssetStore assetStore, IAssetThumbnailGenerator assetThumbnailGenerator, IEnumerable> tagGenerators) : base(grainFactory) { Guard.NotNull(assetStore, nameof(assetStore)); + Guard.NotNull(assetQueryService, nameof(assetQueryService)); Guard.NotNull(assetThumbnailGenerator, nameof(assetThumbnailGenerator)); Guard.NotNull(tagGenerators, nameof(tagGenerators)); this.assetStore = assetStore; + this.assetQueryService = assetQueryService; this.assetThumbnailGenerator = assetThumbnailGenerator; this.tagGenerators = tagGenerators; @@ -53,21 +59,45 @@ namespace Squidex.Domain.Apps.Entities.Assets createAsset.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(createAsset.File.OpenRead()); - foreach (var tagGenerator in tagGenerators) - { - tagGenerator.GenerateTags(createAsset, createAsset.Tags); - } + createAsset.FileHash = await UploadAsync(context, createAsset.File); - var originalTags = new HashSet(createAsset.Tags); - - await assetStore.UploadAsync(context.ContextId.ToString(), createAsset.File.OpenRead()); try { - var result = (AssetSavedResult)await ExecuteCommandAsync(createAsset); - - context.Complete(new AssetCreatedResult(createAsset.AssetId, originalTags, result.Version)); + var existing = await assetQueryService.FindAssetByHashAsync(createAsset.AppId.Id, createAsset.FileHash); + + AssetCreatedResult result; + + if (IsDuplicate(createAsset, existing)) + { + result = new AssetCreatedResult( + existing.Id, + existing.Tags, + existing.Version, + existing.FileVersion, + existing.FileHash, + true); + } + else + { + foreach (var tagGenerator in tagGenerators) + { + tagGenerator.GenerateTags(createAsset, createAsset.Tags); + } + + var commandResult = (AssetSavedResult)await ExecuteCommandAsync(createAsset); + + result = new AssetCreatedResult( + createAsset.AssetId, + createAsset.Tags, + commandResult.Version, + commandResult.FileVersion, + commandResult.FileHash, + false); + + await assetStore.CopyAsync(context.ContextId.ToString(), createAsset.AssetId.ToString(), result.FileVersion, null); + } - await assetStore.CopyAsync(context.ContextId.ToString(), createAsset.AssetId.ToString(), result.FileVersion, null); + context.Complete(result); } finally { @@ -81,10 +111,10 @@ namespace Squidex.Domain.Apps.Entities.Assets { updateAsset.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(updateAsset.File.OpenRead()); - await assetStore.UploadAsync(context.ContextId.ToString(), updateAsset.File.OpenRead()); + updateAsset.FileHash = await UploadAsync(context, updateAsset.File); try { - var result = await ExecuteCommandAsync(updateAsset) as AssetSavedResult; + var result = (AssetSavedResult)await ExecuteCommandAsync(updateAsset); context.Complete(result); @@ -103,5 +133,24 @@ namespace Squidex.Domain.Apps.Entities.Assets break; } } + + private static bool IsDuplicate(CreateAsset createAsset, IAssetEntity asset) + { + return asset != null && asset.FileName == createAsset.File.FileName && asset.FileSize == createAsset.File.FileSize; + } + + private async Task UploadAsync(CommandContext context, AssetFile file) + { + string hash; + + using (var hashStream = new HasherStream(file.OpenRead(), HashAlgorithmName.SHA256)) + { + await assetStore.UploadAsync(context.ContextId.ToString(), hashStream); + + hash = hashStream.GetHashStringAndReset(); + } + + return hash; + } } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs index 8abb01c95..de8da5f23 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs @@ -11,18 +11,25 @@ using Squidex.Infrastructure.Commands; namespace Squidex.Domain.Apps.Entities.Assets { - public sealed class AssetCreatedResult : EntitySavedResult + public sealed class AssetCreatedResult : EntityCreatedResult { - public Guid Id { get; } - public HashSet Tags { get; } - public AssetCreatedResult(Guid id, HashSet tags, long version) - : base(version) - { - Id = id; + public long FileVersion { get; } + + public string FileHash { get; } + + public bool IsDuplicate { get; } + public AssetCreatedResult(Guid id, HashSet tags, long version, long fileVersion, string fileHash, bool isDuplicate) + : base(id, version) + { Tags = tags; + + FileVersion = fileVersion; + FileHash = fileHash; + + IsDuplicate = isDuplicate; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetGrain.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetGrain.cs index ec7b92db2..b16b18ae4 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetGrain.cs @@ -47,11 +47,11 @@ namespace Squidex.Domain.Apps.Entities.Assets { GuardAsset.CanCreate(c); - c.Tags = await NormalizeTagsAsync(c.AppId.Id, c.Tags); + var tagIds = await NormalizeTagsAsync(c.AppId.Id, c.Tags); - Create(c); + Create(c, tagIds); - return new AssetSavedResult(Version, Snapshot.FileVersion); + return new AssetSavedResult(Version, Snapshot.FileVersion, Snapshot.FileHash); }); case UpdateAsset updateRule: return UpdateAsync(updateRule, c => @@ -60,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.Assets Update(c); - return new AssetSavedResult(Version, Snapshot.FileVersion); + return new AssetSavedResult(Version, Snapshot.FileVersion, Snapshot.FileHash); }); case DeleteAsset deleteAsset: return UpdateAsync(deleteAsset, async c => @@ -76,12 +76,9 @@ namespace Squidex.Domain.Apps.Entities.Assets { GuardAsset.CanAnnotate(c, Snapshot.FileName, Snapshot.Slug); - if (c.Tags != null) - { - c.Tags = await NormalizeTagsAsync(Snapshot.AppId.Id, c.Tags); - } + var tagIds = await NormalizeTagsAsync(Snapshot.AppId.Id, c.Tags); - Annotate(c); + Annotate(c, tagIds); }); default: throw new NotSupportedException(); @@ -90,32 +87,37 @@ namespace Squidex.Domain.Apps.Entities.Assets private async Task> NormalizeTagsAsync(Guid appId, HashSet tags) { + if (tags == null) + { + return null; + } + var normalized = await tagService.NormalizeTagsAsync(appId, TagGroups.Assets, tags, Snapshot.Tags); return new HashSet(normalized.Values); } - public void Create(CreateAsset command) + public void Create(CreateAsset command, HashSet tagIds) { var @event = SimpleMapper.Map(command, new AssetCreated { + IsImage = command.ImageInfo != null, FileName = command.File.FileName, FileSize = command.File.FileSize, FileVersion = 0, MimeType = command.File.MimeType, PixelWidth = command.ImageInfo?.PixelWidth, PixelHeight = command.ImageInfo?.PixelHeight, - IsImage = command.ImageInfo != null, Slug = command.File.FileName.ToAssetSlug() }); + @event.Tags = tagIds; + RaiseEvent(@event); } public void Update(UpdateAsset command) { - VerifyNotDeleted(); - var @event = SimpleMapper.Map(command, new AssetUpdated { FileVersion = Snapshot.FileVersion + 1, @@ -129,14 +131,18 @@ namespace Squidex.Domain.Apps.Entities.Assets RaiseEvent(@event); } - public void Delete(DeleteAsset command) + public void Annotate(AnnotateAsset command, HashSet tagIds) { - RaiseEvent(SimpleMapper.Map(command, new AssetDeleted { DeletedSize = Snapshot.TotalSize })); + var @event = SimpleMapper.Map(command, new AssetAnnotated()); + + @event.Tags = tagIds; + + RaiseEvent(@event); } - public void Annotate(AnnotateAsset command) + public void Delete(DeleteAsset command) { - RaiseEvent(SimpleMapper.Map(command, new AssetAnnotated())); + RaiseEvent(SimpleMapper.Map(command, new AssetDeleted { DeletedSize = Snapshot.TotalSize })); } private void RaiseEvent(AppEvent @event) diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs index 0bd7a6975..5965d1030 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetQueryService.cs @@ -21,7 +21,7 @@ using Squidex.Infrastructure.Queries.OData; namespace Squidex.Domain.Apps.Entities.Assets { - public sealed class AssetQueryService : IAssetQueryService + public class AssetQueryService : IAssetQueryService { private readonly ITagService tagService; private readonly IAssetRepository assetRepository; @@ -38,21 +38,38 @@ namespace Squidex.Domain.Apps.Entities.Assets this.tagService = tagService; } - public async Task FindAssetAsync(QueryContext context, Guid id) + public virtual Task FindAssetAsync(QueryContext context, Guid id) { Guard.NotNull(context, nameof(context)); + return FindAssetAsync(context.App.Id, id); + } + + public virtual async Task FindAssetAsync(Guid appId, Guid id) + { var asset = await assetRepository.FindAssetAsync(id); if (asset != null) { - await DenormalizeTagsAsync(context.App.Id, Enumerable.Repeat(asset, 1)); + await DenormalizeTagsAsync(appId, Enumerable.Repeat(asset, 1)); + } + + return asset; + } + + public virtual async Task FindAssetByHashAsync(Guid appId, string hash) + { + var asset = await assetRepository.FindAssetByHashAsync(appId, hash); + + if (asset != null) + { + await DenormalizeTagsAsync(appId, Enumerable.Repeat(asset, 1)); } return asset; } - public async Task> QueryAsync(QueryContext context, Q query) + public virtual async Task> QueryAsync(QueryContext context, Q query) { Guard.NotNull(context, nameof(context)); Guard.NotNull(query, nameof(query)); diff --git a/src/Squidex.Domain.Apps.Entities/Assets/AssetSavedResult.cs b/src/Squidex.Domain.Apps.Entities/Assets/AssetSavedResult.cs index a07331e8f..a43e109cc 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/AssetSavedResult.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/AssetSavedResult.cs @@ -13,10 +13,13 @@ namespace Squidex.Domain.Apps.Entities.Assets { public long FileVersion { get; } - public AssetSavedResult(long version, long fileVersion) + public string FileHash { get; } + + public AssetSavedResult(long version, long fileVersion, string fileHash) : base(version) { FileVersion = fileVersion; + FileHash = fileHash; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs b/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs index 829cf0ce5..9c49e67bd 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs @@ -22,6 +22,8 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands public HashSet Tags { get; set; } + public string FileHash { get; set; } + public CreateAsset() { AssetId = Guid.NewGuid(); diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs b/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs index 1bb193419..1c998ac7a 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpdateAsset.cs @@ -14,5 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands public AssetFile File { get; set; } public ImageInfo ImageInfo { get; set; } + + public string FileHash { get; set; } } } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetRepository.cs b/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetRepository.cs index 939fc65ab..81481f99b 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetRepository.cs @@ -19,9 +19,11 @@ namespace Squidex.Domain.Apps.Entities.Assets.Repositories Task> QueryAsync(Guid appId, HashSet ids); - Task FindAssetAsync(string slug); + Task FindAssetAsync(Guid id, bool allowDeleted = false); - Task FindAssetAsync(Guid id); + Task FindAssetBySlugAsync(Guid appId, string slug); + + Task FindAssetByHashAsync(Guid appId, string hash); Task RemoveAsync(Guid appId); } diff --git a/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs b/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs index 2ea47f7ab..142b5075f 100644 --- a/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs +++ b/src/Squidex.Domain.Apps.Entities/Assets/State/AssetState.cs @@ -16,6 +16,8 @@ using Squidex.Infrastructure.Dispatching; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; +#pragma warning disable IDE0060 // Remove unused parameter + namespace Squidex.Domain.Apps.Entities.Assets.State { public class AssetState : DomainObjectState, IAssetEntity @@ -26,6 +28,9 @@ namespace Squidex.Domain.Apps.Entities.Assets.State [DataMember] public string FileName { get; set; } + [DataMember] + public string FileHash { get; set; } + [DataMember] public string MimeType { get; set; } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs b/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs index ca610a74c..1f2169431 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/State/ContentState.cs @@ -15,6 +15,8 @@ using Squidex.Infrastructure.Dispatching; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; +#pragma warning disable IDE0060 // Remove unused parameter + namespace Squidex.Domain.Apps.Entities.Contents.State { public class ContentState : DomainObjectState, IContentEntity diff --git a/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs b/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs index 48e354328..c6e1bd49d 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/State/RuleState.cs @@ -15,6 +15,8 @@ using Squidex.Infrastructure.Dispatching; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.States; +#pragma warning disable IDE0060 // Remove unused parameter + namespace Squidex.Domain.Apps.Entities.Rules.State { [CollectionName("Rules")] diff --git a/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs b/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs index 922da11a3..9bde80fd1 100644 --- a/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs +++ b/src/Squidex.Domain.Apps.Entities/Schemas/State/SchemaState.cs @@ -16,6 +16,8 @@ using Squidex.Infrastructure.Dispatching; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.States; +#pragma warning disable IDE0060 // Remove unused parameter + namespace Squidex.Domain.Apps.Entities.Schemas.State { [CollectionName("Schemas")] diff --git a/src/Squidex.Domain.Apps.Events/Assets/AssetCreated.cs b/src/Squidex.Domain.Apps.Events/Assets/AssetCreated.cs index 568c324e0..5200031cc 100644 --- a/src/Squidex.Domain.Apps.Events/Assets/AssetCreated.cs +++ b/src/Squidex.Domain.Apps.Events/Assets/AssetCreated.cs @@ -15,6 +15,8 @@ namespace Squidex.Domain.Apps.Events.Assets { public string FileName { get; set; } + public string FileHash { get; set; } + public string MimeType { get; set; } public string Slug { get; set; } diff --git a/src/Squidex.Domain.Apps.Events/Assets/AssetUpdated.cs b/src/Squidex.Domain.Apps.Events/Assets/AssetUpdated.cs index aca1cb89b..b26c49397 100644 --- a/src/Squidex.Domain.Apps.Events/Assets/AssetUpdated.cs +++ b/src/Squidex.Domain.Apps.Events/Assets/AssetUpdated.cs @@ -14,6 +14,8 @@ namespace Squidex.Domain.Apps.Events.Assets { public string MimeType { get; set; } + public string FileHash { get; set; } + public long FileSize { get; set; } public long FileVersion { get; set; } diff --git a/src/Squidex.Infrastructure/Assets/HasherStream.cs b/src/Squidex.Infrastructure/Assets/HasherStream.cs new file mode 100644 index 000000000..ea11e8682 --- /dev/null +++ b/src/Squidex.Infrastructure/Assets/HasherStream.cs @@ -0,0 +1,96 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace Squidex.Infrastructure.Assets +{ + public sealed class HasherStream : Stream + { + private readonly Stream inner; + private readonly IncrementalHash hasher; + + public override bool CanRead + { + get { return inner.CanRead; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return false; } + } + + public override long Length + { + get { return inner.Length; } + } + + public override long Position + { + get { return inner.Position; } + set { throw new NotSupportedException(); } + } + + public HasherStream(Stream inner, HashAlgorithmName hashAlgorithmName) + { + Guard.NotNull(inner, nameof(inner)); + + this.inner = inner; + + hasher = IncrementalHash.CreateHash(hashAlgorithmName); + } + + public override int Read(byte[] buffer, int offset, int count) + { + var read = inner.Read(buffer, offset, count); + + if (read > 0) + { + hasher.AppendData(buffer, offset, read); + } + + return read; + } + + public byte[] GetHashAndReset() + { + return hasher.GetHashAndReset(); + } + + public string GetHashStringAndReset() + { + return Convert.ToBase64String(GetHashAndReset()); + } + + public override void Flush() + { + throw new NotSupportedException(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/Squidex.Infrastructure/Assets/MemoryAssetStore.cs b/src/Squidex.Infrastructure/Assets/MemoryAssetStore.cs index c5c2cbce3..10fa7fe84 100644 --- a/src/Squidex.Infrastructure/Assets/MemoryAssetStore.cs +++ b/src/Squidex.Infrastructure/Assets/MemoryAssetStore.cs @@ -13,7 +13,7 @@ using Squidex.Infrastructure.Tasks; namespace Squidex.Infrastructure.Assets { - public sealed class MemoryAssetStore : IAssetStore + public class MemoryAssetStore : IAssetStore { private readonly ConcurrentDictionary streams = new ConcurrentDictionary(); private readonly AsyncLock readerLock = new AsyncLock(); @@ -24,7 +24,7 @@ namespace Squidex.Infrastructure.Assets return null; } - public async Task CopyAsync(string sourceFileName, string targetFileName, CancellationToken ct = default) + public virtual async Task CopyAsync(string sourceFileName, string targetFileName, CancellationToken ct = default) { Guard.NotNullOrEmpty(sourceFileName, nameof(sourceFileName)); Guard.NotNullOrEmpty(targetFileName, nameof(targetFileName)); @@ -40,7 +40,7 @@ namespace Squidex.Infrastructure.Assets } } - public async Task DownloadAsync(string fileName, Stream stream, CancellationToken ct = default) + public virtual async Task DownloadAsync(string fileName, Stream stream, CancellationToken ct = default) { Guard.NotNullOrEmpty(fileName, nameof(fileName)); @@ -62,7 +62,7 @@ namespace Squidex.Infrastructure.Assets } } - public async Task UploadAsync(string fileName, Stream stream, bool overwrite = false, CancellationToken ct = default) + public virtual async Task UploadAsync(string fileName, Stream stream, bool overwrite = false, CancellationToken ct = default) { Guard.NotNullOrEmpty(fileName, nameof(fileName)); @@ -99,7 +99,7 @@ namespace Squidex.Infrastructure.Assets } } - public Task DeleteAsync(string fileName) + public virtual Task DeleteAsync(string fileName) { Guard.NotNullOrEmpty(fileName, nameof(fileName)); diff --git a/src/Squidex.Infrastructure/Commands/EntityCreatedResult{T}.cs b/src/Squidex.Infrastructure/Commands/EntityCreatedResult{T}.cs index 324c8c6a4..2ab583d59 100644 --- a/src/Squidex.Infrastructure/Commands/EntityCreatedResult{T}.cs +++ b/src/Squidex.Infrastructure/Commands/EntityCreatedResult{T}.cs @@ -7,7 +7,7 @@ namespace Squidex.Infrastructure.Commands { - public sealed class EntityCreatedResult : EntitySavedResult + public class EntityCreatedResult : EntitySavedResult { public T IdOrValue { get; } diff --git a/src/Squidex.Infrastructure/RandomHash.cs b/src/Squidex.Infrastructure/RandomHash.cs index 9b395e23a..e64115342 100644 --- a/src/Squidex.Infrastructure/RandomHash.cs +++ b/src/Squidex.Infrastructure/RandomHash.cs @@ -19,11 +19,15 @@ namespace Squidex.Infrastructure } public static string Sha256Base64(this string value) + { + return Sha256Base64(Encoding.UTF8.GetBytes(value)); + } + + public static string Sha256Base64(this byte[] bytes) { using (var sha = SHA256.Create()) { - var bytesValue = Encoding.UTF8.GetBytes(value); - var bytesHash = sha.ComputeHash(bytesValue); + var bytesHash = sha.ComputeHash(bytes); var result = Convert.ToBase64String(bytesHash); diff --git a/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs b/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs index c9ff22e9b..056250ff0 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs @@ -62,7 +62,38 @@ namespace Squidex.Areas.Api.Controllers.Assets [Route("assets/{id}/{*more}")] [ProducesResponseType(typeof(FileResult), 200)] [ApiCosts(0.5)] - public async Task GetAssetContent(string id, string more, + public async Task GetAssetContent(Guid id, string more, + [FromQuery] long version = EtagVersion.Any, + [FromQuery] int? width = null, + [FromQuery] int? height = null, + [FromQuery] int? quality = null, + [FromQuery] string mode = null) + { + var entity = await assetRepository.FindAssetAsync(id); + + return DeliverAsset(entity, version, width, height, quality, mode); + } + + /// + /// Get the asset content. + /// + /// The name of the app. + /// The id or slug of the asset. + /// Optional suffix that can be used to seo-optimize the link to the image Has not effect. + /// The optional version of the asset. + /// The target width of the asset, if it is an image. + /// The target height of the asset, if it is an image. + /// Optional image quality, it is is an jpeg image. + /// The resize mode when the width and height is defined. + /// + /// 200 => Asset found and content or (resized) image returned. + /// 404 => Asset or app not found. + /// + [HttpGet] + [Route("assets/{app}/{idOrSlug}/{*more}")] + [ProducesResponseType(typeof(FileResult), 200)] + [ApiCosts(0.5)] + public async Task GetAssetContent(string app, string idOrSlug, string more, [FromQuery] long version = EtagVersion.Any, [FromQuery] int? width = null, [FromQuery] int? height = null, @@ -71,15 +102,20 @@ namespace Squidex.Areas.Api.Controllers.Assets { IAssetEntity entity; - if (Guid.TryParse(id, out var guid)) + if (Guid.TryParse(idOrSlug, out var guid)) { entity = await assetRepository.FindAssetAsync(guid); } else { - entity = await assetRepository.FindAssetAsync(id); + entity = await assetRepository.FindAssetByHashAsync(App.Id, idOrSlug); } + return DeliverAsset(entity, version, width, height, quality, mode); + } + + private IActionResult DeliverAsset(IAssetEntity entity, long version, int? width, int? height, int? quality, string mode) + { if (entity == null || entity.FileVersion < version || width == 0 || height == 0 || quality == 0) { return NotFound(); diff --git a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetCreatedDto.cs b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetCreatedDto.cs index 0b1807312..da76057c0 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetCreatedDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetCreatedDto.cs @@ -76,6 +76,11 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models /// public int? PixelHeight { get; set; } + /// + /// Indicates if the asset has been already uploaded. + /// + public bool IsDuplicate { get; set; } + /// /// The version of the asset. /// @@ -83,22 +88,21 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models public static AssetCreatedDto FromCommand(CreateAsset command, AssetCreatedResult result) { - var response = new AssetCreatedDto + return new AssetCreatedDto { - Id = command.AssetId, + Id = result.IdOrValue, FileName = command.File.FileName, FileSize = command.File.FileSize, FileType = command.File.FileName.FileType(), - FileVersion = result.Version, + FileVersion = result.FileVersion, MimeType = command.File.MimeType, IsImage = command.ImageInfo != null, + IsDuplicate = result.IsDuplicate, PixelWidth = command.ImageInfo?.PixelWidth, PixelHeight = command.ImageInfo?.PixelHeight, Tags = result.Tags, Version = result.Version }; - - return response; } } } diff --git a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs index e13b76993..1053302be 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs @@ -29,6 +29,12 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models [Required] public string FileName { get; set; } + /// + /// The file hash. + /// + [Required] + public string FileHash { get; set; } + /// /// The slug. /// diff --git a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetReplacedDto.cs b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetReplacedDto.cs index cb6fcb801..e65faf494 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetReplacedDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetReplacedDto.cs @@ -19,6 +19,12 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models [Required] public string MimeType { get; set; } + /// + /// The file hash. + /// + [Required] + public string FileHash { get; set; } + /// /// The size of the file in bytes. /// diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj index 79983c5dc..a6db529aa 100644 --- a/src/Squidex/Squidex.csproj +++ b/src/Squidex/Squidex.csproj @@ -153,6 +153,6 @@ - $(NoWarn);CS1591;1591;1573;1572;NU1605 + $(NoWarn);CS1591;1591;1573;1572;NU1605;IDE0060 \ No newline at end of file diff --git a/src/Squidex/app/features/administration/declarations.ts b/src/Squidex/app/features/administration/declarations.ts index 09279fe2c..2a3b2198d 100644 --- a/src/Squidex/app/features/administration/declarations.ts +++ b/src/Squidex/app/features/administration/declarations.ts @@ -19,4 +19,5 @@ export * from './services/event-consumers.service'; export * from './services/users.service'; export * from './state/event-consumers.state'; +export * from './state/users.forms'; export * from './state/users.state'; \ No newline at end of file diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts index a8d339148..30b65c600 100644 --- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts +++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts @@ -21,7 +21,7 @@ import { EventConsumersState } from './../../state/event-consumers.state'; }) export class EventConsumersPageComponent extends ResourceOwner implements OnInit { public eventConsumerErrorDialog = new DialogModel(); - public eventConsumerError = ''; + public eventConsumerError?: string; constructor( public readonly eventConsumersState: EventConsumersState diff --git a/src/Squidex/app/features/administration/services/event-consumers.service.ts b/src/Squidex/app/features/administration/services/event-consumers.service.ts index 74de8309a..169850008 100644 --- a/src/Squidex/app/features/administration/services/event-consumers.service.ts +++ b/src/Squidex/app/features/administration/services/event-consumers.service.ts @@ -16,20 +16,16 @@ import { pretifyError } from '@app/shared'; -export class EventConsumerDto extends Model { +export class EventConsumerDto extends Model { constructor( public readonly name: string, - public readonly isStopped: boolean, - public readonly isResetting: boolean, - public readonly error: string, - public readonly position: string + public readonly isStopped?: boolean, + public readonly isResetting?: boolean, + public readonly error?: string, + public readonly position?: string ) { super(); } - - public with(value: Partial): EventConsumerDto { - return this.clone(value); - } } @Injectable() diff --git a/src/Squidex/app/features/administration/services/users.service.ts b/src/Squidex/app/features/administration/services/users.service.ts index 32152110b..524f4b5d4 100644 --- a/src/Squidex/app/features/administration/services/users.service.ts +++ b/src/Squidex/app/features/administration/services/users.service.ts @@ -13,25 +13,19 @@ import { map } from 'rxjs/operators'; import { ApiUrlConfig, Model, - pretifyError + pretifyError, + ResultSet } from '@app/shared'; -export class UsersDto extends Model { - constructor( - public readonly total: number, - public readonly items: UserDto[] - ) { - super(); - } -} +export class UsersDto extends ResultSet {} -export class UserDto extends Model { +export class UserDto extends Model { constructor( public readonly id: string, public readonly email: string, public readonly displayName: string, - public readonly permissions: string[], - public readonly isLocked: boolean + public readonly permissions: string[] = [], + public readonly isLocked?: boolean ) { super(); } @@ -41,24 +35,18 @@ export class UserDto extends Model { } } -export class CreateUserDto { - constructor( - public readonly email: string, - public readonly displayName: string, - public readonly permissions: string[], - public readonly password: string - ) { - } +export interface CreateUserDto { + readonly email: string; + readonly displayName: string; + readonly permissions: string[]; + readonly password: string; } -export class UpdateUserDto { - constructor( - public readonly email: string, - public readonly displayName: string, - public readonly permissions: string[], - public readonly password?: string - ) { - } +export interface UpdateUserDto { + readonly email: string; + readonly displayName: string; + readonly permissions: string[]; + readonly password?: string; } @Injectable() diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts index 980ba1e92..c288609e7 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts @@ -16,8 +16,8 @@ import { EventConsumersState } from './event-consumers.state'; describe('EventConsumersState', () => { const oldConsumers = [ - new EventConsumerDto('name1', false, false, 'error', '1'), - new EventConsumerDto('name2', true, true, 'error', '2') + new EventConsumerDto('name1', false), + new EventConsumerDto('name2', true) ]; let dialogs: IMock; diff --git a/src/Squidex/app/features/administration/state/users.forms.ts b/src/Squidex/app/features/administration/state/users.forms.ts new file mode 100644 index 000000000..e998d449f --- /dev/null +++ b/src/Squidex/app/features/administration/state/users.forms.ts @@ -0,0 +1,60 @@ +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; + +import { Form, ValidatorsEx } from '@app/shared'; + +import { UserDto } from './../services/users.service'; + +export class UserForm extends Form { + constructor( + formBuilder: FormBuilder + ) { + super(formBuilder.group({ + email: ['', + [ + Validators.email, + Validators.required, + Validators.maxLength(100) + ] + ], + displayName: ['', + [ + Validators.required, + Validators.maxLength(100) + ] + ], + password: ['', + [ + Validators.nullValidator + ] + ], + passwordConfirm: ['', + [ + ValidatorsEx.match('password', 'Passwords must be the same.') + ] + ], + permissions: [''] + })); + } + + public load(user?: UserDto) { + if (user) { + this.form.controls['password'].setValidators(null); + + super.load({ ...user, permissions: user.permissions.join('\n') }); + } else { + this.form.controls['password'].setValidators(Validators.required); + + super.load(undefined); + } + } + + public submit() { + const result = super.submit(); + + if (result) { + result['permissions'] = result['permissions'].split('\n').filter((x: any) => !!x); + } + + return result; + } +} \ No newline at end of file diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts index 31adfec4d..53bd4f3e3 100644 --- a/src/Squidex/app/features/administration/state/users.state.spec.ts +++ b/src/Squidex/app/features/administration/state/users.state.spec.ts @@ -13,8 +13,6 @@ import { AuthService, DialogService } from '@app/shared'; import { UsersState } from './users.state'; import { - CreateUserDto, - UpdateUserDto, UserDto, UsersDto, UsersService @@ -168,7 +166,7 @@ describe('UsersState', () => { }); it('should update user properties when updated', () => { - const request = new UpdateUserDto('new@mail.com', 'New', ['Permission1']); + const request = { email: 'new@mail.com', displayName: 'New', permissions: ['Permission1'] }; usersService.setup(x => x.putUser('id1', request)) .returns(() => of({})); @@ -178,13 +176,14 @@ describe('UsersState', () => { const user_1 = usersState.snapshot.users.at(0); - expect(user_1.user.email).toEqual('new@mail.com'); - expect(user_1.user.displayName).toEqual('New'); + expect(user_1.user.email).toEqual(request.email); + expect(user_1.user.displayName).toEqual(request.permissions); + expect(user_1.user.permissions).toEqual(request.permissions); expect(user_1).toBe(usersState.snapshot.selectedUser!); }); it('should add user to snapshot when created', () => { - const request = new CreateUserDto(newUser.email, newUser.displayName, newUser.permissions, 'password'); + const request = { ...newUser, password: 'password' }; usersService.setup(x => x.postUser(request)) .returns(() => of(newUser)); diff --git a/src/Squidex/app/features/administration/state/users.state.ts b/src/Squidex/app/features/administration/state/users.state.ts index bb34bc5f8..c5d82e70e 100644 --- a/src/Squidex/app/features/administration/state/users.state.ts +++ b/src/Squidex/app/features/administration/state/users.state.ts @@ -6,7 +6,6 @@ */ import { Injectable } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Observable, of } from 'rxjs'; import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators'; @@ -15,12 +14,10 @@ import '@app/framework/utils/rxjs-extensions'; import { AuthService, DialogService, - Form, ImmutableArray, notify, Pager, - State, - ValidatorsEx + State } from '@app/shared'; import { @@ -30,61 +27,6 @@ import { UsersService } from './../services/users.service'; -export class UserForm extends Form { - constructor( - formBuilder: FormBuilder - ) { - super(formBuilder.group({ - email: ['', - [ - Validators.email, - Validators.required, - Validators.maxLength(100) - ] - ], - displayName: ['', - [ - Validators.required, - Validators.maxLength(100) - ] - ], - password: ['', - [ - Validators.nullValidator - ] - ], - passwordConfirm: ['', - [ - ValidatorsEx.match('password', 'Passwords must be the same.') - ] - ], - permissions: [''] - })); - } - - public load(user?: UserDto) { - if (user) { - this.form.controls['password'].setValidators(null); - - super.load({ ...user, permissions: user.permissions.join('\n') }); - } else { - this.form.controls['password'].setValidators(Validators.required); - - super.load(undefined); - } - } - - public submit() { - const result = super.submit(); - - if (result) { - result['permissions'] = result['permissions'].split('\n').filter((x: any) => !!x); - } - - return result; - } -} - interface SnapshotUser { // The user. user: UserDto; diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index f93c0b7c3..ae0ddfcb1 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -97,9 +97,17 @@ export class Form { } } -export class Model { - protected clone(update: ((v: any) => object) | object, validOnly = false): any { - let values: object; +export function createModel(c: { new(): T; }, values: Partial): T { + return Object.assign(new c(), values); +} + +export class Model { + public with(value: Partial, validOnly = false): T { + return this.clone(value, validOnly); + } + + protected clone(update: ((v: any) => T) | Partial, validOnly = false): T { + let values: Partial; if (Types.isFunction(update)) { values = update(this); } else { @@ -126,6 +134,15 @@ export class Model { } } +export class ResultSet extends Model> { + constructor( + public readonly total: number, + public readonly items: T[] + ) { + super(); + } +} + export class State { private readonly state: BehaviorSubject>; private readonly initialState: Readonly; diff --git a/src/Squidex/app/shared/components/assets-list.component.ts b/src/Squidex/app/shared/components/assets-list.component.ts index dd2339e48..674656236 100644 --- a/src/Squidex/app/shared/components/assets-list.component.ts +++ b/src/Squidex/app/shared/components/assets-list.component.ts @@ -11,6 +11,7 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AssetDto, AssetsState, + DialogService, ImmutableArray } from '@app/shared/internal'; @@ -38,10 +39,19 @@ export class AssetsListComponent { @Output() public select = new EventEmitter(); + constructor( + private readonly dialogs: DialogService + ) { + } + public add(file: File, asset: AssetDto) { this.newFiles = this.newFiles.remove(file); - this.state.add(asset); + if (asset.isDuplicate) { + this.dialogs.notifyError('The same asset has already been uploaded.'); + } else { + this.state.add(asset); + } } public search() { diff --git a/src/Squidex/app/shared/services/app-clients.service.spec.ts b/src/Squidex/app/shared/services/app-clients.service.spec.ts index 1137473a9..c1179f696 100644 --- a/src/Squidex/app/shared/services/app-clients.service.spec.ts +++ b/src/Squidex/app/shared/services/app-clients.service.spec.ts @@ -15,8 +15,6 @@ import { AppClientDto, AppClientsDto, AppClientsService, - CreateAppClientDto, - UpdateAppClientDto, Version } from './../'; @@ -83,7 +81,7 @@ describe('AppClientsService', () => { it('should make post request to create client', inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { - const dto = new CreateAppClientDto('client1'); + const dto = { id: 'client1' }; let client: AppClientDto; @@ -104,7 +102,7 @@ describe('AppClientsService', () => { it('should make put request to rename client', inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { - const dto = new UpdateAppClientDto('Client 1 New'); + const dto = { name: 'New Name' }; appClientsService.putClient('my-app', 'client1', dto, version).subscribe(); diff --git a/src/Squidex/app/shared/services/app-clients.service.ts b/src/Squidex/app/shared/services/app-clients.service.ts index f7dfd3590..36507531d 100644 --- a/src/Squidex/app/shared/services/app-clients.service.ts +++ b/src/Squidex/app/shared/services/app-clients.service.ts @@ -20,7 +20,7 @@ import { Versioned } from '@app/framework'; -export class AppClientsDto extends Model { +export class AppClientsDto extends Model { constructor( public readonly clients: AppClientDto[], public readonly version: Version @@ -29,42 +29,32 @@ export class AppClientsDto extends Model { } } -export class AppClientDto extends Model { +export class AppClientDto extends Model { constructor( public readonly id: string, public readonly name: string, public readonly secret: string, - public readonly role: string + public readonly role = 'Developer' ) { super(); } - - public with(value: Partial): AppClientDto { - return this.clone(value); - } } -export class CreateAppClientDto { +export class AccessTokenDto { constructor( - public readonly id: string + public readonly accessToken: string, + public readonly tokenType: string ) { } } -export class UpdateAppClientDto { - constructor( - public readonly name?: string, - public readonly role?: string - ) { - } +export interface CreateAppClientDto { + readonly id: string; } -export class AccessTokenDto { - constructor( - public readonly accessToken: string, - public readonly tokenType: string - ) { - } +export interface UpdateAppClientDto { + readonly name?: string; + readonly role?: string; } @Injectable() diff --git a/src/Squidex/app/shared/services/app-contributors.service.spec.ts b/src/Squidex/app/shared/services/app-contributors.service.spec.ts index fda899774..084240dfe 100644 --- a/src/Squidex/app/shared/services/app-contributors.service.spec.ts +++ b/src/Squidex/app/shared/services/app-contributors.service.spec.ts @@ -14,7 +14,6 @@ import { AppContributorDto, AppContributorsDto, AppContributorsService, - AssignContributorDto, ContributorAssignedDto, Version } from './../'; @@ -81,7 +80,7 @@ describe('AppContributorsService', () => { it('should make post request to assign contributor', inject([AppContributorsService, HttpTestingController], (appContributorsService: AppContributorsService, httpMock: HttpTestingController) => { - const dto = new AssignContributorDto('123', 'Owner'); + const dto = { contributorId: '123', role: 'Owner' }; let contributorAssignedDto: ContributorAssignedDto; diff --git a/src/Squidex/app/shared/services/app-contributors.service.ts b/src/Squidex/app/shared/services/app-contributors.service.ts index c67966b79..ddf3edd6c 100644 --- a/src/Squidex/app/shared/services/app-contributors.service.ts +++ b/src/Squidex/app/shared/services/app-contributors.service.ts @@ -20,7 +20,7 @@ import { Versioned } from '@app/framework'; -export class AppContributorsDto extends Model { +export class AppContributorsDto extends Model { constructor( public readonly contributors: AppContributorDto[], public readonly maxContributors: number, @@ -30,31 +30,24 @@ export class AppContributorsDto extends Model { } } -export class AssignContributorDto extends Model { +export class AppContributorDto extends Model { constructor( public readonly contributorId: string, - public readonly role: string, - public readonly invite = false + public readonly role: string ) { super(); } } -export class AppContributorDto extends Model { - constructor( - public readonly contributorId: string, - public readonly role: string - ) { - super(); - } +export interface ContributorAssignedDto { + readonly contributorId: string; + readonly isCreated?: boolean; } -export class ContributorAssignedDto { - constructor( - public readonly contributorId: string, - public readonly isCreated: boolean - ) { - } +export interface AssignContributorDto { + readonly contributorId: string; + readonly role: string; + readonly invite?: boolean; } @Injectable() @@ -93,9 +86,7 @@ export class AppContributorsService { map(response => { const body: any = response.payload.body; - const result = new ContributorAssignedDto(body.contributorId, body.isCreated); - - return new Versioned(response.version, result); + return new Versioned(response.version, body); }), tap(() => { this.analytics.trackEvent('Contributor', 'Configured', appName); diff --git a/src/Squidex/app/shared/services/app-languages.service.spec.ts b/src/Squidex/app/shared/services/app-languages.service.spec.ts index b17284dc7..5fd7d0cab 100644 --- a/src/Squidex/app/shared/services/app-languages.service.spec.ts +++ b/src/Squidex/app/shared/services/app-languages.service.spec.ts @@ -9,13 +9,11 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/ import { inject, TestBed } from '@angular/core/testing'; import { - AddAppLanguageDto, AnalyticsService, ApiUrlConfig, AppLanguageDto, AppLanguagesDto, AppLanguagesService, - UpdateAppLanguageDto, Version } from './../'; @@ -83,7 +81,7 @@ describe('AppLanguagesService', () => { it('should make post request to add language', inject([AppLanguagesService, HttpTestingController], (appLanguagesService: AppLanguagesService, httpMock: HttpTestingController) => { - const dto = new AddAppLanguageDto('de'); + const dto = { language: 'de' }; let language: AppLanguageDto; @@ -104,7 +102,7 @@ describe('AppLanguagesService', () => { it('should make put request to make master language', inject([AppLanguagesService, HttpTestingController], (appLanguagesService: AppLanguagesService, httpMock: HttpTestingController) => { - const dto = new UpdateAppLanguageDto(true, true, []); + const dto = { isMaster: true }; appLanguagesService.putLanguage('my-app', 'de', dto, version).subscribe(); diff --git a/src/Squidex/app/shared/services/app-languages.service.ts b/src/Squidex/app/shared/services/app-languages.service.ts index 7f68eaa6a..8cd281d7c 100644 --- a/src/Squidex/app/shared/services/app-languages.service.ts +++ b/src/Squidex/app/shared/services/app-languages.service.ts @@ -20,7 +20,7 @@ import { Versioned } from '@app/framework'; -export class AppLanguagesDto extends Model { +export class AppLanguagesDto extends Model { constructor( public readonly languages: AppLanguageDto[], public readonly version: Version @@ -29,7 +29,7 @@ export class AppLanguagesDto extends Model { } } -export class AppLanguageDto extends Model { +export class AppLanguageDto extends Model { constructor( public readonly iso2Code: string, public readonly englishName: string, @@ -41,20 +41,14 @@ export class AppLanguageDto extends Model { } } -export class AddAppLanguageDto { - constructor( - public readonly language: string - ) { - } +export interface AddAppLanguageDto { + readonly language: string; } -export class UpdateAppLanguageDto { - constructor( - public readonly isMaster: boolean, - public readonly isOptional: boolean, - public readonly fallback: string[] - ) { - } +export interface UpdateAppLanguageDto { + readonly isMaster?: boolean; + readonly isOptional?: boolean; + readonly fallback?: string[]; } @Injectable() diff --git a/src/Squidex/app/shared/services/app-patterns.service.spec.ts b/src/Squidex/app/shared/services/app-patterns.service.spec.ts index b5a31ab66..43b1b8e95 100644 --- a/src/Squidex/app/shared/services/app-patterns.service.spec.ts +++ b/src/Squidex/app/shared/services/app-patterns.service.spec.ts @@ -14,7 +14,6 @@ import { AppPatternDto, AppPatternsDto, AppPatternsService, - EditAppPatternDto, Version } from './../'; @@ -80,7 +79,7 @@ describe('AppPatternsService', () => { it('should make post request to add pattern', inject([AppPatternsService, HttpTestingController], (patternService: AppPatternsService, httpMock: HttpTestingController) => { - const dto = new EditAppPatternDto('Number', '[0-9]', 'Message1'); + const dto = { name: 'Number', pattern: '[0-9]' }; let pattern: AppPatternDto; @@ -106,7 +105,7 @@ describe('AppPatternsService', () => { it('should make put request to update pattern', inject([AppPatternsService, HttpTestingController], (patternService: AppPatternsService, httpMock: HttpTestingController) => { - const dto = new EditAppPatternDto('Number', '[0-9]', 'Message1'); + const dto = { name: 'Number', pattern: '[0-9]' }; patternService.putPattern('my-app', '1', dto, version).subscribe(); diff --git a/src/Squidex/app/shared/services/app-patterns.service.ts b/src/Squidex/app/shared/services/app-patterns.service.ts index 71cbe6fb6..d2ce8969c 100644 --- a/src/Squidex/app/shared/services/app-patterns.service.ts +++ b/src/Squidex/app/shared/services/app-patterns.service.ts @@ -20,7 +20,7 @@ import { Versioned } from '@app/framework'; -export class AppPatternsDto extends Model { +export class AppPatternsDto extends Model { constructor( public readonly patterns: AppPatternDto[], public readonly version: Version @@ -29,27 +29,23 @@ export class AppPatternsDto extends Model { } } -export class AppPatternDto extends Model { +export class AppPatternDto extends Model { constructor( public readonly id: string, public readonly name: string, public readonly pattern: string, - public readonly message: string + public readonly message?: string ) { super(); } } -export class EditAppPatternDto { - constructor( - public readonly name: string, - public readonly pattern: string, - public readonly message: string - ) { - } +export interface EditAppPatternDto { + readonly name: string; + readonly pattern: string; + readonly message?: string; } - @Injectable() export class AppPatternsService { constructor( diff --git a/src/Squidex/app/shared/services/app-roles.service.spec.ts b/src/Squidex/app/shared/services/app-roles.service.spec.ts index 1138a3b43..35979140b 100644 --- a/src/Squidex/app/shared/services/app-roles.service.spec.ts +++ b/src/Squidex/app/shared/services/app-roles.service.spec.ts @@ -14,8 +14,6 @@ import { AppRoleDto, AppRolesDto, AppRolesService, - CreateAppRoleDto, - UpdateAppRoleDto, Version } from './../'; @@ -101,7 +99,7 @@ describe('AppRolesService', () => { it('should make post request to add role', inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { - const dto = new CreateAppRoleDto('Role3'); + const dto = { name: 'Role3' }; let role: AppRoleDto; @@ -122,7 +120,7 @@ describe('AppRolesService', () => { it('should make put request to update role', inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { - const dto = new UpdateAppRoleDto(['P4', 'P5']); + const dto = { permissions: ['P4', 'P5'] }; roleService.putRole('my-app', 'role1', dto, version).subscribe(); diff --git a/src/Squidex/app/shared/services/app-roles.service.ts b/src/Squidex/app/shared/services/app-roles.service.ts index bf1878572..008fd47fd 100644 --- a/src/Squidex/app/shared/services/app-roles.service.ts +++ b/src/Squidex/app/shared/services/app-roles.service.ts @@ -20,7 +20,7 @@ import { Versioned } from '@app/framework'; -export class AppRolesDto extends Model { +export class AppRolesDto extends Model { constructor( public readonly roles: AppRoleDto[], public readonly version: Version @@ -29,7 +29,7 @@ export class AppRolesDto extends Model { } } -export class AppRoleDto extends Model { +export class AppRoleDto extends Model { constructor( public readonly name: string, public readonly numClients: number, @@ -38,24 +38,14 @@ export class AppRoleDto extends Model { ) { super(); } - - public with(value: Partial): AppRoleDto { - return this.clone(value); - } } -export class CreateAppRoleDto { - constructor( - public readonly name: string - ) { - } +export interface CreateAppRoleDto { + readonly name: string; } -export class UpdateAppRoleDto { - constructor( - public readonly permissions: string[] - ) { - } +export interface UpdateAppRoleDto { + readonly permissions: string[]; } @Injectable() diff --git a/src/Squidex/app/shared/services/apps.service.spec.ts b/src/Squidex/app/shared/services/apps.service.spec.ts index 7fc4a43c1..361d80a2d 100644 --- a/src/Squidex/app/shared/services/apps.service.spec.ts +++ b/src/Squidex/app/shared/services/apps.service.spec.ts @@ -13,7 +13,6 @@ import { ApiUrlConfig, AppDto, AppsService, - CreateAppDto, DateTime, Permission } from './../'; @@ -83,7 +82,7 @@ describe('AppsService', () => { it('should make post request to create app', inject([AppsService, HttpTestingController], (appsService: AppsService, httpMock: HttpTestingController) => { - const dto = new CreateAppDto('new-app'); + const dto = { name: 'new-app' }; let app: AppDto; diff --git a/src/Squidex/app/shared/services/apps.service.ts b/src/Squidex/app/shared/services/apps.service.ts index 8f7644298..5771c9775 100644 --- a/src/Squidex/app/shared/services/apps.service.ts +++ b/src/Squidex/app/shared/services/apps.service.ts @@ -20,26 +20,23 @@ import { pretifyError } from '@app/framework'; -export class AppDto extends Model { +export class AppDto extends Model { constructor( public readonly id: string, public readonly name: string, public readonly permissions: Permission[], public readonly created: DateTime, public readonly lastModified: DateTime, - public readonly planName: string, - public readonly planUpgrade: string + public readonly planName?: string, + public readonly planUpgrade?: string ) { super(); } } -export class CreateAppDto { - constructor( - public readonly name: string, - public readonly template?: string - ) { - } +export interface CreateAppDto { + readonly name: string; + readonly template?: string; } @Injectable() diff --git a/src/Squidex/app/shared/services/assets.service.spec.ts b/src/Squidex/app/shared/services/assets.service.spec.ts index fb0c87344..16709cc4f 100644 --- a/src/Squidex/app/shared/services/assets.service.spec.ts +++ b/src/Squidex/app/shared/services/assets.service.spec.ts @@ -10,7 +10,6 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, - AnnotateAssetDto, ApiUrlConfig, AssetDto, AssetReplacedDto, @@ -31,9 +30,9 @@ describe('AssetDto', () => { const newVersion = new Version('2'); it('should update tag property and user info when annnoting', () => { - const update = new AnnotateAssetDto('NewName.png', null, null); + const update = { fileName: 'New-Name.png' }; - const asset_1 = new AssetDto('1', creator, creator, creation, creation, 'Name.png', 'png', 1, 1, 'image/png', false, 1, 1, 'name.png', [], 'url', version); + const asset_1 = new AssetDto('1', creator, creator, creation, creation, 'Name.png', 'Hash', 'png', 1, 1, 'image/png', false, false, 1, 1, 'name.png', [], 'url', version); const asset_2 = asset_1.annnotate(update, modifier, newVersion, modified); expect(asset_2.fileName).toEqual('NewName.png'); @@ -45,11 +44,12 @@ describe('AssetDto', () => { }); it('should update file properties when uploading', () => { - const update = new AssetReplacedDto(2, 2, 'image/jpeg', true, 2, 2); + const update = new AssetReplacedDto('Hash New', 2, 2, 'image/jpeg', true, 2, 2); - const asset_1 = new AssetDto('1', creator, creator, creation, creation, 'Name.png', 'png', 1, 1, 'image/png', false, 1, 1, 'name.png', [], 'url', version); + const asset_1 = new AssetDto('1', creator, creator, creation, creation, 'Name.png', 'Hash', 'png', 1, 1, 'image/png', false, false, 1, 1, 'name.png', [], 'url', version); const asset_2 = asset_1.update(update, modifier, newVersion, modified); + expect(asset_2.fileHash).toEqual('Hash New'); expect(asset_2.fileSize).toEqual(2); expect(asset_2.fileVersion).toEqual(2); expect(asset_2.mimeType).toEqual('image/jpeg'); @@ -133,6 +133,7 @@ describe('AssetsService', () => { lastModified: '2017-12-12T10:10', lastModifiedBy: 'LastModifiedBy1', fileName: 'My Asset1.png', + fileHash: 'My Hash1', fileType: 'png', fileSize: 1024, fileVersion: 2000, @@ -151,6 +152,7 @@ describe('AssetsService', () => { lastModified: '2017-10-12T10:10', lastModifiedBy: 'LastModifiedBy2', fileName: 'My Asset2.png', + fileHash: 'My Hash1', fileType: 'png', fileSize: 1024, fileVersion: 2000, @@ -172,10 +174,12 @@ describe('AssetsService', () => { DateTime.parseISO_UTC('2016-12-12T10:10'), DateTime.parseISO_UTC('2017-12-12T10:10'), 'My Asset1.png', + 'My Hash1', 'png', 1024, 2000, 'image/png', + false, true, 1024, 2048, @@ -187,10 +191,12 @@ describe('AssetsService', () => { DateTime.parseISO_UTC('2016-10-12T10:10'), DateTime.parseISO_UTC('2017-10-12T10:10'), 'My Asset2.png', + 'My Hash1', 'png', 1024, 2000, 'image/png', + false, true, 1024, 2048, @@ -222,6 +228,7 @@ describe('AssetsService', () => { lastModified: '2017-12-12T10:10', lastModifiedBy: 'LastModifiedBy1', fileName: 'My Asset1.png', + fileHash: 'My Hash1', fileType: 'png', fileSize: 1024, fileVersion: 2000, @@ -243,10 +250,12 @@ describe('AssetsService', () => { DateTime.parseISO_UTC('2016-12-12T10:10'), DateTime.parseISO_UTC('2017-12-12T10:10'), 'My Asset1.png', + 'My Hash1', 'png', 1024, 2000, 'image/png', + false, true, 1024, 2048, @@ -312,10 +321,12 @@ describe('AssetsService', () => { req.flush({ id: 'id1', fileName: 'My Asset1.png', + fileHash: 'My Hash1', fileType: 'png', fileSize: 1024, fileVersion: 2, mimeType: 'image/png', + isDuplicate: true, isImage: true, pixelWidth: 1024, pixelHeight: 2048, @@ -335,10 +346,12 @@ describe('AssetsService', () => { now, now, 'My Asset1.png', + 'My Hash1', 'png', 1024, 2, 'image/png', true, + true, 1024, 2048, 'my-asset1.png', @@ -385,8 +398,9 @@ describe('AssetsService', () => { expect(req.request.headers.get('If-Match')).toEqual(version.value); req.flush({ + fileHash: 'Hash New', fileSize: 1024, - fileVersion: 2, + fileVersion: 12, mimeType: 'image/png', isImage: true, pixelWidth: 1024, @@ -395,7 +409,9 @@ describe('AssetsService', () => { expect(asset!).toEqual( new AssetReplacedDto( - 1024, 2, + 'Hash New', + 1024, + 12, 'image/png', true, 1024, @@ -428,7 +444,7 @@ describe('AssetsService', () => { it('should make put request to annotate asset', inject([AssetsService, HttpTestingController], (assetsService: AssetsService, httpMock: HttpTestingController) => { - const dto = new AnnotateAssetDto('My Asset.pdf', 'my-asset.pdf', ['tag1', 'tag2']); + const dto = { fileName: 'New-Name.png' }; assetsService.putAsset('my-app', '123', dto, version).subscribe(); diff --git a/src/Squidex/app/shared/services/assets.service.ts b/src/Squidex/app/shared/services/assets.service.ts index 7fa7d0cb3..eb8b5d3ff 100644 --- a/src/Squidex/app/shared/services/assets.service.ts +++ b/src/Squidex/app/shared/services/assets.service.ts @@ -18,21 +18,15 @@ import { HTTP, Model, pretifyError, + ResultSet, Types, Version, Versioned } from '@app/framework'; -export class AssetsDto extends Model { - constructor( - public readonly total: number, - public readonly items: AssetDto[] - ) { - super(); - } -} +export class AssetsDto extends ResultSet { } -export class AssetDto extends Model { +export class AssetDto extends Model { public get canPreview() { return this.isImage || (this.mimeType === 'image/svg+xml' && this.fileSize < 100 * 1024); } @@ -44,10 +38,12 @@ export class AssetDto extends Model { public readonly created: DateTime, public readonly lastModified: DateTime, public readonly fileName: string, + public readonly fileHash: string, public readonly fileType: string, public readonly fileSize: number, public readonly fileVersion: number, public readonly mimeType: string, + public readonly isDuplicate: boolean, public readonly isImage: boolean, public readonly pixelWidth: number | null, public readonly pixelHeight: number | null, @@ -59,12 +55,8 @@ export class AssetDto extends Model { super(); } - public with(value: Partial, validOnly = false): AssetDto { - return this.clone(value, validOnly); - } - public update(update: AssetReplacedDto, user: string, version: Version, now?: DateTime): AssetDto { - return this.with({ + return this.clone({ ...update, lastModified: now || DateTime.now(), lastModifiedBy: user, @@ -73,7 +65,7 @@ export class AssetDto extends Model { } public annnotate(update: AnnotateAssetDto, user: string, version: Version, now?: DateTime): AssetDto { - return this.with({ + return this.clone({ ...update, lastModified: now || DateTime.now(), lastModifiedBy: user, @@ -82,25 +74,20 @@ export class AssetDto extends Model { } } -export class AnnotateAssetDto { - constructor( - public readonly fileName: string | null, - public readonly slug: string | null, - public readonly tags: string[] | null - ) { - } +export interface AnnotateAssetDto { + readonly fileName?: string; + readonly slug?: string; + readonly tags?: string[]; } -export class AssetReplacedDto { - constructor( - public readonly fileSize: number, - public readonly fileVersion: number, - public readonly mimeType: string, - public readonly isImage: boolean, - public readonly pixelWidth: number | null, - public readonly pixelHeight: number | null - ) { - } +export interface AssetReplacedDto { + readonly fileHash: string; + readonly fileSize: number; + readonly fileVersion: number; + readonly mimeType: string; + readonly isImage: boolean; + readonly pixelWidth?: number | null; + readonly pixelHeight?: number | null; } @Injectable() @@ -169,10 +156,12 @@ export class AssetsService { DateTime.parseISO_UTC(item.created), DateTime.parseISO_UTC(item.lastModified), item.fileName, + item.fileHash, item.fileType, item.fileSize, item.fileVersion, item.mimeType, + false, item.isImage, item.pixelWidth, item.pixelHeight, @@ -212,10 +201,12 @@ export class AssetsService { now, now, response.fileName, + response.fileHash, response.fileType, response.fileSize, response.fileVersion, response.mimeType, + response.isDuplicate, response.isImage, response.pixelWidth, response.pixelHeight, @@ -260,10 +251,12 @@ export class AssetsService { DateTime.parseISO_UTC(body.created), DateTime.parseISO_UTC(body.lastModified), body.fileName, + body.fileHash, body.fileType, body.fileSize, body.fileVersion, body.mimeType, + false, body.isImage, body.pixelWidth, body.pixelHeight, @@ -292,15 +285,7 @@ export class AssetsService { } else if (Types.is(event, HttpResponse)) { const response: any = event.body; - const replaced = new AssetReplacedDto( - response.fileSize, - response.fileVersion, - response.mimeType, - response.isImage, - response.pixelWidth, - response.pixelHeight); - - return new Versioned(new Version(event.headers.get('etag')!), replaced); + return new Versioned(new Version(event.headers.get('etag')!), response); } else { throw 'Invalid'; } diff --git a/src/Squidex/app/shared/services/backups.service.spec.ts b/src/Squidex/app/shared/services/backups.service.spec.ts index c88b0f161..3f2c971a2 100644 --- a/src/Squidex/app/shared/services/backups.service.spec.ts +++ b/src/Squidex/app/shared/services/backups.service.spec.ts @@ -14,8 +14,7 @@ import { BackupDto, BackupsService, DateTime, - RestoreDto, - StartRestoreDto + RestoreDto } from './../'; describe('BackupsService', () => { @@ -170,7 +169,9 @@ describe('BackupsService', () => { it('should make post request to start restore', inject([BackupsService, HttpTestingController], (backupsService: BackupsService, httpMock: HttpTestingController) => { - backupsService.postRestore(new StartRestoreDto('http://url')).subscribe(); + const dto = { url: 'http://url' }; + + backupsService.postRestore(dto).subscribe(); const req = httpMock.expectOne('http://service/p/api/apps/restore'); diff --git a/src/Squidex/app/shared/services/backups.service.ts b/src/Squidex/app/shared/services/backups.service.ts index 198db6775..4a9f0dbea 100644 --- a/src/Squidex/app/shared/services/backups.service.ts +++ b/src/Squidex/app/shared/services/backups.service.ts @@ -19,7 +19,7 @@ import { Types } from '@app/framework'; -export class BackupDto extends Model { +export class BackupDto extends Model { constructor( public readonly id: string, public readonly started: DateTime, @@ -32,7 +32,7 @@ export class BackupDto extends Model { } } -export class RestoreDto { +export class RestoreDto extends Model { constructor( public readonly url: string, public readonly started: DateTime, @@ -40,15 +40,13 @@ export class RestoreDto { public readonly status: string, public readonly log: string[] ) { + super(); } } -export class StartRestoreDto { - constructor( - public readonly url: string, - public readonly newAppName?: string - ) { - } +export interface StartRestoreDto { + readonly url: string; + readonly newAppName?: string; } @Injectable() diff --git a/src/Squidex/app/shared/services/comments.service.spec.ts b/src/Squidex/app/shared/services/comments.service.spec.ts index 9e5b7290b..03be1dcc6 100644 --- a/src/Squidex/app/shared/services/comments.service.spec.ts +++ b/src/Squidex/app/shared/services/comments.service.spec.ts @@ -14,7 +14,6 @@ import { CommentsDto, CommentsService, DateTime, - UpsertCommentDto, Version } from './../'; @@ -84,9 +83,11 @@ describe('CommentsService', () => { it('should make post request to create comment', inject([CommentsService, HttpTestingController], (commentsService: CommentsService, httpMock: HttpTestingController) => { + const dto = { text: 'text1' }; + let comment: CommentDto; - commentsService.postComment('my-app', 'my-comments', new UpsertCommentDto('text1')).subscribe(result => { + commentsService.postComment('my-app', 'my-comments', dto).subscribe(result => { comment = result; }); @@ -108,7 +109,9 @@ describe('CommentsService', () => { it('should make put request to replace comment content', inject([CommentsService, HttpTestingController], (commentsService: CommentsService, httpMock: HttpTestingController) => { - commentsService.putComment('my-app', 'my-comments', '123', new UpsertCommentDto('text1')).subscribe(); + const dto = { text: 'text1' }; + + commentsService.putComment('my-app', 'my-comments', '123', dto).subscribe(); const req = httpMock.expectOne('http://service/p/api/apps/my-app/comments/my-comments/123'); diff --git a/src/Squidex/app/shared/services/comments.service.ts b/src/Squidex/app/shared/services/comments.service.ts index dc2dc762c..b170ccfd0 100644 --- a/src/Squidex/app/shared/services/comments.service.ts +++ b/src/Squidex/app/shared/services/comments.service.ts @@ -18,7 +18,7 @@ import { Version } from '@app/framework'; -export class CommentsDto extends Model { +export class CommentsDto extends Model { constructor( public readonly createdComments: CommentDto[], public readonly updatedComments: CommentDto[], @@ -29,7 +29,7 @@ export class CommentsDto extends Model { } } -export class CommentDto extends Model { +export class CommentDto extends Model { constructor( public readonly id: string, public readonly time: DateTime, @@ -38,17 +38,10 @@ export class CommentDto extends Model { ) { super(); } - - public with(value: Partial): CommentDto { - return this.clone(value); - } } -export class UpsertCommentDto { - constructor( - public readonly text: string - ) { - } +export interface UpsertCommentDto { + readonly text: string; } @Injectable() diff --git a/src/Squidex/app/shared/services/contents.service.ts b/src/Squidex/app/shared/services/contents.service.ts index 7fa8358fc..6888dc646 100644 --- a/src/Squidex/app/shared/services/contents.service.ts +++ b/src/Squidex/app/shared/services/contents.service.ts @@ -17,25 +17,12 @@ import { HTTP, Model, pretifyError, + ResultSet, Version, Versioned } from '@app/framework'; -export class ContentsDto extends Model { - constructor( - public readonly total: number, - public readonly items: ContentDto[] - ) { - - super(); - } - - public with(value: Partial): ContentsDto { - return this.clone(value); - }} - - -export class ScheduleDto extends Model { +export class ScheduleDto extends Model { constructor( public readonly status: string, public readonly scheduledBy: string, @@ -45,7 +32,9 @@ export class ScheduleDto extends Model { } } -export class ContentDto extends Model { +export class ContentsDto extends ResultSet { } + +export class ContentDto extends Model { constructor( public readonly id: string, public readonly status: string, diff --git a/src/Squidex/app/shared/services/plans.service.spec.ts b/src/Squidex/app/shared/services/plans.service.spec.ts index d3139bc1b..35396170d 100644 --- a/src/Squidex/app/shared/services/plans.service.spec.ts +++ b/src/Squidex/app/shared/services/plans.service.spec.ts @@ -11,7 +11,6 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, ApiUrlConfig, - ChangePlanDto, PlanChangedDto, PlanDto, PlansDto, @@ -101,7 +100,7 @@ describe('PlansService', () => { it('should make put request to change plan', inject([PlansService, HttpTestingController], (plansService: PlansService, httpMock: HttpTestingController) => { - const dto = new ChangePlanDto('enterprise'); + const dto = { planId: 'enterprise' }; let planChanged: PlanChangedDto; @@ -116,6 +115,6 @@ describe('PlansService', () => { expect(req.request.method).toEqual('PUT'); expect(req.request.headers.get('If-Match')).toBe(version.value); - expect(planChanged!).toEqual(new PlanChangedDto('my-url')); + expect(planChanged!).toEqual({ redirectUri: 'http://url' }); })); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/services/plans.service.ts b/src/Squidex/app/shared/services/plans.service.ts index 9ab81561f..5298380ee 100644 --- a/src/Squidex/app/shared/services/plans.service.ts +++ b/src/Squidex/app/shared/services/plans.service.ts @@ -20,7 +20,7 @@ import { Versioned } from '@app/framework'; -export class PlansDto extends Model { +export class PlansDto extends Model { constructor( public readonly currentPlanId: string, public readonly planOwner: string, @@ -32,7 +32,7 @@ export class PlansDto extends Model { } } -export class PlanDto extends Model { +export class PlanDto extends Model { constructor( public readonly id: string, public readonly name: string, @@ -47,18 +47,12 @@ export class PlanDto extends Model { } } -export class PlanChangedDto { - constructor( - public readonly redirectUri: string - ) { - } +export interface PlanChangedDto { + readonly redirectUri?: string; } -export class ChangePlanDto { - constructor( - public readonly planId: string - ) { - } +export interface ChangePlanDto { + readonly planId: string; } @Injectable() @@ -106,7 +100,7 @@ export class PlansService { map(response => { const body = response.payload.body; - return new Versioned(response.version, new PlanChangedDto(body.redirectUri)); + return new Versioned(response.version, body); }), tap(() => { this.analytics.trackEvent('Plan', 'Changed', appName); diff --git a/src/Squidex/app/shared/services/rules.service.spec.ts b/src/Squidex/app/shared/services/rules.service.spec.ts index 7005eb894..5a46294ff 100644 --- a/src/Squidex/app/shared/services/rules.service.spec.ts +++ b/src/Squidex/app/shared/services/rules.service.spec.ts @@ -12,7 +12,6 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, ApiUrlConfig, - CreateRuleDto, DateTime, RuleDto, RuleElementDto, @@ -20,7 +19,6 @@ import { RuleEventDto, RuleEventsDto, RulesService, - UpdateRuleDto, Version } from './../'; @@ -168,15 +166,18 @@ describe('RulesService', () => { it('should make post request to create rule', inject([RulesService, HttpTestingController], (rulesService: RulesService, httpMock: HttpTestingController) => { - const dto = new CreateRuleDto({ - param1: 1, - param2: 2, - triggerType: 'ContentChanged' - }, { - param3: 3, - param4: 4, - actionType: 'Webhook' - }); + const dto = { + trigger: { + param1: 1, + param2: 2, + triggerType: 'ContentChanged' + }, + action: { + param3: 3, + param4: 4, + actionType: 'Webhook' + } + }; let rule: RuleDto; @@ -216,7 +217,14 @@ describe('RulesService', () => { it('should make put request to update rule', inject([RulesService, HttpTestingController], (rulesService: RulesService, httpMock: HttpTestingController) => { - const dto = new UpdateRuleDto({ param1: 1 }, { param2: 2 }); + const dto = { + trigger: { + param1: 1 + }, + action: { + param3: 2 + } + }; rulesService.putRule('my-app', '123', dto, version).subscribe(); diff --git a/src/Squidex/app/shared/services/rules.service.ts b/src/Squidex/app/shared/services/rules.service.ts index 9ca980f73..11b5f6e5a 100644 --- a/src/Squidex/app/shared/services/rules.service.ts +++ b/src/Squidex/app/shared/services/rules.service.ts @@ -17,6 +17,7 @@ import { HTTP, Model, pretifyError, + ResultSet, Version, Versioned } from '@app/framework'; @@ -72,7 +73,7 @@ export class RuleElementPropertyDto { } } -export class RuleDto extends Model { +export class RuleDto extends Model { constructor( public readonly id: string, public readonly createdBy: string, @@ -88,22 +89,11 @@ export class RuleDto extends Model { ) { super(); } - - public with(value: Partial): RuleDto { - return this.clone(value); - } } -export class RuleEventsDto extends Model { - constructor( - public readonly total: number, - public readonly items: RuleEventDto[] - ) { - super(); - } -} +export class RuleEventsDto extends ResultSet { } -export class RuleEventDto extends Model { +export class RuleEventDto extends Model { constructor( public readonly id: string, public readonly created: DateTime, @@ -117,26 +107,16 @@ export class RuleEventDto extends Model { ) { super(); } - - public with(value: Partial): RuleEventDto { - return this.clone(value); - } } -export class CreateRuleDto { - constructor( - public readonly trigger: any, - public readonly action: any - ) { - } +export interface CreateRuleDto { + readonly trigger: any; + readonly action: any; } -export class UpdateRuleDto { - constructor( - public readonly trigger: any, - public readonly action: any - ) { - } +export interface UpdateRuleDto { + readonly trigger?: any; + readonly action?: any; } @Injectable() diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index f354699e7..d6ea001bd 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -22,9 +22,6 @@ import { SchemaDto, SchemaPropertiesDto, SchemasService, - UpdateFieldDto, - UpdateSchemaCategoryDto, - UpdateSchemaDto, Version } from './../'; @@ -358,7 +355,7 @@ describe('SchemasService', () => { it('should make put request to update schema', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new UpdateSchemaDto('label', 'hints'); + const dto = { label: 'label1' }; schemasService.putSchema('my-app', 'my-schema', dto, version).subscribe(); @@ -388,7 +385,7 @@ describe('SchemasService', () => { it('should make put request to update category', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new UpdateSchemaCategoryDto(); + const dto = {}; schemasService.putCategory('my-app', 'my-schema', dto, version).subscribe(); @@ -486,7 +483,7 @@ describe('SchemasService', () => { it('should make put request to update field', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new UpdateFieldDto(createProperties('Number')); + const dto = { properties: createProperties('Number') }; schemasService.putField('my-app', 'my-schema', 1, dto, undefined, version).subscribe(); @@ -501,7 +498,7 @@ describe('SchemasService', () => { it('should make put request to update nested field', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new UpdateFieldDto(createProperties('Number')); + const dto = { properties: createProperties('Number') }; schemasService.putField('my-app', 'my-schema', 1, dto, 13, version).subscribe(); diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index 2457dc456..e9248d2eb 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -24,7 +24,7 @@ import { import { createProperties, FieldPropertiesDto } from './schemas.types'; -export class SchemaDto extends Model { +export class SchemaDto extends Model { public get displayName() { return StringHelper.firstNonEmpty(this.properties.label, this.name); } @@ -44,10 +44,6 @@ export class SchemaDto extends Model { ) { super(); } - - public with(value: Partial): SchemaDto { - return this.clone(value); - } } export class SchemaDetailsDto extends SchemaDto { @@ -88,13 +84,9 @@ export class SchemaDetailsDto extends SchemaDto { this.listFieldsEditable = fields.filter(x => x.isInlineEditable); } } - - public with(value: Partial): SchemaDetailsDto { - return this.clone(value); - } } -export class FieldDto extends Model { +export class FieldDto extends Model { public get isInlineEditable(): boolean { return !this.isDisabled && this.properties['inlineEditable'] === true; } @@ -117,10 +109,6 @@ export class FieldDto extends Model { ) { super(); } - - public with(value: Partial): FieldDto { - return this.clone(value); - } } export class RootFieldDto extends FieldDto { @@ -149,10 +137,6 @@ export class RootFieldDto extends FieldDto { ) { super(fieldId, name, properties, isLocked, isHidden, isDisabled); } - - public with(value: Partial): RootFieldDto { - return this.clone(value); - } } export class NestedFieldDto extends FieldDto { @@ -164,10 +148,6 @@ export class NestedFieldDto extends FieldDto { ) { super(fieldId, name, properties, isLocked, isHidden, isDisabled); } - - public with(value: Partial): NestedFieldDto { - return this.clone(value); - } } export class SchemaPropertiesDto { @@ -197,26 +177,17 @@ export class CreateSchemaDto { } } -export class UpdateSchemaCategoryDto { - constructor( - public readonly name?: string - ) { - } +export interface UpdateSchemaCategoryDto { + readonly name?: string; } -export class UpdateFieldDto { - constructor( - public readonly properties: FieldPropertiesDto - ) { - } +export interface UpdateFieldDto { + readonly properties: FieldPropertiesDto; } -export class UpdateSchemaDto { - constructor( - public readonly label?: string, - public readonly hints?: string - ) { - } +export interface UpdateSchemaDto { + readonly label?: string; + readonly hints?: string; } @Injectable() diff --git a/src/Squidex/app/shared/services/schemas.types.ts b/src/Squidex/app/shared/services/schemas.types.ts index ba94c6567..d2238838f 100644 --- a/src/Squidex/app/shared/services/schemas.types.ts +++ b/src/Squidex/app/shared/services/schemas.types.ts @@ -5,7 +5,19 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -export const fieldTypes = [ +export type FieldType = + 'Array' | + 'Assets' | + 'Boolean' | + 'DateTime' | + 'Json' | + 'Geolocation' | + 'Number' | + 'References' | + 'String' | + 'Tags'; + +export const fieldTypes: { type: FieldType, description: string }[] = [ { type: 'String', description: 'Titles, names, paragraphs.' @@ -41,7 +53,7 @@ export const fieldTypes = [ export const fieldInvariant = 'iv'; -export function createProperties(fieldType: string, values: Object | null = null): FieldPropertiesDto { +export function createProperties(fieldType: FieldType, values: Object | null = null): FieldPropertiesDto { let properties: FieldPropertiesDto; switch (fieldType) { @@ -109,7 +121,7 @@ export interface FieldPropertiesVisitor { } export abstract class FieldPropertiesDto { - public abstract fieldType: string; + public abstract fieldType: FieldType; public readonly editorUrl?: string; public readonly label?: string; diff --git a/src/Squidex/app/shared/services/translations.service.spec.ts b/src/Squidex/app/shared/services/translations.service.spec.ts index ac4beed2e..864fab019 100644 --- a/src/Squidex/app/shared/services/translations.service.spec.ts +++ b/src/Squidex/app/shared/services/translations.service.spec.ts @@ -10,7 +10,6 @@ import { inject, TestBed } from '@angular/core/testing'; import { ApiUrlConfig, - TranslateDto, TranslationDto, TranslationsService } from './../'; @@ -35,11 +34,11 @@ describe('TranslationsService', () => { it('should make post request to translate text', inject([TranslationsService, HttpTestingController], (translationsService: TranslationsService, httpMock: HttpTestingController) => { - let translation: TranslationDto; + const dto = { text: 'Hello', sourceLanguage: 'en', targetLanguage: 'de' }; - const request = new TranslateDto('Hello', 'en', 'de'); + let translation: TranslationDto; - translationsService.translate('my-app', request).subscribe(result => { + translationsService.translate('my-app', dto).subscribe(result => { translation = result; }); diff --git a/src/Squidex/app/shared/services/translations.service.ts b/src/Squidex/app/shared/services/translations.service.ts index 618ace20b..b6dd270de 100644 --- a/src/Squidex/app/shared/services/translations.service.ts +++ b/src/Squidex/app/shared/services/translations.service.ts @@ -20,13 +20,10 @@ export class TranslationDto { } } -export class TranslateDto { - constructor( - public readonly text: string, - public readonly sourceLanguage: string, - public readonly targetLanguage: string - ) { - } +export interface TranslateDto { + readonly text: string; + readonly sourceLanguage: string; + readonly targetLanguage: string; } @Injectable() diff --git a/src/Squidex/app/shared/services/ui.service.ts b/src/Squidex/app/shared/services/ui.service.ts index 91ce220ec..97115ccff 100644 --- a/src/Squidex/app/shared/services/ui.service.ts +++ b/src/Squidex/app/shared/services/ui.service.ts @@ -13,10 +13,10 @@ import { catchError } from 'rxjs/operators'; import { ApiUrlConfig } from '@app/framework'; export interface UISettingsDto { - mapType: string; - mapKey?: string; + readonly mapType: string; + readonly mapKey?: string; - canCreateApps: boolean; + readonly canCreateApps: boolean; } @Injectable() diff --git a/src/Squidex/app/shared/state/apps.state.spec.ts b/src/Squidex/app/shared/state/apps.state.spec.ts index fd8c16c49..83eecd9ea 100644 --- a/src/Squidex/app/shared/state/apps.state.spec.ts +++ b/src/Squidex/app/shared/state/apps.state.spec.ts @@ -12,7 +12,6 @@ import { AppDto, AppsService, AppsState, - CreateAppDto, DateTime, DialogService, Permission @@ -22,11 +21,11 @@ describe('AppsState', () => { const now = DateTime.now(); const oldApps = [ - new AppDto('id1', 'old-name1', [new Permission('Owner')], now, now, 'Free', 'Plan'), - new AppDto('id2', 'old-name2', [new Permission('Owner')], now, now, 'Free', 'Plan') + new AppDto('id1', 'old-name1', [new Permission('Owner')], now, now), + new AppDto('id2', 'old-name2', [new Permission('Owner')], now, now) ]; - const newApp = new AppDto('id3', 'new-name', [new Permission('Owner')], now, now, 'Free', 'Plan'); + const newApp = new AppDto('id3', 'new-name', [new Permission('Owner')], now, now); let dialogs: IMock; let appsService: IMock; @@ -83,7 +82,7 @@ describe('AppsState', () => { }); it('should add app to snapshot when created', () => { - const request = new CreateAppDto(newApp.name); + const request = { ...newApp }; appsService.setup(x => x.postApp(request)) .returns(() => of(newApp)); @@ -94,7 +93,7 @@ describe('AppsState', () => { }); it('should remove app from snashot when archived', () => { - const request = new CreateAppDto(newApp.name); + const request = { ...newApp }; appsService.setup(x => x.postApp(request)) .returns(() => of(newApp)); diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index 7b80efe03..aa32d70f3 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -30,8 +30,8 @@ describe('AssetsState', () => { const newVersion = new Version('2'); const oldAssets = [ - new AssetDto('id1', creator, creator, creation, creation, 'name1', 'type1', 1, 1, 'mime1', false, null, null, 'slug1', ['tag1', 'shared'], 'url1', version), - new AssetDto('id2', creator, creator, creation, creation, 'name2', 'type2', 2, 2, 'mime2', false, null, null, 'slug2', ['tag2', 'shared'], 'url2', version) + new AssetDto('id1', creator, creator, creation, creation, 'name1', 'hash1', 'type1', 1, 1, 'mime1', false, false, null, null, 'slug1', ['tag1', 'shared'], 'url1', version), + new AssetDto('id2', creator, creator, creation, creation, 'name2', 'hash2', 'type2', 2, 2, 'mime2', false, false, null, null, 'slug2', ['tag2', 'shared'], 'url2', version) ]; let dialogs: IMock; @@ -81,7 +81,7 @@ describe('AssetsState', () => { }); it('should add asset to snapshot when created', () => { - const newAsset = new AssetDto('id3', creator, creator, creation, creation, 'name3', 'type3', 3, 3, 'mime3', true, 0, 0, 'slug2', [], 'url3', version); + const newAsset = new AssetDto('id3', creator, creator, creation, creation, 'name3', 'hash3', 'type3', 3, 3, 'mime3', false, true, 0, 0, 'slug2', [], 'url3', version); assetsState.add(newAsset); @@ -90,7 +90,7 @@ describe('AssetsState', () => { }); it('should update properties when updated', () => { - const newAsset = new AssetDto('id1', modifier, modifier, modified, modified, 'name3', 'type3', 3, 3, 'mime3', true, 0, 0, 'slug3', ['new'], 'url3', version); + const newAsset = new AssetDto('id1', modifier, modifier, modified, modified, 'name3', 'hash3', 'type3', 3, 3, 'mime3', false, true, 0, 0, 'slug3', ['new'], 'url3', version); assetsState.update(newAsset); diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index 27a1ebcfa..f11706196 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -14,9 +14,7 @@ import { AppClientsService, AppsState, ClientsState, - CreateAppClientDto, DialogService, - UpdateAppClientDto, Version, Versioned } from './../'; @@ -27,8 +25,8 @@ describe('ClientsState', () => { const newVersion = new Version('2'); const oldClients = [ - new AppClientDto('id1', 'name1', 'secret1', 'Developer'), - new AppClientDto('id2', 'name2', 'secret2', 'Developer') + new AppClientDto('id1', 'name1', 'secret1'), + new AppClientDto('id2', 'name2', 'secret2') ]; let dialogs: IMock; @@ -70,9 +68,9 @@ describe('ClientsState', () => { }); it('should add client to snapshot when created', () => { - const newClient = new AppClientDto('id3', 'name3', 'secret3', 'Developer'); + const newClient = new AppClientDto('id3', 'name3', 'secret3'); - const request = new CreateAppClientDto('id3'); + const request = { id: 'id3' }; clientsService.setup(x => x.postClient(app, request, version)) .returns(() => of(new Versioned(newVersion, newClient))); @@ -84,7 +82,7 @@ describe('ClientsState', () => { }); it('should update properties when updated', () => { - const request = new UpdateAppClientDto('NewName', 'NewRole'); + const request = { name: 'NewName', role: 'NewRole' }; clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version)) .returns(() => of(new Versioned(newVersion, {}))); diff --git a/src/Squidex/app/shared/state/comments.state.spec.ts b/src/Squidex/app/shared/state/comments.state.spec.ts index 4be327dbe..7a101a793 100644 --- a/src/Squidex/app/shared/state/comments.state.spec.ts +++ b/src/Squidex/app/shared/state/comments.state.spec.ts @@ -17,7 +17,6 @@ import { DateTime, DialogService, ImmutableArray, - UpsertCommentDto, Version } from './../'; @@ -56,10 +55,10 @@ describe('CommentsState', () => { it('should load and merge comments', () => { const newComments = new CommentsDto([ - new CommentDto('3', now, 'text3', user) - ], [ - new CommentDto('2', now, 'text2_2', user) - ], ['1'], new Version('2')); + new CommentDto('3', now, 'text3', user) + ], [ + new CommentDto('2', now, 'text2_2', user) + ], ['1'], new Version('2')); commentsService.setup(x => x.getComments(app, commentsId, new Version('1'))) .returns(() => of(newComments)); @@ -78,7 +77,9 @@ describe('CommentsState', () => { it('should add comment to snapshot when created', () => { const newComment = new CommentDto('3', now, 'text3', user); - commentsService.setup(x => x.postComment(app, commentsId, new UpsertCommentDto('text3'))) + const request = { text: 'text3' }; + + commentsService.setup(x => x.postComment(app, commentsId, request)) .returns(() => of(newComment)); commentsState.create('text3').subscribe(); @@ -91,7 +92,9 @@ describe('CommentsState', () => { }); it('should update properties when updated', () => { - commentsService.setup(x => x.putComment(app, commentsId, '2', new UpsertCommentDto('text2_2'))) + const request = { text: 'text2_2' }; + + commentsService.setup(x => x.putComment(app, commentsId, '2', request)) .returns(() => of({})); commentsState.update('2', 'text2_2', now).subscribe(); @@ -101,7 +104,7 @@ describe('CommentsState', () => { new CommentDto('2', now, 'text2_2', user) ])); - commentsService.verify(x => x.putComment(app, commentsId, '2', new UpsertCommentDto('text2_2')), Times.once()); + commentsService.verify(x => x.putComment(app, commentsId, '2', request), Times.once()); }); it('should remove comment from snapshot when deleted', () => { diff --git a/src/Squidex/app/shared/state/comments.state.ts b/src/Squidex/app/shared/state/comments.state.ts index a330ac9ec..fb653ad3e 100644 --- a/src/Squidex/app/shared/state/comments.state.ts +++ b/src/Squidex/app/shared/state/comments.state.ts @@ -17,12 +17,7 @@ import { Version } from '@app/framework'; -import { - CommentDto, - CommentsService, - UpsertCommentDto -} from './../services/comments.service'; - +import { CommentDto, CommentsService } from './../services/comments.service'; import { AppsState } from './apps.state'; interface Snapshot { @@ -81,7 +76,7 @@ export class CommentsState extends State { } public create(text: string): Observable { - return this.commentsService.postComment(this.appName, this.commentsId, new UpsertCommentDto(text)).pipe( + return this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( tap(dto => { this.next(s => { const comments = s.comments.push(dto); @@ -93,7 +88,7 @@ export class CommentsState extends State { } public update(commentId: string, text: string, now?: DateTime): Observable { - return this.commentsService.putComment(this.appName, this.commentsId, commentId, new UpsertCommentDto(text)).pipe( + return this.commentsService.putComment(this.appName, this.commentsId, commentId, { text }).pipe( tap(() => { this.next(s => { const comments = s.comments.map(c => c.id === commentId ? update(c, text, now || DateTime.now()) : c); diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index e3992cad6..0c2893e95 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -13,7 +13,6 @@ import { AppContributorsDto, AppContributorsService, AppsState, - AssignContributorDto, AuthService, ContributorAssignedDto, ContributorsState, @@ -84,7 +83,7 @@ describe('ContributorsState', () => { it('should add contributor to snapshot when assigned', () => { const newContributor = new AppContributorDto('id3', 'Developer'); - const request = new AssignContributorDto('mail2stehle@gmail.com', 'Developer'); + const request = { contributorId: 'mail2stehle@gmail.com', role: 'Developer' }; contributorsService.setup(x => x.postContributor(app, request, version)) .returns(() => of(new Versioned(newVersion, new ContributorAssignedDto('id3', true)))); diff --git a/src/Squidex/app/shared/state/languages.state.spec.ts b/src/Squidex/app/shared/state/languages.state.spec.ts index 1d4c41382..97ab66264 100644 --- a/src/Squidex/app/shared/state/languages.state.spec.ts +++ b/src/Squidex/app/shared/state/languages.state.spec.ts @@ -18,7 +18,6 @@ import { LanguageDto, LanguagesService, LanguagesState, - UpdateAppLanguageDto, Version, Versioned } from './../'; @@ -121,7 +120,7 @@ describe('LanguagesState', () => { }); it('should update language in snapshot when updated', () => { - const request = new UpdateAppLanguageDto(true, false, []); + const request = { isMaster: true }; languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) .returns(() => of(new Versioned(newVersion, {}))); diff --git a/src/Squidex/app/shared/state/languages.state.ts b/src/Squidex/app/shared/state/languages.state.ts index 43659f094..9910fe399 100644 --- a/src/Squidex/app/shared/state/languages.state.ts +++ b/src/Squidex/app/shared/state/languages.state.ts @@ -17,7 +17,12 @@ import { Version } from '@app/framework'; -import { AddAppLanguageDto, AppLanguageDto, AppLanguagesService, UpdateAppLanguageDto } from './../services/app-languages.service'; +import { + AppLanguageDto, + AppLanguagesService, + UpdateAppLanguageDto +} from './../services/app-languages.service'; + import { LanguageDto, LanguagesService } from './../services/languages.service'; import { AppsState } from './apps.state'; @@ -105,7 +110,7 @@ export class LanguagesState extends State { } public add(language: LanguageDto): Observable { - return this.appLanguagesService.postLanguage(this.appName, new AddAppLanguageDto(language.iso2Code), this.version).pipe( + return this.appLanguagesService.postLanguage(this.appName, { language: language.iso2Code }, this.version).pipe( tap(dto => { const languages = this.snapshot.plainLanguages.push(dto.payload).sortByStringAsc(x => x.englishName); @@ -129,9 +134,9 @@ export class LanguagesState extends State { tap(dto => { const languages = this.snapshot.plainLanguages.map(l => { if (l.iso2Code === language.iso2Code) { - return update(l, request.isMaster, request.isOptional, request.fallback); + return update(l, request); } else if (l.isMaster && request.isMaster) { - return update(l, false, l.isOptional, l.fallback); + return update(l, { isMaster: false }); } else { return l; } @@ -190,10 +195,5 @@ export class LanguagesState extends State { } } -const update = (language: AppLanguageDto, isMaster: boolean, isOptional: boolean, fallback: string[]) => - new AppLanguageDto( - language.iso2Code, - language.englishName, - isMaster, - isOptional, - fallback); \ No newline at end of file +const update = (language: AppLanguageDto, request: UpdateAppLanguageDto) => + language.with(request); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index 8a72ce685..583bd6ec8 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -14,7 +14,6 @@ import { AppPatternsService, AppsState, DialogService, - EditAppPatternDto, PatternsState, Version, Versioned @@ -70,7 +69,7 @@ describe('PatternsState', () => { it('should add pattern to snapshot when created', () => { const newPattern = new AppPatternDto('id3', 'name3', 'pattern3', ''); - const request = new EditAppPatternDto('name3', 'pattern3', ''); + const request = { ...newPattern }; patternsService.setup(x => x.postPattern(app, request, version)) .returns(() => of(new Versioned(newVersion, newPattern))); @@ -82,7 +81,7 @@ describe('PatternsState', () => { }); it('should update properties when updated', () => { - const request = new EditAppPatternDto('a_name2', 'a_pattern2', 'a_message2'); + const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' }; patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) .returns(() => of(new Versioned(newVersion, {}))); @@ -91,9 +90,9 @@ describe('PatternsState', () => { const pattern_1 = patternsState.snapshot.patterns.at(0); - expect(pattern_1.name).toBe('a_name2'); - expect(pattern_1.pattern).toBe('a_pattern2'); - expect(pattern_1.message).toBe('a_message2'); + expect(pattern_1.name).toBe(request.name); + expect(pattern_1.pattern).toBe(request.pattern); + expect(pattern_1.message).toBe(request.message); expect(patternsState.snapshot.version).toEqual(newVersion); }); diff --git a/src/Squidex/app/shared/state/patterns.state.ts b/src/Squidex/app/shared/state/patterns.state.ts index 649308978..7673b50b8 100644 --- a/src/Squidex/app/shared/state/patterns.state.ts +++ b/src/Squidex/app/shared/state/patterns.state.ts @@ -120,4 +120,4 @@ export class PatternsState extends State { } const update = (pattern: AppPatternDto, request: EditAppPatternDto) => - new AppPatternDto(pattern.id, request.name, request.pattern, request.message); \ No newline at end of file + pattern.with(request); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/plans.state.spec.ts b/src/Squidex/app/shared/state/plans.state.spec.ts index ba8929185..e30c52238 100644 --- a/src/Squidex/app/shared/state/plans.state.spec.ts +++ b/src/Squidex/app/shared/state/plans.state.spec.ts @@ -103,7 +103,7 @@ describe('PlansState', () => { plansState.window = { location: {} }; plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, new PlanChangedDto('URI')))); + .returns(() => of(new Versioned(newVersion, { redirectUri: 'http://url' }))); plansState.load().subscribe(); plansState.change('free').pipe(onErrorResumeNext()).subscribe(); @@ -120,7 +120,7 @@ describe('PlansState', () => { plansState.window = { location: {} }; plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, new PlanChangedDto('')))); + .returns(() => of(new Versioned(newVersion, { redirectUri: '' }))); plansState.load().subscribe(); plansState.change('id2_yearly').pipe(onErrorResumeNext()).subscribe(); diff --git a/src/Squidex/app/shared/state/plans.state.ts b/src/Squidex/app/shared/state/plans.state.ts index b4ae83ae3..a0745f2aa 100644 --- a/src/Squidex/app/shared/state/plans.state.ts +++ b/src/Squidex/app/shared/state/plans.state.ts @@ -18,14 +18,9 @@ import { } from '@app/framework'; import { AuthService } from './../services/auth.service'; +import { PlanDto, PlansService } from './../services/plans.service'; import { AppsState } from './apps.state'; -import { - ChangePlanDto, - PlanDto, - PlansService -} from './../services/plans.service'; - interface PlanInfo { // The plan. plan: PlanDto; @@ -116,7 +111,7 @@ export class PlansState extends State { } public change(planId: string): Observable { - return this.plansService.putPlan(this.appName, new ChangePlanDto(planId), this.version).pipe( + return this.plansService.putPlan(this.appName, { planId }, this.version).pipe( tap(dto => { if (dto.payload.redirectUri && dto.payload.redirectUri.length > 0) { this.window.location.href = dto.payload.redirectUri; diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index a52781fcc..eb8c5f59b 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -13,10 +13,8 @@ import { AppRolesDto, AppRolesService, AppsState, - CreateAppRoleDto, DialogService, RolesState, - UpdateAppRoleDto, Version, Versioned } from './../'; @@ -72,7 +70,7 @@ describe('RolesState', () => { it('should add role to snapshot when added', () => { const newRole = new AppRoleDto('Role3', 0, 0, ['P3']); - const request = new CreateAppRoleDto('Role3'); + const request = { name: newRole.name }; rolesService.setup(x => x.postRole(app, request, version)) .returns(() => of(new Versioned(newVersion, newRole))); @@ -84,7 +82,7 @@ describe('RolesState', () => { }); it('should update permissions when updated', () => { - const request = new UpdateAppRoleDto(['P4', 'P5']); + const request = { permissions: ['P4', 'P5'] }; rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version)) .returns(() => of(new Versioned(newVersion, {}))); diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index 59331b2c5..5181981ab 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -13,7 +13,6 @@ import { RulesState } from './rules.state'; import { AppsState, AuthService, - CreateRuleDto, DateTime, DialogService, RuleDto, @@ -83,7 +82,7 @@ describe('RulesState', () => { it('should add rule to snapshot when created', () => { const newRule = new RuleDto('id3', creator, creator, creation, creation, version, false, {}, 'trigger3', {}, 'action3'); - const request = new CreateRuleDto({}, {}); + const request = { action: {}, trigger: {} }; rulesService.setup(x => x.postRule(app, request, modifier, creation)) .returns(() => of(newRule)); diff --git a/src/Squidex/app/shared/state/rules.state.ts b/src/Squidex/app/shared/state/rules.state.ts index a8cc1dffb..6cc19956a 100644 --- a/src/Squidex/app/shared/state/rules.state.ts +++ b/src/Squidex/app/shared/state/rules.state.ts @@ -24,8 +24,7 @@ import { AppsState } from './apps.state'; import { CreateRuleDto, RuleDto, - RulesService, - UpdateRuleDto + RulesService } from './../services/rules.service'; interface Snapshot { @@ -100,7 +99,7 @@ export class RulesState extends State { } public updateAction(rule: RuleDto, action: any, now?: DateTime): Observable { - return this.rulesService.putRule(this.appName, rule.id, new UpdateRuleDto(null, action), rule.version).pipe( + return this.rulesService.putRule(this.appName, rule.id, { action }, rule.version).pipe( tap(dto => { this.replaceRule(updateAction(rule, action, this.user, dto.version, now)); }), @@ -108,7 +107,7 @@ export class RulesState extends State { } public updateTrigger(rule: RuleDto, trigger: any, now?: DateTime): Observable { - return this.rulesService.putRule(this.appName, rule.id, new UpdateRuleDto(trigger, null), rule.version).pipe( + return this.rulesService.putRule(this.appName, rule.id, { trigger }, rule.version).pipe( tap(dto => { this.replaceRule(updateTrigger(rule, trigger, this.user, dto.version, now)); }), 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 b0cd01ea5..995f42271 100644 --- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs +++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/AssetsFieldTests.cs @@ -28,6 +28,8 @@ namespace Squidex.Domain.Apps.Core.Operations.ValidateContent public string FileName { get; set; } + public string FileHash { get; set; } + public string Slug { get; set; } public long FileSize { get; set; } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs index 1d9ac1cb4..e21102546 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs @@ -14,6 +14,7 @@ using FakeItEasy; using Orleans; using Squidex.Domain.Apps.Core.Tags; using Squidex.Domain.Apps.Entities.Assets.Commands; +using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Entities.Assets.State; using Squidex.Domain.Apps.Entities.Tags; using Squidex.Domain.Apps.Entities.TestHelpers; @@ -26,8 +27,9 @@ namespace Squidex.Domain.Apps.Entities.Assets { public class AssetCommandMiddlewareTests : HandlerTestBase { + private readonly AssetQueryService assetQueryService = A.Fake(); private readonly IAssetThumbnailGenerator assetThumbnailGenerator = A.Fake(); - private readonly IAssetStore assetStore = A.Fake(); + private readonly IAssetStore assetStore = A.Fake(); private readonly ITagService tagService = A.Fake(); private readonly ITagGenerator tagGenerator = A.Fake>(); private readonly IGrainFactory grainFactory = A.Fake(); @@ -56,7 +58,7 @@ namespace Squidex.Domain.Apps.Entities.Assets A.CallTo(() => grainFactory.GetGrain(Id, null)) .Returns(asset); - sut = new AssetCommandMiddleware(grainFactory, assetStore, assetThumbnailGenerator, new[] { tagGenerator }); + sut = new AssetCommandMiddleware(grainFactory, assetQueryService, assetStore, assetThumbnailGenerator, new[] { tagGenerator }); } [Fact] @@ -65,20 +67,14 @@ namespace Squidex.Domain.Apps.Entities.Assets var command = new CreateAsset { AssetId = assetId, File = file }; var context = CreateContextForCommand(command); - A.CallTo(() => tagGenerator.GenerateTags(command, A>.Ignored)) - .Invokes(new Action>((c, tags) => - { - tags.Add("tag1"); - tags.Add("tag2"); - })); - + SetupTags(command); SetupImageInfo(); await sut.HandleAsync(context); var result = context.Result(); - Assert.Equal(assetId, result.Id); + Assert.Equal(assetId, result.IdOrValue); Assert.Contains("tag1", result.Tags); Assert.Contains("tag2", result.Tags); @@ -86,10 +82,66 @@ namespace Squidex.Domain.Apps.Entities.Assets AssertAssetImageChecked(); } + [Fact] + public async Task Create_should_calculate_hash() + { + var command = new CreateAsset { AssetId = assetId, File = file }; + var context = CreateContextForCommand(command); + + SetupImageInfo(); + + await sut.HandleAsync(context); + + Assert.True(command.FileHash.Length > 10); + } + + [Fact] + public async Task Create_should_return_duplicate_result_if_file_with_same_hash_found() + { + var command = new CreateAsset { AssetId = assetId, File = file }; + var context = CreateContextForCommand(command); + + SetupSameHashAsset(file.FileName, file.FileSize, out _); + SetupImageInfo(); + + await sut.HandleAsync(context); + + Assert.True(context.Result().IsDuplicate); + } + + [Fact] + public async Task Create_should_not_return_duplicate_result_if_file_with_same_hash_but_other_name_found() + { + var command = new CreateAsset { AssetId = assetId, File = file }; + var context = CreateContextForCommand(command); + + SetupSameHashAsset("other-name", file.FileSize, out _); + SetupImageInfo(); + + await sut.HandleAsync(context); + + Assert.False(context.Result().IsDuplicate); + } + + [Fact] + public async Task Create_should_not_return_duplicate_result_if_file_with_same_hash_but_other_size_found() + { + var command = new CreateAsset { AssetId = assetId, File = file }; + var context = CreateContextForCommand(command); + + SetupSameHashAsset(file.FileName, 12345, out _); + SetupImageInfo(); + + await sut.HandleAsync(context); + + Assert.False(context.Result().IsDuplicate); + } + [Fact] public async Task Update_should_update_domain_object() { - var context = CreateContextForCommand(new UpdateAsset { AssetId = assetId, File = file }); + var command = new UpdateAsset { AssetId = assetId, File = file }; + var context = CreateContextForCommand(command); SetupImageInfo(); @@ -101,16 +153,41 @@ namespace Squidex.Domain.Apps.Entities.Assets AssertAssetImageChecked(); } + [Fact] + public async Task Update_should_calculate_hash() + { + var command = new UpdateAsset { AssetId = assetId, File = file }; + var context = CreateContextForCommand(command); + + SetupImageInfo(); + + await ExecuteCreateAsync(); + + await sut.HandleAsync(context); + + Assert.True(command.FileHash.Length > 10); + } + private Task ExecuteCreateAsync() { return asset.ExecuteAsync(CreateCommand(new CreateAsset { AssetId = Id, File = file })); } + private void SetupTags(CreateAsset command) + { + A.CallTo(() => tagGenerator.GenerateTags(command, A>.Ignored)) + .Invokes(new Action>((c, tags) => + { + tags.Add("tag1"); + tags.Add("tag2"); + })); + } + private void AssertAssetHasBeenUploaded(long version, Guid commitId) { var fileName = AssetStoreExtensions.GetFileName(assetId.ToString(), version); - A.CallTo(() => assetStore.UploadAsync(commitId.ToString(), stream, false, CancellationToken.None)) + A.CallTo(() => assetStore.UploadAsync(commitId.ToString(), A.Ignored, false, CancellationToken.None)) .MustHaveHappened(); A.CallTo(() => assetStore.CopyAsync(commitId.ToString(), fileName, CancellationToken.None)) .MustHaveHappened(); @@ -118,6 +195,17 @@ namespace Squidex.Domain.Apps.Entities.Assets .MustHaveHappened(); } + private void SetupSameHashAsset(string fileName, long fileSize, out IAssetEntity existing) + { + var temp = existing = A.Fake(); + + A.CallTo(() => temp.FileName).Returns(fileName); + A.CallTo(() => temp.FileSize).Returns(fileSize); + + A.CallTo(() => assetQueryService.FindAssetByHashAsync(A.Ignored, A.Ignored)) + .Returns(existing); + } + private void SetupImageInfo() { A.CallTo(() => assetThumbnailGenerator.GetImageInfoAsync(stream)) diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetGrainTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetGrainTests.cs index 1846de4b4..8ef290b23 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetGrainTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetGrainTests.cs @@ -27,8 +27,9 @@ namespace Squidex.Domain.Apps.Entities.Assets { private readonly ITagService tagService = A.Fake(); private readonly ImageInfo image = new ImageInfo(2048, 2048); - private readonly Guid assetId = Guid.NewGuid(); private readonly AssetFile file = new AssetFile("my-image.png", "image/png", 1024, () => new MemoryStream()); + private readonly Guid assetId = Guid.NewGuid(); + private readonly string fileHash = Guid.NewGuid().ToString(); private readonly AssetGrain sut; protected override Guid Id @@ -57,13 +58,14 @@ namespace Squidex.Domain.Apps.Entities.Assets [Fact] public async Task Create_should_create_events() { - var command = new CreateAsset { File = file, ImageInfo = image }; + var command = new CreateAsset { File = file, ImageInfo = image, FileHash = fileHash, Tags = new HashSet() }; var result = await sut.ExecuteAsync(CreateAssetCommand(command)); - result.ShouldBeEquivalent(new AssetSavedResult(0, 0)); + result.ShouldBeEquivalent(new AssetSavedResult(0, 0, fileHash)); Assert.Equal(0, sut.Snapshot.FileVersion); + Assert.Equal(fileHash, sut.Snapshot.FileHash); LastEvents .ShouldHaveSameEvents( @@ -71,6 +73,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { IsImage = true, FileName = file.FileName, + FileHash = fileHash, FileSize = file.FileSize, FileVersion = 0, MimeType = file.MimeType, @@ -85,15 +88,16 @@ namespace Squidex.Domain.Apps.Entities.Assets [Fact] public async Task Update_should_create_events() { - var command = new UpdateAsset { File = file, ImageInfo = image }; + var command = new UpdateAsset { File = file, ImageInfo = image, FileHash = fileHash }; await ExecuteCreateAsync(); var result = await sut.ExecuteAsync(CreateAssetCommand(command)); - result.ShouldBeEquivalent(new AssetSavedResult(1, 1)); + result.ShouldBeEquivalent(new AssetSavedResult(1, 1, fileHash)); Assert.Equal(1, sut.Snapshot.FileVersion); + Assert.Equal(fileHash, sut.Snapshot.FileHash); LastEvents .ShouldHaveSameEvents( @@ -101,6 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { IsImage = true, FileSize = file.FileSize, + FileHash = fileHash, FileVersion = 1, MimeType = file.MimeType, PixelWidth = image.PixelWidth, diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs index f5520618b..308faf158 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetQueryServiceTests.cs @@ -57,7 +57,7 @@ namespace Squidex.Domain.Apps.Entities.Assets { var id = Guid.NewGuid(); - A.CallTo(() => assetRepository.FindAssetAsync(id)) + A.CallTo(() => assetRepository.FindAssetAsync(id, false)) .Returns(CreateAsset(id, "id1", "id2", "id3")); var result = await sut.FindAssetAsync(context, id); @@ -65,6 +65,19 @@ namespace Squidex.Domain.Apps.Entities.Assets Assert.Equal(HashSet.Of("name1", "name2", "name3"), result.Tags); } + [Fact] + public async Task Should_find_asset_by_hash_and_resolve_tags() + { + var id = Guid.NewGuid(); + + A.CallTo(() => assetRepository.FindAssetByHashAsync(appId.Id, "hash")) + .Returns(CreateAsset(id, "id1", "id2", "id3")); + + var result = await sut.FindAssetByHashAsync(appId.Id, "hash"); + + Assert.Equal(HashSet.Of("name1", "name2", "name3"), result.Tags); + } + [Fact] public async Task Should_load_assets_from_ids_and_resolve_tags() { diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/TestData/FakeAssetEntity.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/TestData/FakeAssetEntity.cs index d51659fca..2daf028de 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/TestData/FakeAssetEntity.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/TestData/FakeAssetEntity.cs @@ -37,6 +37,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.TestData public string FileName { get; set; } + public string FileHash { get; set; } + public string Slug { get; set; } public long FileSize { get; set; } diff --git a/tests/Squidex.Infrastructure.Tests/Assets/HasherStreamTests.cs b/tests/Squidex.Infrastructure.Tests/Assets/HasherStreamTests.cs new file mode 100644 index 000000000..fd8e07631 --- /dev/null +++ b/tests/Squidex.Infrastructure.Tests/Assets/HasherStreamTests.cs @@ -0,0 +1,47 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.IO; +using System.Security.Cryptography; +using Xunit; + +namespace Squidex.Infrastructure.Assets +{ + public class HasherStreamTests + { + [Fact] + public void Should_calculate_hash_while_copying() + { + var source = GenerateTestData(); + var sourceHash = source.Sha256Base64(); + + var sourceStream = new HasherStream(new MemoryStream(source), HashAlgorithmName.SHA256); + + using (sourceStream) + { + var target = new MemoryStream(); + + sourceStream.CopyTo(target); + + var targetHash = sourceStream.GetHashStringAndReset(); + + Assert.Equal(sourceHash, targetHash); + } + } + + private byte[] GenerateTestData(int length = 1000) + { + var random = new Random(); + var result = new byte[length]; + + random.NextBytes(result); + + return result; + } + } +} diff --git a/tests/Squidex.Infrastructure.Tests/DispatchingTests.cs b/tests/Squidex.Infrastructure.Tests/DispatchingTests.cs index a7ea52049..cca1080fa 100644 --- a/tests/Squidex.Infrastructure.Tests/DispatchingTests.cs +++ b/tests/Squidex.Infrastructure.Tests/DispatchingTests.cs @@ -10,6 +10,8 @@ using Squidex.Infrastructure.Dispatching; using Squidex.Infrastructure.Tasks; using Xunit; +#pragma warning disable IDE0060 // Remove unused parameter + namespace Squidex.Infrastructure { public class DispatchingTests @@ -95,13 +97,13 @@ namespace Squidex.Infrastructure public Task On(MyEventA @event, int context) { - EventATriggered = EventATriggered + context; + EventATriggered += context; return TaskHelper.Done; } public Task On(MyEventB @event, int context) { - EventBTriggered = EventATriggered + context; + EventBTriggered += context; return TaskHelper.Done; } } @@ -169,12 +171,12 @@ namespace Squidex.Infrastructure public void On(MyEventA @event, int context) { - EventATriggered = EventATriggered + context; + EventATriggered += context; } public void On(MyEventB @event, int context) { - EventBTriggered = EventATriggered + context; + EventBTriggered += context; } } From b47deb8ab45e364726460d3bd9ced533b3338bab Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 26 Apr 2019 10:49:13 +0200 Subject: [PATCH 02/20] Temp --- .../event-consumers-page.component.ts | 3 +- .../pages/users/user-page.component.ts | 7 +++- .../pages/users/users-page.component.ts | 3 +- .../services/users.service.spec.ts | 6 +-- .../pages/content/content-field.component.ts | 3 +- .../pages/rules/rule-wizard.component.ts | 3 +- .../pages/schema/field-wizard.component.ts | 5 +-- .../schemas/pages/schema/field.component.ts | 9 ++-- .../forms/field-form-validation.component.ts | 6 +-- .../types/string-validation.component.ts | 6 +-- .../pages/clients/client.component.ts | 21 ++++------ .../pages/clients/clients-page.component.ts | 9 ++-- .../contributors-page.component.ts | 13 +++--- .../pages/languages/language.component.ts | 5 +-- .../pages/patterns/pattern.component.ts | 4 +- .../pages/patterns/patterns-page.component.ts | 4 +- .../settings/pages/roles/role.component.ts | 9 ++-- .../pages/roles/roles-page.component.ts | 10 ++--- src/Squidex/app/framework/state.ts | 16 +++---- .../shared/components/app-form.component.ts | 3 +- src/Squidex/app/shared/internal.ts | 8 ++-- src/Squidex/app/shared/module.ts | 16 +++---- .../shared/services/app-languages.service.ts | 8 ++-- .../shared/services/assets.service.spec.ts | 42 +++++++++++-------- .../app/shared/services/assets.service.ts | 4 +- ...ervice.spec.ts => clients.service.spec.ts} | 42 +++++++++---------- ...-clients.service.ts => clients.service.ts} | 26 ++++++------ ...e.spec.ts => contributors.service.spec.ts} | 30 ++++++------- ...ors.service.ts => contributors.service.ts} | 14 +++---- .../app/shared/services/help.service.spec.ts | 2 +- ...rvice.spec.ts => patterns.service.spec.ts} | 30 ++++++------- ...atterns.service.ts => patterns.service.ts} | 22 +++++----- ....service.spec.ts => roles.service.spec.ts} | 32 +++++++------- ...{app-roles.service.ts => roles.service.ts} | 24 +++++------ .../shared/services/schemas.service.spec.ts | 8 ++-- .../app/shared/services/schemas.service.ts | 12 ++++++ .../app/shared/state/clients.state.spec.ts | 20 ++++----- src/Squidex/app/shared/state/clients.state.ts | 30 ++++++------- .../shared/state/contributors.state.spec.ts | 26 ++++++------ .../app/shared/state/contributors.state.ts | 26 ++++++------ .../app/shared/state/patterns.state.spec.ts | 20 ++++----- .../app/shared/state/patterns.state.ts | 28 ++++++------- .../app/shared/state/roles.state.spec.ts | 20 ++++----- src/Squidex/app/shared/state/roles.state.ts | 30 ++++++------- .../app/shared/state/schemas.state.spec.ts | 12 +++--- src/Squidex/app/shared/state/schemas.state.ts | 11 +++-- 46 files changed, 346 insertions(+), 342 deletions(-) rename src/Squidex/app/shared/services/{app-clients.service.spec.ts => clients.service.spec.ts} (68%) rename src/Squidex/app/shared/services/{app-clients.service.ts => clients.service.ts} (82%) rename src/Squidex/app/shared/services/{app-contributors.service.spec.ts => contributors.service.spec.ts} (71%) rename src/Squidex/app/shared/services/{app-contributors.service.ts => contributors.service.ts} (87%) rename src/Squidex/app/shared/services/{app-patterns.service.spec.ts => patterns.service.spec.ts} (75%) rename src/Squidex/app/shared/services/{app-patterns.service.ts => patterns.service.ts} (81%) rename src/Squidex/app/shared/services/{app-roles.service.spec.ts => roles.service.spec.ts} (77%) rename src/Squidex/app/shared/services/{app-roles.service.ts => roles.service.ts} (81%) diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts index 30b65c600..c23849a99 100644 --- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts +++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts @@ -11,8 +11,7 @@ import { onErrorResumeNext, switchMap } from 'rxjs/operators'; import { DialogModel, ResourceOwner } from '@app/shared'; -import { EventConsumerDto } from './../../services/event-consumers.service'; -import { EventConsumersState } from './../../state/event-consumers.state'; +import { EventConsumerDto, EventConsumersState } from '../../declarations'; @Component({ selector: 'sqx-event-consumers-page', diff --git a/src/Squidex/app/features/administration/pages/users/user-page.component.ts b/src/Squidex/app/features/administration/pages/users/user-page.component.ts index e009b6115..e2be65749 100644 --- a/src/Squidex/app/features/administration/pages/users/user-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/user-page.component.ts @@ -11,8 +11,11 @@ import { ActivatedRoute, Router } from '@angular/router'; import { ResourceOwner } from '@app/shared'; -import { UserDto } from './../../services/users.service'; -import { UserForm, UsersState } from './../../state/users.state'; +import { + UserDto, + UserForm, + UsersState +} from '../../declarations'; @Component({ selector: 'sqx-user-page', diff --git a/src/Squidex/app/features/administration/pages/users/users-page.component.ts b/src/Squidex/app/features/administration/pages/users/users-page.component.ts index 8d8c5c052..a7b6ab87d 100644 --- a/src/Squidex/app/features/administration/pages/users/users-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/users-page.component.ts @@ -9,8 +9,7 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { onErrorResumeNext } from 'rxjs/operators'; -import { UserDto } from './../../services/users.service'; -import { UsersState } from './../../state/users.state'; +import { UserDto, UsersState } from '../../declarations'; @Component({ selector: 'sqx-users-page', diff --git a/src/Squidex/app/features/administration/services/users.service.spec.ts b/src/Squidex/app/features/administration/services/users.service.spec.ts index 2095c84ef..ee74d079f 100644 --- a/src/Squidex/app/features/administration/services/users.service.spec.ts +++ b/src/Squidex/app/features/administration/services/users.service.spec.ts @@ -11,8 +11,6 @@ import { inject, TestBed } from '@angular/core/testing'; import { ApiUrlConfig } from '@app/framework'; import { - CreateUserDto, - UpdateUserDto, UserDto, UsersDto, UsersService @@ -145,7 +143,7 @@ describe('UsersService', () => { it('should make post request to create user', inject([UsersService, HttpTestingController], (userManagementService: UsersService, httpMock: HttpTestingController) => { - const dto = new CreateUserDto('mail@squidex.io', 'Squidex User', ['Permission1'], 'password'); + const dto = { email: 'mail@squidex.io', displayName: 'Squidex User', permissions: ['Permission1'], password: 'password' }; let user: UserDto; @@ -166,7 +164,7 @@ describe('UsersService', () => { it('should make put request to update user', inject([UsersService, HttpTestingController], (userManagementService: UsersService, httpMock: HttpTestingController) => { - const dto = new UpdateUserDto('mail@squidex.io', 'Squidex User', ['Permission1'], 'password'); + const dto = { email: 'mail@squidex.io', displayName: 'Squidex User', permissions: ['Permission1'], password: 'password' }; userManagementService.putUser('123', dto).subscribe(); diff --git a/src/Squidex/app/features/content/pages/content/content-field.component.ts b/src/Squidex/app/features/content/pages/content/content-field.component.ts index 24fe7fdc2..c949af5de 100644 --- a/src/Squidex/app/features/content/pages/content/content-field.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-field.component.ts @@ -19,7 +19,6 @@ import { LocalStoreService, RootFieldDto, SchemaDto, - TranslateDto, TranslationsService, Types, value$ @@ -158,7 +157,7 @@ export class ContentFieldComponent implements OnChanges { const value = control.value; if (!value) { - const request = new TranslateDto(text, sourceLanguage, targetLanguage); + const request = { text, sourceLanguage, targetLanguage }; this.translations.translate(this.appsState.appName, request) .subscribe(result => { diff --git a/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts b/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts index 5d493db2b..a6339aa75 100644 --- a/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts +++ b/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts @@ -9,7 +9,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { - CreateRuleDto, Form, ImmutableArray, RuleDto, @@ -118,7 +117,7 @@ export class RuleWizardComponent implements OnInit { } private createRule() { - const requestDto = new CreateRuleDto(this.trigger, this.action); + const requestDto = { trigger: this.trigger, action: this.action }; this.rulesState.create(requestDto) .subscribe(() => { diff --git a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts index d341f4af2..ea4a99529 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts @@ -18,8 +18,7 @@ import { RootFieldDto, SchemaDetailsDto, SchemasState, - Types, - UpdateFieldDto + Types } from '@app/shared'; @Component({ @@ -103,7 +102,7 @@ export class FieldWizardComponent implements OnInit { if (value) { const properties = createProperties(this.field.properties['fieldType'], value); - this.schemasState.updateField(this.schema, this.field as RootFieldDto, new UpdateFieldDto(properties)) + this.schemasState.updateField(this.schema, this.field as RootFieldDto, { properties }) .subscribe(() => { this.editForm.submitCompleted(); diff --git a/src/Squidex/app/features/schemas/pages/schema/field.component.ts b/src/Squidex/app/features/schemas/pages/schema/field.component.ts index f3c843584..2e64fdf05 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/field.component.ts @@ -10,7 +10,6 @@ import { FormBuilder } from '@angular/forms'; import { onErrorResumeNext } from 'rxjs/operators'; import { - AppPatternDto, createProperties, DialogModel, EditFieldForm, @@ -18,10 +17,10 @@ import { ImmutableArray, ModalModel, NestedFieldDto, + PatternDto, RootFieldDto, SchemaDetailsDto, - SchemasState, - UpdateFieldDto + SchemasState } from '@app/shared'; @Component({ @@ -43,7 +42,7 @@ export class FieldComponent implements OnChanges { public parent: RootFieldDto; @Input() - public patterns: ImmutableArray; + public patterns: ImmutableArray; public dropdown = new ModalModel(); @@ -120,7 +119,7 @@ export class FieldComponent implements OnChanges { if (value) { const properties = createProperties(this.field.properties['fieldType'], value); - this.schemasState.updateField(this.schema, this.field, new UpdateFieldDto(properties)) + this.schemasState.updateField(this.schema, this.field, { properties }) .subscribe(() => { this.editForm.submitCompleted(); }, error => { diff --git a/src/Squidex/app/features/schemas/pages/schema/forms/field-form-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/forms/field-form-validation.component.ts index 9917a677d..d02c495a5 100644 --- a/src/Squidex/app/features/schemas/pages/schema/forms/field-form-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/forms/field-form-validation.component.ts @@ -9,9 +9,9 @@ import { Component, Input } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { - AppPatternDto, FieldDto, - ImmutableArray + ImmutableArray, + PatternDto } from '@app/shared'; @Component({ @@ -27,5 +27,5 @@ export class FieldFormValidationComponent { public field: FieldDto; @Input() - public patterns: ImmutableArray; + public patterns: ImmutableArray; } \ No newline at end of file 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 77cd4f192..7ecd32f9b 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 @@ -10,11 +10,11 @@ import { FormControl, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; import { - AppPatternDto, FieldDto, hasNoValue$, ImmutableArray, ModalModel, + PatternDto, ResourceOwner, RootFieldDto, StringFieldPropertiesDto, @@ -37,7 +37,7 @@ export class StringValidationComponent extends ResourceOwner implements OnInit { public properties: StringFieldPropertiesDto; @Input() - public patterns: ImmutableArray; + public patterns: ImmutableArray; public showDefaultValue: Observable; public showPatternMessage: boolean; @@ -93,7 +93,7 @@ export class StringValidationComponent extends ResourceOwner implements OnInit { this.setPatternName(); } - public setPattern(pattern: AppPatternDto) { + public setPattern(pattern: PatternDto) { this.patternName = pattern.name; this.editForm.controls['pattern'].setValue(pattern.pattern); this.editForm.controls['patternMessage'].setValue(pattern.message); diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.ts b/src/Squidex/app/features/settings/pages/clients/client.component.ts index fd8648645..e45c48ac9 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/client.component.ts @@ -12,15 +12,14 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AccessTokenDto, ApiUrlConfig, - AppClientDto, - AppClientsService, - AppRoleDto, AppsState, + ClientDto, + ClientsService, ClientsState, DialogModel, DialogService, RenameClientForm, - UpdateAppClientDto + RoleDto } from '@app/shared'; const ESCAPE_KEY = 27; @@ -62,10 +61,10 @@ function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, }) export class ClientComponent implements OnChanges { @Input() - public client: AppClientDto; + public client: ClientDto; @Input() - public clientRoles: AppRoleDto[]; + public clientRoles: RoleDto[]; public isRenaming = false; @@ -82,7 +81,7 @@ export class ClientComponent implements OnChanges { constructor( public readonly appsState: AppsState, private readonly apiUrl: ApiUrlConfig, - private readonly appClientsService: AppClientsService, + private readonly clientsService: ClientsService, private readonly clientsState: ClientsState, private readonly dialogs: DialogService, private readonly formBuilder: FormBuilder @@ -105,7 +104,7 @@ export class ClientComponent implements OnChanges { } public update(role: string) { - this.clientsState.update(this.client, new UpdateAppClientDto(undefined, role)).pipe(onErrorResumeNext()).subscribe(); + this.clientsState.update(this.client, { role }).pipe(onErrorResumeNext()).subscribe(); } public toggleRename() { @@ -122,9 +121,7 @@ export class ClientComponent implements OnChanges { const value = this.renameForm.submit(); if (value) { - const requestDto = new UpdateAppClientDto(value.name); - - this.clientsState.update(this.client, requestDto) + this.clientsState.update(this.client, value) .subscribe(() => { this.renameForm.submitCompleted(); @@ -138,7 +135,7 @@ export class ClientComponent implements OnChanges { public connect() { this.connectDialog.show(); - this.appClientsService.createToken(this.appsState.appName, this.client) + this.clientsService.createToken(this.appsState.appName, this.client) .subscribe(dto => { this.connectToken = dto; }, error => { diff --git a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts index 00caae62c..bb73da085 100644 --- a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts @@ -10,11 +10,10 @@ import { FormBuilder } from '@angular/forms'; import { onErrorResumeNext } from 'rxjs/operators'; import { - AppClientDto, AppsState, AttachClientForm, + ClientDto, ClientsState, - CreateAppClientDto, RolesState } from '@app/shared'; @@ -48,9 +47,7 @@ export class ClientsPageComponent implements OnInit { const value = this.addClientForm.submit(); if (value) { - const requestDto = new CreateAppClientDto(value.name); - - this.clientsState.attach(requestDto) + this.clientsState.attach(value) .subscribe(() => { this.addClientForm.submitCompleted(); }, error => { @@ -63,7 +60,7 @@ export class ClientsPageComponent implements OnInit { this.addClientForm.submitCompleted(); } - public trackByClient(index: number, item: AppClientDto) { + public trackByClient(index: number, item: ClientDto) { return item.id; } } \ No newline at end of file diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts index 61d77c7b8..c3807c899 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts @@ -11,11 +11,10 @@ import { Observable } from 'rxjs'; import { onErrorResumeNext, withLatestFrom } from 'rxjs/operators'; import { - AppContributorDto, AppsState, - AssignContributorDto, AssignContributorForm, AutocompleteSource, + ContributorDto, ContributorsState, DialogService, RolesState, @@ -78,12 +77,12 @@ export class ContributorsPageComponent implements OnInit { this.contributorsState.load(true).pipe(onErrorResumeNext()).subscribe(); } - public remove(contributor: AppContributorDto) { + public remove(contributor: ContributorDto) { this.contributorsState.revoke(contributor).pipe(onErrorResumeNext()).subscribe(); } - public changeRole(contributor: AppContributorDto, role: string) { - this.contributorsState.assign(new AssignContributorDto(contributor.contributorId, role)).pipe(onErrorResumeNext()).subscribe(); + public changeRole(contributor: ContributorDto, role: string) { + this.contributorsState.assign({ contributorId: contributor.contributorId, role }).pipe(onErrorResumeNext()).subscribe(); } public assignContributor() { @@ -96,7 +95,7 @@ export class ContributorsPageComponent implements OnInit { user = user.id; } - const requestDto = new AssignContributorDto(user, 'Editor', true); + const requestDto = { contributorId: user, role: 'Editor', invite: true }; this.contributorsState.assign(requestDto) .subscribe(isCreated => { @@ -111,7 +110,7 @@ export class ContributorsPageComponent implements OnInit { } } - public trackByContributor(index: number, contributorInfo: { contributor: AppContributorDto }) { + public trackByContributor(index: number, contributorInfo: { contributor: ContributorDto }) { return contributorInfo.contributor.contributorId; } } diff --git a/src/Squidex/app/features/settings/pages/languages/language.component.ts b/src/Squidex/app/features/settings/pages/languages/language.component.ts index 67da727e0..6d1ed36e1 100644 --- a/src/Squidex/app/features/settings/pages/languages/language.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/language.component.ts @@ -14,8 +14,7 @@ import { EditLanguageForm, fadeAnimation, ImmutableArray, - LanguagesState, - UpdateAppLanguageDto + LanguagesState } from '@app/shared'; @Component({ @@ -64,7 +63,7 @@ export class LanguageComponent implements OnChanges { const value = this.editForm.submit(); if (value) { - const request = new UpdateAppLanguageDto(value.isMaster, value.isOptional, this.fallbackLanguages.map(x => x.iso2Code).values); + const request = { ...value, fallbackLanguages: this.fallbackLanguages.map(x => x.iso2Code).values }; this.languagesState.update(this.language, request) .subscribe(() => { diff --git a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts index d37976ef0..8b02c9a52 100644 --- a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts @@ -10,8 +10,8 @@ import { FormBuilder } from '@angular/forms'; import { onErrorResumeNext } from 'rxjs/operators'; import { - AppPatternDto, EditPatternForm, + PatternDto, PatternsState } from '@app/shared'; @@ -22,7 +22,7 @@ import { }) export class PatternComponent implements OnInit { @Input() - public pattern: AppPatternDto; + public pattern: PatternDto; public editForm = new EditPatternForm(this.formBuilder); diff --git a/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts b/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts index 57db136ae..01ff48e92 100644 --- a/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts @@ -9,8 +9,8 @@ import { Component, OnInit } from '@angular/core'; import { onErrorResumeNext } from 'rxjs/operators'; import { - AppPatternDto, AppsState, + PatternDto, PatternsState } from '@app/shared'; @@ -34,7 +34,7 @@ export class PatternsPageComponent implements OnInit { this.patternsState.load(true).pipe(onErrorResumeNext()).subscribe(); } - public trackByPattern(index: number, pattern: AppPatternDto) { + public trackByPattern(index: number, pattern: PatternDto) { return pattern.id; } } \ No newline at end of file diff --git a/src/Squidex/app/features/settings/pages/roles/role.component.ts b/src/Squidex/app/features/settings/pages/roles/role.component.ts index 5c892da21..a0980abfc 100644 --- a/src/Squidex/app/features/settings/pages/roles/role.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/role.component.ts @@ -11,13 +11,12 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AddPermissionForm, - AppRoleDto, AutocompleteComponent, AutocompleteSource, EditPermissionsForm, fadeAnimation, - RolesState, - UpdateAppRoleDto + RoleDto, + RolesState } from '@app/shared'; const DEFAULT_ROLES = [ @@ -37,7 +36,7 @@ const DEFAULT_ROLES = [ }) export class RoleComponent implements OnChanges { @Input() - public role: AppRoleDto; + public role: RoleDto; @Input() public allPermissions: AutocompleteSource; @@ -95,7 +94,7 @@ export class RoleComponent implements OnChanges { const value = this.editForm.submit(); if (value) { - const request = new UpdateAppRoleDto(value); + const request = { permissions: value }; this.rolesState.update(this.role, request) .subscribe(() => { diff --git a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts index 0722c02ba..ddf0607e8 100644 --- a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts @@ -12,17 +12,17 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AddRoleForm, - AppRoleDto, - AppRolesService, AppsState, AutocompleteSource, + RoleDto, + RolesService, RolesState } from '@app/shared'; class PermissionsAutocomplete implements AutocompleteSource { private permissions: string[] = []; - constructor(appsState: AppsState, rolesService: AppRolesService) { + constructor(appsState: AppsState, rolesService: RolesService) { rolesService.getPermissions(appsState.appName).subscribe(x => this.permissions = x); } @@ -43,7 +43,7 @@ export class RolesPageComponent implements OnInit { constructor( public readonly appsState: AppsState, - public readonly rolesService: AppRolesService, + public readonly rolesService: RolesService, public readonly rolesState: RolesState, private readonly formBuilder: FormBuilder ) { @@ -74,7 +74,7 @@ export class RolesPageComponent implements OnInit { } } - public trackByRole(index: number, role: AppRoleDto) { + public trackByRole(index: number, role: RoleDto) { return role.name; } } diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index ae0ddfcb1..4a529406d 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -20,7 +20,7 @@ export interface FormState { error?: string | null; } -export class Form { +export class Form { private readonly state = new State({ submitted: false }); public submitted = @@ -42,21 +42,21 @@ export class Form { this.form.enable(); } - protected reset(value: any) { + protected reset(value: V | undefined) { this.form.reset(value); } - protected setValue(value: any) { + protected setValue(value: V | undefined) { this.form.reset(value, { emitEvent: true }); } - public load(value: any) { + public load(value: V | undefined) { this.state.next(_ => ({ submitted: false, error: null })); this.setValue(value); } - public submit(): any | null { + public submit(): V | null { this.state.next(_ => ({ submitted: true })); if (this.form.valid) { @@ -70,7 +70,7 @@ export class Form { } } - public submitCompleted(newValue?: any) { + public submitCompleted(newValue?: V) { this.state.next(_ => ({ submitted: false, error: null })); this.enable(); @@ -106,8 +106,8 @@ export class Model { return this.clone(value, validOnly); } - protected clone(update: ((v: any) => T) | Partial, validOnly = false): T { - let values: Partial; + protected clone(update: ((v: any) => V) | Partial, validOnly = false): V { + let values: Partial; if (Types.isFunction(update)) { values = update(this); } else { diff --git a/src/Squidex/app/shared/components/app-form.component.ts b/src/Squidex/app/shared/components/app-form.component.ts index 1b812a6c6..561db49cc 100644 --- a/src/Squidex/app/shared/components/app-form.component.ts +++ b/src/Squidex/app/shared/components/app-form.component.ts @@ -11,7 +11,6 @@ import { FormBuilder } from '@angular/forms'; import { ApiUrlConfig, AppsState, - CreateAppDto, CreateAppForm } from '@app/shared/internal'; @@ -45,7 +44,7 @@ export class AppFormComponent { const value = this.createForm.submit(); if (value) { - const request = new CreateAppDto(value.name, this.template); + const request = { ...value, template: this.template }; this.appsStore.create(request) .subscribe(() => { diff --git a/src/Squidex/app/shared/internal.ts b/src/Squidex/app/shared/internal.ts index 4508030d9..21a2aab51 100644 --- a/src/Squidex/app/shared/internal.ts +++ b/src/Squidex/app/shared/internal.ts @@ -19,14 +19,12 @@ export * from './guards/unset-content.guard'; export * from './interceptors/auth.interceptor'; -export * from './services/app-contributors.service'; -export * from './services/app-clients.service'; export * from './services/app-languages.service'; -export * from './services/app-patterns.service'; -export * from './services/app-roles.service'; export * from './services/apps.service'; export * from './services/assets.service'; export * from './services/auth.service'; +export * from './services/clients.service'; +export * from './services/contributors.service'; export * from './services/backups.service'; export * from './services/comments.service'; export * from './services/contents.service'; @@ -35,7 +33,9 @@ export * from './services/help.service'; export * from './services/history.service'; export * from './services/languages.service'; export * from './services/news.service'; +export * from './services/patterns.service'; export * from './services/plans.service'; +export * from './services/roles.service'; export * from './services/rules.service'; export * from './services/schemas.service'; export * from './services/schemas.types'; diff --git a/src/Squidex/app/shared/module.ts b/src/Squidex/app/shared/module.ts index 51d794428..044ad2167 100644 --- a/src/Squidex/app/shared/module.ts +++ b/src/Squidex/app/shared/module.ts @@ -13,13 +13,9 @@ import { DndModule } from 'ng2-dnd'; import { SqxFrameworkModule } from '@app/framework'; import { - AppClientsService, - AppContributorsService, AppFormComponent, AppLanguagesService, AppMustExistGuard, - AppPatternsService, - AppRolesService, AppsService, AppsState, AssetComponent, @@ -35,6 +31,7 @@ import { AuthService, BackupsService, BackupsState, + ClientsService, ClientsState, CommentComponent, CommentsComponent, @@ -42,6 +39,7 @@ import { ContentMustExistGuard, ContentsService, ContentsState, + ContributorsService, ContributorsState, FileIconPipe, GeolocationEditorComponent, @@ -62,11 +60,13 @@ import { MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, NewsService, + PatternsService, PatternsState, PermissionDirective, PlansService, PlansState, RichEditorComponent, + RolesService, RolesState, RuleEventsState, RulesService, @@ -173,12 +173,12 @@ export class SqxSharedModule { return { ngModule: SqxSharedModule, providers: [ - AppClientsService, - AppContributorsService, + ClientsService, + ContributorsService, AppLanguagesService, AppMustExistGuard, - AppPatternsService, - AppRolesService, + PatternsService, + RolesService, AppsService, AppsState, AssetsState, diff --git a/src/Squidex/app/shared/services/app-languages.service.ts b/src/Squidex/app/shared/services/app-languages.service.ts index 8cd281d7c..5a83f059e 100644 --- a/src/Squidex/app/shared/services/app-languages.service.ts +++ b/src/Squidex/app/shared/services/app-languages.service.ts @@ -73,8 +73,8 @@ export class AppLanguagesService { return new AppLanguageDto( item.iso2Code, item.englishName, - item.isMaster === true, - item.isOptional === true, + item.isMaster, + item.isOptional, item.fallback || []); }); @@ -93,8 +93,8 @@ export class AppLanguagesService { const language = new AppLanguageDto( body.iso2Code, body.englishName, - body.isMaster === true, - body.isOptional === true, + body.isMaster, + body.isOptional, body.fallback || []); return new Versioned(response.version, language); diff --git a/src/Squidex/app/shared/services/assets.service.spec.ts b/src/Squidex/app/shared/services/assets.service.spec.ts index 16709cc4f..6c32b85d4 100644 --- a/src/Squidex/app/shared/services/assets.service.spec.ts +++ b/src/Squidex/app/shared/services/assets.service.spec.ts @@ -35,7 +35,7 @@ describe('AssetDto', () => { const asset_1 = new AssetDto('1', creator, creator, creation, creation, 'Name.png', 'Hash', 'png', 1, 1, 'image/png', false, false, 1, 1, 'name.png', [], 'url', version); const asset_2 = asset_1.annnotate(update, modifier, newVersion, modified); - expect(asset_2.fileName).toEqual('NewName.png'); + expect(asset_2.fileName).toEqual(update.fileName); expect(asset_2.tags).toEqual([]); expect(asset_2.slug).toEqual(asset_1.slug); expect(asset_2.lastModified).toEqual(modified); @@ -44,18 +44,26 @@ describe('AssetDto', () => { }); it('should update file properties when uploading', () => { - const update = new AssetReplacedDto('Hash New', 2, 2, 'image/jpeg', true, 2, 2); + const update = { + fileHash: 'Hash New', + fileSize: 1024, + fileVersion: 12, + mimeType: 'image/png', + isImage: true, + pixelWidth: 1024, + pixelHeight: 2048 + }; const asset_1 = new AssetDto('1', creator, creator, creation, creation, 'Name.png', 'Hash', 'png', 1, 1, 'image/png', false, false, 1, 1, 'name.png', [], 'url', version); const asset_2 = asset_1.update(update, modifier, newVersion, modified); - expect(asset_2.fileHash).toEqual('Hash New'); - expect(asset_2.fileSize).toEqual(2); - expect(asset_2.fileVersion).toEqual(2); - expect(asset_2.mimeType).toEqual('image/jpeg'); + expect(asset_2.fileHash).toEqual(update.fileHash); + expect(asset_2.fileSize).toEqual(update.fileSize); + expect(asset_2.fileVersion).toEqual(update.fileVersion); + expect(asset_2.mimeType).toEqual(update.mimeType); expect(asset_2.isImage).toBeTruthy(); - expect(asset_2.pixelWidth).toEqual(2); - expect(asset_2.pixelHeight).toEqual(2); + expect(asset_2.pixelWidth).toEqual(update.pixelWidth); + expect(asset_2.pixelHeight).toEqual(update.pixelHeight); expect(asset_2.lastModified).toEqual(modified); expect(asset_2.lastModifiedBy).toEqual(modifier); expect(asset_2.version).toEqual(newVersion); @@ -407,15 +415,15 @@ describe('AssetsService', () => { pixelHeight: 2048 }); - expect(asset!).toEqual( - new AssetReplacedDto( - 'Hash New', - 1024, - 12, - 'image/png', - true, - 1024, - 2048)); + expect(asset!).toEqual({ + fileHash: 'Hash New', + fileSize: 1024, + fileVersion: 12, + mimeType: 'image/png', + isImage: true, + pixelWidth: 1024, + pixelHeight: 2048 + }); })); it('should return proper error when replace failed with 413', diff --git a/src/Squidex/app/shared/services/assets.service.ts b/src/Squidex/app/shared/services/assets.service.ts index eb8b5d3ff..d5ac43806 100644 --- a/src/Squidex/app/shared/services/assets.service.ts +++ b/src/Squidex/app/shared/services/assets.service.ts @@ -56,7 +56,7 @@ export class AssetDto extends Model { } public update(update: AssetReplacedDto, user: string, version: Version, now?: DateTime): AssetDto { - return this.clone({ + return this.with({ ...update, lastModified: now || DateTime.now(), lastModifiedBy: user, @@ -65,7 +65,7 @@ export class AssetDto extends Model { } public annnotate(update: AnnotateAssetDto, user: string, version: Version, now?: DateTime): AssetDto { - return this.clone({ + return this.with({ ...update, lastModified: now || DateTime.now(), lastModifiedBy: user, diff --git a/src/Squidex/app/shared/services/app-clients.service.spec.ts b/src/Squidex/app/shared/services/clients.service.spec.ts similarity index 68% rename from src/Squidex/app/shared/services/app-clients.service.spec.ts rename to src/Squidex/app/shared/services/clients.service.spec.ts index c1179f696..14ced0b32 100644 --- a/src/Squidex/app/shared/services/app-clients.service.spec.ts +++ b/src/Squidex/app/shared/services/clients.service.spec.ts @@ -12,13 +12,13 @@ import { AccessTokenDto, AnalyticsService, ApiUrlConfig, - AppClientDto, - AppClientsDto, - AppClientsService, + ClientDto, + ClientsDto, + ClientsService, Version } from './../'; -describe('AppClientsService', () => { +describe('ClientsService', () => { const version = new Version('1'); beforeEach(() => { @@ -27,7 +27,7 @@ describe('AppClientsService', () => { HttpClientTestingModule ], providers: [ - AppClientsService, + ClientsService, { provide: ApiUrlConfig, useValue: new ApiUrlConfig('http://service/p/') }, { provide: AnalyticsService, useValue: new AnalyticsService() } ] @@ -39,11 +39,11 @@ describe('AppClientsService', () => { })); it('should make get request to get app clients', - inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { + inject([ClientsService, HttpTestingController], (clientsService: ClientsService, httpMock: HttpTestingController) => { - let clients: AppClientsDto; + let clients: ClientsDto; - appClientsService.getClients('my-app').subscribe(result => { + clientsService.getClients('my-app').subscribe(result => { clients = result; }); @@ -72,20 +72,20 @@ describe('AppClientsService', () => { }); expect(clients!).toEqual( - new AppClientsDto([ - new AppClientDto('client1', 'Client 1', 'secret1', 'Editor'), - new AppClientDto('client2', 'Client 2', 'secret2', 'Developer') + new ClientsDto([ + new ClientDto('client1', 'Client 1', 'secret1', 'Editor'), + new ClientDto('client2', 'Client 2', 'secret2', 'Developer') ], new Version('2'))); })); it('should make post request to create client', - inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { + inject([ClientsService, HttpTestingController], (clientsService: ClientsService, httpMock: HttpTestingController) => { const dto = { id: 'client1' }; - let client: AppClientDto; + let client: ClientDto; - appClientsService.postClient('my-app', dto, version).subscribe(result => { + clientsService.postClient('my-app', dto, version).subscribe(result => { client = result.payload; }); @@ -96,15 +96,15 @@ describe('AppClientsService', () => { req.flush({ id: 'client1', name: 'Client 1', secret: 'secret1', role: 'Developer' }); - expect(client!).toEqual(new AppClientDto('client1', 'Client 1', 'secret1', 'Developer')); + expect(client!).toEqual(new ClientDto('client1', 'Client 1', 'secret1', 'Developer')); })); it('should make put request to rename client', - inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { + inject([ClientsService, HttpTestingController], (clientsService: ClientsService, httpMock: HttpTestingController) => { const dto = { name: 'New Name' }; - appClientsService.putClient('my-app', 'client1', dto, version).subscribe(); + clientsService.putClient('my-app', 'client1', dto, version).subscribe(); const req = httpMock.expectOne('http://service/p/api/apps/my-app/clients/client1'); @@ -115,9 +115,9 @@ describe('AppClientsService', () => { })); it('should make delete request to remove client', - inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { + inject([ClientsService, HttpTestingController], (clientsService: ClientsService, httpMock: HttpTestingController) => { - appClientsService.deleteClient('my-app', 'client1', version).subscribe(); + clientsService.deleteClient('my-app', 'client1', version).subscribe(); const req = httpMock.expectOne('http://service/p/api/apps/my-app/clients/client1'); @@ -128,11 +128,11 @@ describe('AppClientsService', () => { })); it('should make form request to create token', - inject([AppClientsService, HttpTestingController], (appClientsService: AppClientsService, httpMock: HttpTestingController) => { + inject([ClientsService, HttpTestingController], (clientsService: ClientsService, httpMock: HttpTestingController) => { let accessTokenDto: AccessTokenDto; - appClientsService.createToken('my-app', new AppClientDto('myClientId', 'myClient', 'mySecret', 'Editor')).subscribe(result => { + clientsService.createToken('my-app', new ClientDto('myClientId', 'myClient', 'mySecret', 'Editor')).subscribe(result => { accessTokenDto = result; }); diff --git a/src/Squidex/app/shared/services/app-clients.service.ts b/src/Squidex/app/shared/services/clients.service.ts similarity index 82% rename from src/Squidex/app/shared/services/app-clients.service.ts rename to src/Squidex/app/shared/services/clients.service.ts index 36507531d..396e3182e 100644 --- a/src/Squidex/app/shared/services/app-clients.service.ts +++ b/src/Squidex/app/shared/services/clients.service.ts @@ -20,16 +20,16 @@ import { Versioned } from '@app/framework'; -export class AppClientsDto extends Model { +export class ClientsDto extends Model { constructor( - public readonly clients: AppClientDto[], + public readonly clients: ClientDto[], public readonly version: Version ) { super(); } } -export class AppClientDto extends Model { +export class ClientDto extends Model { constructor( public readonly id: string, public readonly name: string, @@ -48,17 +48,17 @@ export class AccessTokenDto { } } -export interface CreateAppClientDto { +export interface CreateClientDto { readonly id: string; } -export interface UpdateAppClientDto { +export interface UpdateClientDto { readonly name?: string; readonly role?: string; } @Injectable() -export class AppClientsService { +export class ClientsService { constructor( private readonly http: HttpClient, private readonly apiUrl: ApiUrlConfig, @@ -66,7 +66,7 @@ export class AppClientsService { ) { } - public getClients(appName: string): Observable { + public getClients(appName: string): Observable { const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`); return HTTP.getVersioned(this.http, url).pipe( @@ -76,26 +76,26 @@ export class AppClientsService { const items: any[] = body; const clients = items.map(item => { - return new AppClientDto( + return new ClientDto( item.id, item.name || body.id, item.secret, item.role); }); - return new AppClientsDto(clients, response.version); + return new ClientsDto(clients, response.version); }), pretifyError('Failed to load clients. Please reload.')); } - public postClient(appName: string, dto: CreateAppClientDto, version: Version): Observable> { + public postClient(appName: string, dto: CreateClientDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`); return HTTP.postVersioned(this.http, url, dto, version).pipe( map(response => { const body = response.payload.body; - const client = new AppClientDto( + const client = new ClientDto( body.id, body.name || body.id, body.secret, @@ -109,7 +109,7 @@ export class AppClientsService { pretifyError('Failed to add client. Please reload.')); } - public putClient(appName: string, id: string, dto: UpdateAppClientDto, version: Version): Observable> { + public putClient(appName: string, id: string, dto: UpdateClientDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients/${id}`); return HTTP.putVersioned(this.http, url, dto, version).pipe( @@ -129,7 +129,7 @@ export class AppClientsService { pretifyError('Failed to revoke client. Please reload.')); } - public createToken(appName: string, client: AppClientDto): Observable { + public createToken(appName: string, client: ClientDto): Observable { const options = { headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded', 'NoAuth': 'true' diff --git a/src/Squidex/app/shared/services/app-contributors.service.spec.ts b/src/Squidex/app/shared/services/contributors.service.spec.ts similarity index 71% rename from src/Squidex/app/shared/services/app-contributors.service.spec.ts rename to src/Squidex/app/shared/services/contributors.service.spec.ts index 084240dfe..502e753a5 100644 --- a/src/Squidex/app/shared/services/app-contributors.service.spec.ts +++ b/src/Squidex/app/shared/services/contributors.service.spec.ts @@ -11,14 +11,14 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, ApiUrlConfig, - AppContributorDto, - AppContributorsDto, - AppContributorsService, ContributorAssignedDto, + ContributorDto, + ContributorsDto, + ContributorsService, Version } from './../'; -describe('AppContributorsService', () => { +describe('ContributorsService', () => { const version = new Version('1'); beforeEach(() => { @@ -27,7 +27,7 @@ describe('AppContributorsService', () => { HttpClientTestingModule ], providers: [ - AppContributorsService, + ContributorsService, { provide: ApiUrlConfig, useValue: new ApiUrlConfig('http://service/p/') }, { provide: AnalyticsService, useValue: new AnalyticsService() } ] @@ -39,11 +39,11 @@ describe('AppContributorsService', () => { })); it('should make get request to get app contributors', - inject([AppContributorsService, HttpTestingController], (appContributorsService: AppContributorsService, httpMock: HttpTestingController) => { + inject([ContributorsService, HttpTestingController], (contributorsService: ContributorsService, httpMock: HttpTestingController) => { - let contributors: AppContributorsDto; + let contributors: ContributorsDto; - appContributorsService.getContributors('my-app').subscribe(result => { + contributorsService.getContributors('my-app').subscribe(result => { contributors = result; }); @@ -71,20 +71,20 @@ describe('AppContributorsService', () => { }); expect(contributors!).toEqual( - new AppContributorsDto([ - new AppContributorDto('123', 'Owner'), - new AppContributorDto('456', 'Owner') + new ContributorsDto([ + new ContributorDto('123', 'Owner'), + new ContributorDto('456', 'Owner') ], 100, new Version('2'))); })); it('should make post request to assign contributor', - inject([AppContributorsService, HttpTestingController], (appContributorsService: AppContributorsService, httpMock: HttpTestingController) => { + inject([ContributorsService, HttpTestingController], (contributorsService: ContributorsService, httpMock: HttpTestingController) => { const dto = { contributorId: '123', role: 'Owner' }; let contributorAssignedDto: ContributorAssignedDto; - appContributorsService.postContributor('my-app', dto, version).subscribe(result => { + contributorsService.postContributor('my-app', dto, version).subscribe(result => { contributorAssignedDto = result.payload; }); @@ -99,9 +99,9 @@ describe('AppContributorsService', () => { })); it('should make delete request to remove contributor', - inject([AppContributorsService, HttpTestingController], (appContributorsService: AppContributorsService, httpMock: HttpTestingController) => { + inject([ContributorsService, HttpTestingController], (contributorsService: ContributorsService, httpMock: HttpTestingController) => { - appContributorsService.deleteContributor('my-app', '123', version).subscribe(); + contributorsService.deleteContributor('my-app', '123', version).subscribe(); const req = httpMock.expectOne('http://service/p/api/apps/my-app/contributors/123'); diff --git a/src/Squidex/app/shared/services/app-contributors.service.ts b/src/Squidex/app/shared/services/contributors.service.ts similarity index 87% rename from src/Squidex/app/shared/services/app-contributors.service.ts rename to src/Squidex/app/shared/services/contributors.service.ts index ddf3edd6c..94c9b0f22 100644 --- a/src/Squidex/app/shared/services/app-contributors.service.ts +++ b/src/Squidex/app/shared/services/contributors.service.ts @@ -20,9 +20,9 @@ import { Versioned } from '@app/framework'; -export class AppContributorsDto extends Model { +export class ContributorsDto extends Model { constructor( - public readonly contributors: AppContributorDto[], + public readonly contributors: ContributorDto[], public readonly maxContributors: number, public readonly version: Version ) { @@ -30,7 +30,7 @@ export class AppContributorsDto extends Model { } } -export class AppContributorDto extends Model { +export class ContributorDto extends Model { constructor( public readonly contributorId: string, public readonly role: string @@ -51,7 +51,7 @@ export interface AssignContributorDto { } @Injectable() -export class AppContributorsService { +export class ContributorsService { constructor( private readonly http: HttpClient, private readonly apiUrl: ApiUrlConfig, @@ -59,7 +59,7 @@ export class AppContributorsService { ) { } - public getContributors(appName: string): Observable { + public getContributors(appName: string): Observable { const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors`); return HTTP.getVersioned(this.http, url).pipe( @@ -68,9 +68,9 @@ export class AppContributorsService { const items: any[] = body.contributors; - return new AppContributorsDto( + return new ContributorsDto( items.map(item => { - return new AppContributorDto( + return new ContributorDto( item.contributorId, item.role); }), diff --git a/src/Squidex/app/shared/services/help.service.spec.ts b/src/Squidex/app/shared/services/help.service.spec.ts index b3cc4552a..29891a4a3 100644 --- a/src/Squidex/app/shared/services/help.service.spec.ts +++ b/src/Squidex/app/shared/services/help.service.spec.ts @@ -10,7 +10,7 @@ import { inject, TestBed } from '@angular/core/testing'; import { HelpService } from './../'; -describe('AppClientsService', () => { +describe('ClientsService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ diff --git a/src/Squidex/app/shared/services/app-patterns.service.spec.ts b/src/Squidex/app/shared/services/patterns.service.spec.ts similarity index 75% rename from src/Squidex/app/shared/services/app-patterns.service.spec.ts rename to src/Squidex/app/shared/services/patterns.service.spec.ts index 43b1b8e95..e98ba43a2 100644 --- a/src/Squidex/app/shared/services/app-patterns.service.spec.ts +++ b/src/Squidex/app/shared/services/patterns.service.spec.ts @@ -11,13 +11,13 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, ApiUrlConfig, - AppPatternDto, - AppPatternsDto, - AppPatternsService, + PatternDto, + PatternsDto, + PatternsService, Version } from './../'; -describe('AppPatternsService', () => { +describe('PatternsService', () => { const version = new Version('1'); beforeEach(() => { @@ -26,7 +26,7 @@ describe('AppPatternsService', () => { HttpClientTestingModule ], providers: [ - AppPatternsService, + PatternsService, { provide: ApiUrlConfig, useValue: new ApiUrlConfig('http://service/p/') }, { provide: AnalyticsService, useValue: new AnalyticsService() } ] @@ -38,9 +38,9 @@ describe('AppPatternsService', () => { })); it('should make get request to get patterns', - inject([AppPatternsService, HttpTestingController], (patternService: AppPatternsService, httpMock: HttpTestingController) => { + inject([PatternsService, HttpTestingController], (patternService: PatternsService, httpMock: HttpTestingController) => { - let patterns: AppPatternsDto; + let patterns: PatternsDto; patternService.getPatterns('my-app').subscribe(result => { patterns = result; @@ -70,18 +70,18 @@ describe('AppPatternsService', () => { }); expect(patterns!).toEqual( - new AppPatternsDto([ - new AppPatternDto('1', 'Number', '[0-9]', 'Message1'), - new AppPatternDto('2', 'Numbers', '[0-9]*', 'Message2') + new PatternsDto([ + new PatternDto('1', 'Number', '[0-9]', 'Message1'), + new PatternDto('2', 'Numbers', '[0-9]*', 'Message2') ], new Version('2'))); })); it('should make post request to add pattern', - inject([AppPatternsService, HttpTestingController], (patternService: AppPatternsService, httpMock: HttpTestingController) => { + inject([PatternsService, HttpTestingController], (patternService: PatternsService, httpMock: HttpTestingController) => { const dto = { name: 'Number', pattern: '[0-9]' }; - let pattern: AppPatternDto; + let pattern: PatternDto; patternService.postPattern('my-app', dto, version).subscribe(result => { pattern = result.payload; @@ -99,11 +99,11 @@ describe('AppPatternsService', () => { message: 'Message1' }); - expect(pattern!).toEqual(new AppPatternDto('1', 'Number', '[0-9]', 'Message1')); + expect(pattern!).toEqual(new PatternDto('1', 'Number', '[0-9]', 'Message1')); })); it('should make put request to update pattern', - inject([AppPatternsService, HttpTestingController], (patternService: AppPatternsService, httpMock: HttpTestingController) => { + inject([PatternsService, HttpTestingController], (patternService: PatternsService, httpMock: HttpTestingController) => { const dto = { name: 'Number', pattern: '[0-9]' }; @@ -118,7 +118,7 @@ describe('AppPatternsService', () => { })); it('should make delete request to remove pattern', - inject([AppPatternsService, HttpTestingController], (patternService: AppPatternsService, httpMock: HttpTestingController) => { + inject([PatternsService, HttpTestingController], (patternService: PatternsService, httpMock: HttpTestingController) => { patternService.deletePattern('my-app', '1', version).subscribe(); diff --git a/src/Squidex/app/shared/services/app-patterns.service.ts b/src/Squidex/app/shared/services/patterns.service.ts similarity index 81% rename from src/Squidex/app/shared/services/app-patterns.service.ts rename to src/Squidex/app/shared/services/patterns.service.ts index d2ce8969c..209c93ede 100644 --- a/src/Squidex/app/shared/services/app-patterns.service.ts +++ b/src/Squidex/app/shared/services/patterns.service.ts @@ -20,16 +20,16 @@ import { Versioned } from '@app/framework'; -export class AppPatternsDto extends Model { +export class PatternsDto extends Model { constructor( - public readonly patterns: AppPatternDto[], + public readonly patterns: PatternDto[], public readonly version: Version ) { super(); } } -export class AppPatternDto extends Model { +export class PatternDto extends Model { constructor( public readonly id: string, public readonly name: string, @@ -40,14 +40,14 @@ export class AppPatternDto extends Model { } } -export interface EditAppPatternDto { +export interface EditPatternDto { readonly name: string; readonly pattern: string; readonly message?: string; } @Injectable() -export class AppPatternsService { +export class PatternsService { constructor( private readonly http: HttpClient, private readonly apiUrl: ApiUrlConfig, @@ -55,7 +55,7 @@ export class AppPatternsService { ) { } - public getPatterns(appName: string): Observable { + public getPatterns(appName: string): Observable { const url = this.apiUrl.buildUrl(`api/apps/${appName}/patterns`); return HTTP.getVersioned(this.http, url).pipe( @@ -64,9 +64,9 @@ export class AppPatternsService { const items: any[] = body; - return new AppPatternsDto( + return new PatternsDto( items.map(item => { - return new AppPatternDto( + return new PatternDto( item.patternId, item.name, item.pattern, @@ -77,14 +77,14 @@ export class AppPatternsService { pretifyError('Failed to add pattern. Please reload.')); } - public postPattern(appName: string, dto: EditAppPatternDto, version: Version): Observable> { + public postPattern(appName: string, dto: EditPatternDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/patterns`); return HTTP.postVersioned(this.http, url, dto, version).pipe( map(response => { const body = response.payload.body; - const pattern = new AppPatternDto( + const pattern = new PatternDto( body.patternId, body.name, body.pattern, @@ -98,7 +98,7 @@ export class AppPatternsService { pretifyError('Failed to add pattern. Please reload.')); } - public putPattern(appName: string, id: string, dto: EditAppPatternDto, version: Version): Observable> { + public putPattern(appName: string, id: string, dto: EditPatternDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/patterns/${id}`); return HTTP.putVersioned(this.http, url, dto, version).pipe( diff --git a/src/Squidex/app/shared/services/app-roles.service.spec.ts b/src/Squidex/app/shared/services/roles.service.spec.ts similarity index 77% rename from src/Squidex/app/shared/services/app-roles.service.spec.ts rename to src/Squidex/app/shared/services/roles.service.spec.ts index 35979140b..cf64c4d0b 100644 --- a/src/Squidex/app/shared/services/app-roles.service.spec.ts +++ b/src/Squidex/app/shared/services/roles.service.spec.ts @@ -11,13 +11,13 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, ApiUrlConfig, - AppRoleDto, - AppRolesDto, - AppRolesService, + RoleDto, + RolesDto, + RolesService, Version } from './../'; -describe('AppRolesService', () => { +describe('RolesService', () => { const version = new Version('1'); beforeEach(() => { @@ -26,7 +26,7 @@ describe('AppRolesService', () => { HttpClientTestingModule ], providers: [ - AppRolesService, + RolesService, { provide: ApiUrlConfig, useValue: new ApiUrlConfig('http://service/p/') }, { provide: AnalyticsService, useValue: new AnalyticsService() } ] @@ -38,7 +38,7 @@ describe('AppRolesService', () => { })); it('should make get request to get all permissions', - inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { + inject([RolesService, HttpTestingController], (roleService: RolesService, httpMock: HttpTestingController) => { let permissions: string[]; @@ -57,9 +57,9 @@ describe('AppRolesService', () => { })); it('should make get request to get roles', - inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { + inject([RolesService, HttpTestingController], (roleService: RolesService, httpMock: HttpTestingController) => { - let roles: AppRolesDto; + let roles: RolesDto; roleService.getRoles('my-app').subscribe(result => { roles = result; @@ -89,19 +89,19 @@ describe('AppRolesService', () => { }); expect(roles!).toEqual( - new AppRolesDto([ - new AppRoleDto('Role1', 3, 5, ['P1']), - new AppRoleDto('Role2', 7, 9, ['P2']) + new RolesDto([ + new RoleDto('Role1', 3, 5, ['P1']), + new RoleDto('Role2', 7, 9, ['P2']) ], new Version('2'))); })); it('should make post request to add role', - inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { + inject([RolesService, HttpTestingController], (roleService: RolesService, httpMock: HttpTestingController) => { const dto = { name: 'Role3' }; - let role: AppRoleDto; + let role: RoleDto; roleService.postRole('my-app', dto, version).subscribe(result => { role = result.payload; @@ -114,11 +114,11 @@ describe('AppRolesService', () => { req.flush({}); - expect(role!).toEqual(new AppRoleDto('Role3', 0, 0, [])); + expect(role!).toEqual(new RoleDto('Role3', 0, 0, [])); })); it('should make put request to update role', - inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { + inject([RolesService, HttpTestingController], (roleService: RolesService, httpMock: HttpTestingController) => { const dto = { permissions: ['P4', 'P5'] }; @@ -133,7 +133,7 @@ describe('AppRolesService', () => { })); it('should make delete request to remove role', - inject([AppRolesService, HttpTestingController], (roleService: AppRolesService, httpMock: HttpTestingController) => { + inject([RolesService, HttpTestingController], (roleService: RolesService, httpMock: HttpTestingController) => { roleService.deleteRole('my-app', 'role1', version).subscribe(); diff --git a/src/Squidex/app/shared/services/app-roles.service.ts b/src/Squidex/app/shared/services/roles.service.ts similarity index 81% rename from src/Squidex/app/shared/services/app-roles.service.ts rename to src/Squidex/app/shared/services/roles.service.ts index 008fd47fd..e45ce027c 100644 --- a/src/Squidex/app/shared/services/app-roles.service.ts +++ b/src/Squidex/app/shared/services/roles.service.ts @@ -20,16 +20,16 @@ import { Versioned } from '@app/framework'; -export class AppRolesDto extends Model { +export class RolesDto extends Model { constructor( - public readonly roles: AppRoleDto[], + public readonly roles: RoleDto[], public readonly version: Version ) { super(); } } -export class AppRoleDto extends Model { +export class RoleDto extends Model { constructor( public readonly name: string, public readonly numClients: number, @@ -40,16 +40,16 @@ export class AppRoleDto extends Model { } } -export interface CreateAppRoleDto { +export interface CreateRoleDto { readonly name: string; } -export interface UpdateAppRoleDto { +export interface UpdateRoleDto { readonly permissions: string[]; } @Injectable() -export class AppRolesService { +export class RolesService { constructor( private readonly http: HttpClient, private readonly apiUrl: ApiUrlConfig, @@ -57,7 +57,7 @@ export class AppRolesService { ) { } - public getRoles(appName: string): Observable { + public getRoles(appName: string): Observable { const url = this.apiUrl.buildUrl(`api/apps/${appName}/roles`); return HTTP.getVersioned(this.http, url).pipe( @@ -67,24 +67,24 @@ export class AppRolesService { const items: any[] = body.roles; const roles = items.map(item => { - return new AppRoleDto( + return new RoleDto( item.name, item.numClients, item.numContributors, item.permissions); }); - return new AppRolesDto(roles, response.version); + return new RolesDto(roles, response.version); }), pretifyError('Failed to load roles. Please reload.')); } - public postRole(appName: string, dto: CreateAppRoleDto, version: Version): Observable> { + public postRole(appName: string, dto: CreateRoleDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/roles`); return HTTP.postVersioned(this.http, url, dto, version).pipe( map(response => { - const role = new AppRoleDto(dto.name, 0, 0, []); + const role = new RoleDto(dto.name, 0, 0, []); return new Versioned(response.version, role); }), @@ -94,7 +94,7 @@ export class AppRolesService { pretifyError('Failed to add role. Please reload.')); } - public putRole(appName: string, name: string, dto: UpdateAppRoleDto, version: Version): Observable> { + public putRole(appName: string, name: string, dto: UpdateRoleDto, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/roles/${name}`); return HTTP.putVersioned(this.http, url, dto, version).pipe( diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index d6ea001bd..6bfd583e4 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -48,7 +48,9 @@ describe('SchemasService', () => { })); it('should throw if creating invalid property type', () => { - expect(() => createProperties('invalid')).toThrow('Invalid properties type'); + const type: any = 'invalid'; + + expect(() => createProperties(type)).toThrow('Invalid properties type'); }); it('should make get request to get schemas', @@ -417,7 +419,7 @@ describe('SchemasService', () => { const dto = new AddFieldDto('name', 'invariant', createProperties('Number')); - let field: FieldDto; + let field: FieldDto; schemasService.postField('my-app', 'my-schema', dto, undefined, version).subscribe(result => { field = result.payload; @@ -464,7 +466,7 @@ describe('SchemasService', () => { const dto = new AddFieldDto('name', 'invariant', createProperties('Number')); - let field: FieldDto; + let field: FieldDto; schemasService.postField('my-app', 'my-schema', dto, 13, version).subscribe(result => { field = result.payload; diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index e9248d2eb..863f9b95f 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -84,6 +84,10 @@ export class SchemaDetailsDto extends SchemaDto { this.listFieldsEditable = fields.filter(x => x.isInlineEditable); } } + + public with(value: Partial): SchemaDetailsDto { + return this.clone(value); + } } export class FieldDto extends Model { @@ -137,6 +141,10 @@ export class RootFieldDto extends FieldDto { ) { super(fieldId, name, properties, isLocked, isHidden, isDisabled); } + + public with(value: Partial): RootFieldDto { + return this.clone(value); + } } export class NestedFieldDto extends FieldDto { @@ -148,6 +156,10 @@ export class NestedFieldDto extends FieldDto { ) { super(fieldId, name, properties, isLocked, isHidden, isDisabled); } + + public with(value: Partial): NestedFieldDto { + return this.clone(value); + } } export class SchemaPropertiesDto { diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index f11706196..6462f20b7 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -9,10 +9,10 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppClientDto, - AppClientsDto, - AppClientsService, AppsState, + ClientDto, + ClientsDto, + ClientsService, ClientsState, DialogService, Version, @@ -25,13 +25,13 @@ describe('ClientsState', () => { const newVersion = new Version('2'); const oldClients = [ - new AppClientDto('id1', 'name1', 'secret1'), - new AppClientDto('id2', 'name2', 'secret2') + new ClientDto('id1', 'name1', 'secret1'), + new ClientDto('id2', 'name2', 'secret2') ]; let dialogs: IMock; let appsState: IMock; - let clientsService: IMock; + let clientsService: IMock; let clientsState: ClientsState; beforeEach(() => { @@ -42,10 +42,10 @@ describe('ClientsState', () => { appsState.setup(x => x.appName) .returns(() => app); - clientsService = Mock.ofType(); + clientsService = Mock.ofType(); clientsService.setup(x => x.getClients(app)) - .returns(() => of(new AppClientsDto(oldClients, version))); + .returns(() => of(new ClientsDto(oldClients, version))); clientsState = new ClientsState(clientsService.object, appsState.object, dialogs.object); clientsState.load().subscribe(); @@ -68,12 +68,12 @@ describe('ClientsState', () => { }); it('should add client to snapshot when created', () => { - const newClient = new AppClientDto('id3', 'name3', 'secret3'); + const newClient = new ClientDto('id3', 'name3', 'secret3'); const request = { id: 'id3' }; clientsService.setup(x => x.postClient(app, request, version)) - .returns(() => of(new Versioned(newVersion, newClient))); + .returns(() => of(new Versioned(newVersion, newClient))); clientsState.attach(request).subscribe(); diff --git a/src/Squidex/app/shared/state/clients.state.ts b/src/Squidex/app/shared/state/clients.state.ts index bc3ef18b5..5f3098169 100644 --- a/src/Squidex/app/shared/state/clients.state.ts +++ b/src/Squidex/app/shared/state/clients.state.ts @@ -20,15 +20,15 @@ import { import { AppsState } from './apps.state'; import { - AppClientDto, - AppClientsService, - CreateAppClientDto, - UpdateAppClientDto -} from './../services/app-clients.service'; + ClientDto, + ClientsService, + CreateClientDto, + UpdateClientDto +} from './../services/clients.service'; interface Snapshot { // The current clients. - clients: ImmutableArray; + clients: ImmutableArray; // The app version. version: Version; @@ -48,7 +48,7 @@ export class ClientsState extends State { distinctUntilChanged()); constructor( - private readonly appClientsService: AppClientsService, + private readonly clientsService: ClientsService, private readonly appsState: AppsState, private readonly dialogs: DialogService ) { @@ -60,7 +60,7 @@ export class ClientsState extends State { this.resetState(); } - return this.appClientsService.getClients(this.appName).pipe( + return this.clientsService.getClients(this.appName).pipe( tap(dtos => { if (isReload) { this.dialogs.notifyInfo('Clients reloaded.'); @@ -75,8 +75,8 @@ export class ClientsState extends State { notify(this.dialogs)); } - public attach(request: CreateAppClientDto): Observable { - return this.appClientsService.postClient(this.appName, request, this.version).pipe( + public attach(request: CreateClientDto): Observable { + return this.clientsService.postClient(this.appName, request, this.version).pipe( tap(dto => { this.next(s => { const clients = s.clients.push(dto.payload); @@ -87,8 +87,8 @@ export class ClientsState extends State { notify(this.dialogs)); } - public revoke(client: AppClientDto): Observable { - return this.appClientsService.deleteClient(this.appName, client.id, this.version).pipe( + public revoke(client: ClientDto): Observable { + return this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( tap(dto => { this.next(s => { const clients = s.clients.filter(c => c.id !== client.id); @@ -99,8 +99,8 @@ export class ClientsState extends State { notify(this.dialogs)); } - public update(client: AppClientDto, request: UpdateAppClientDto): Observable { - return this.appClientsService.putClient(this.appName, client.id, request, this.version).pipe( + public update(client: ClientDto, request: UpdateClientDto): Observable { + return this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( tap(dto => { this.next(s => { const clients = s.clients.replaceBy('id', update(client, request)); @@ -120,5 +120,5 @@ export class ClientsState extends State { } } -const update = (client: AppClientDto, request: UpdateAppClientDto) => +const update = (client: ClientDto, request: UpdateClientDto) => client.with({ name: request.name || client.name, role: request.role || client.role }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index 0c2893e95..b98051959 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -9,12 +9,12 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppContributorDto, - AppContributorsDto, - AppContributorsService, AppsState, AuthService, ContributorAssignedDto, + ContributorDto, + ContributorsDto, + ContributorsService, ContributorsState, DialogService, Version, @@ -27,14 +27,14 @@ describe('ContributorsState', () => { const newVersion = new Version('2'); const oldContributors = [ - new AppContributorDto('id1', 'Developer'), - new AppContributorDto('id2', 'Developer') + new ContributorDto('id1', 'Developer'), + new ContributorDto('id2', 'Developer') ]; let dialogs: IMock; let appsState: IMock; let authService: IMock; - let contributorsService: IMock; + let contributorsService: IMock; let contributorsState: ContributorsState; beforeEach(() => { @@ -50,10 +50,10 @@ describe('ContributorsState', () => { appsState.setup(x => x.appName) .returns(() => app); - contributorsService = Mock.ofType(); + contributorsService = Mock.ofType(); contributorsService.setup(x => x.getContributors(app)) - .returns(() => of(new AppContributorsDto(oldContributors, 3, version))); + .returns(() => of(new ContributorsDto(oldContributors, 3, version))); contributorsState = new ContributorsState(contributorsService.object, appsState.object, authService.object, dialogs.object); contributorsState.load().subscribe(); @@ -81,12 +81,12 @@ describe('ContributorsState', () => { }); it('should add contributor to snapshot when assigned', () => { - const newContributor = new AppContributorDto('id3', 'Developer'); + const newContributor = new ContributorDto('id3', 'Developer'); const request = { contributorId: 'mail2stehle@gmail.com', role: 'Developer' }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, new ContributorAssignedDto('id3', true)))); + .returns(() => of(new Versioned(newVersion, { contributorId: '123', isCreated: true }))); contributorsState.assign(request).subscribe(); @@ -101,12 +101,12 @@ describe('ContributorsState', () => { }); it('should update contributor in snapshot when assigned and already added', () => { - const newContributor = new AppContributorDto('id2', 'Owner'); + const newContributor = new ContributorDto('id2', 'Owner'); - const request = new AssignContributorDto('mail2stehle@gmail.com', 'Owner'); + const request = { ...newContributor }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, new ContributorAssignedDto('id2', true)))); + .returns(() => of(new Versioned(newVersion, { contributorId: '123', isCreated: true }))); contributorsState.assign(request).subscribe(); diff --git a/src/Squidex/app/shared/state/contributors.state.ts b/src/Squidex/app/shared/state/contributors.state.ts index 58034970b..4f8dbfff9 100644 --- a/src/Squidex/app/shared/state/contributors.state.ts +++ b/src/Squidex/app/shared/state/contributors.state.ts @@ -20,17 +20,17 @@ import { } from '@app/framework'; import { - AppContributorDto, - AppContributorsService, - AssignContributorDto -} from './../services/app-contributors.service'; + AssignContributorDto, + ContributorDto, + ContributorsService +} from './../services/contributors.service'; import { AuthService } from './../services/auth.service'; import { AppsState } from './apps.state'; interface SnapshotContributor { // The contributor. - contributor: AppContributorDto; + contributor: ContributorDto; // Indicates if the contributor is the ucrrent user. isCurrentUser: boolean; @@ -72,7 +72,7 @@ export class ContributorsState extends State { distinctUntilChanged()); constructor( - private readonly appContributorsService: AppContributorsService, + private readonly contributorsService: ContributorsService, private readonly appsState: AppsState, private readonly authState: AuthService, private readonly dialogs: DialogService @@ -85,7 +85,7 @@ export class ContributorsState extends State { this.resetState(); } - return this.appContributorsService.getContributors(this.appName).pipe( + return this.contributorsService.getContributors(this.appName).pipe( tap(dtos => { if (isReload) { this.dialogs.notifyInfo('Contributors reloaded.'); @@ -98,8 +98,8 @@ export class ContributorsState extends State { notify(this.dialogs)); } - public revoke(contributor: AppContributorDto): Observable { - return this.appContributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( + public revoke(contributor: ContributorDto): Observable { + return this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( tap(dto => { const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId); @@ -108,8 +108,8 @@ export class ContributorsState extends State { notify(this.dialogs)); } - public assign(request: AssignContributorDto): Observable { - return this.appContributorsService.postContributor(this.appName, request, this.version).pipe( + public assign(request: AssignContributorDto): Observable { + return this.contributorsService.postContributor(this.appName, request, this.version).pipe( map(dto => { const contributors = this.updateContributors(dto.payload.contributorId, request.role, dto.version); @@ -128,7 +128,7 @@ export class ContributorsState extends State { } private updateContributors(id: string, role: string, version: Version) { - const contributor = new AppContributorDto(id, role); + const contributor = new ContributorDto(id, role); const contributors = this.snapshot.contributors; if (contributors.find(x => x.contributor.contributorId === id)) { @@ -161,7 +161,7 @@ export class ContributorsState extends State { return this.snapshot.version; } - private createContributor(contributor: AppContributorDto, current?: SnapshotContributor): SnapshotContributor { + private createContributor(contributor: ContributorDto, current?: SnapshotContributor): SnapshotContributor { if (!contributor) { return null!; } else if (current && current.contributor === contributor) { diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index 583bd6ec8..60d6d5653 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -9,11 +9,11 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppPatternDto, - AppPatternsDto, - AppPatternsService, AppsState, DialogService, + PatternDto, + PatternsDto, + PatternsService, PatternsState, Version, Versioned @@ -25,13 +25,13 @@ describe('PatternsState', () => { const newVersion = new Version('2'); const oldPatterns = [ - new AppPatternDto('id1', 'name1', 'pattern1', ''), - new AppPatternDto('id2', 'name2', 'pattern2', '') + new PatternDto('id1', 'name1', 'pattern1', ''), + new PatternDto('id2', 'name2', 'pattern2', '') ]; let dialogs: IMock; let appsState: IMock; - let patternsService: IMock; + let patternsService: IMock; let patternsState: PatternsState; beforeEach(() => { @@ -42,10 +42,10 @@ describe('PatternsState', () => { appsState.setup(x => x.appName) .returns(() => app); - patternsService = Mock.ofType(); + patternsService = Mock.ofType(); patternsService.setup(x => x.getPatterns(app)) - .returns(() => of(new AppPatternsDto(oldPatterns, version))); + .returns(() => of(new PatternsDto(oldPatterns, version))); patternsState = new PatternsState(patternsService.object, appsState.object, dialogs.object); patternsState.load().subscribe(); @@ -67,12 +67,12 @@ describe('PatternsState', () => { }); it('should add pattern to snapshot when created', () => { - const newPattern = new AppPatternDto('id3', 'name3', 'pattern3', ''); + const newPattern = new PatternDto('id3', 'name3', 'pattern3', ''); const request = { ...newPattern }; patternsService.setup(x => x.postPattern(app, request, version)) - .returns(() => of(new Versioned(newVersion, newPattern))); + .returns(() => of(new Versioned(newVersion, newPattern))); patternsState.create(request).subscribe(); diff --git a/src/Squidex/app/shared/state/patterns.state.ts b/src/Squidex/app/shared/state/patterns.state.ts index 7673b50b8..4ae94204a 100644 --- a/src/Squidex/app/shared/state/patterns.state.ts +++ b/src/Squidex/app/shared/state/patterns.state.ts @@ -20,14 +20,14 @@ import { import { AppsState } from './apps.state'; import { - AppPatternDto, - AppPatternsService, - EditAppPatternDto -} from './../services/app-patterns.service'; + EditPatternDto, + PatternDto, + PatternsService +} from './../services/patterns.service'; interface Snapshot { // The current patterns. - patterns: ImmutableArray; + patterns: ImmutableArray; // The app version. version: Version; @@ -47,7 +47,7 @@ export class PatternsState extends State { distinctUntilChanged()); constructor( - private readonly appPatternsService: AppPatternsService, + private readonly patternsService: PatternsService, private readonly appsState: AppsState, private readonly dialogs: DialogService ) { @@ -59,7 +59,7 @@ export class PatternsState extends State { this.resetState(); } - return this.appPatternsService.getPatterns(this.appName).pipe( + return this.patternsService.getPatterns(this.appName).pipe( tap(dtos => { if (isReload) { this.dialogs.notifyInfo('Patterns reloaded.'); @@ -74,8 +74,8 @@ export class PatternsState extends State { notify(this.dialogs)); } - public create(request: EditAppPatternDto): Observable { - return this.appPatternsService.postPattern(this.appName, request, this.version).pipe( + public create(request: EditPatternDto): Observable { + return this.patternsService.postPattern(this.appName, request, this.version).pipe( tap(dto => { this.next(s => { const patterns = s.patterns.push(dto.payload).sortByStringAsc(x => x.name); @@ -86,8 +86,8 @@ export class PatternsState extends State { notify(this.dialogs)); } - public update(pattern: AppPatternDto, request: EditAppPatternDto): Observable { - return this.appPatternsService.putPattern(this.appName, pattern.id, request, this.version).pipe( + public update(pattern: PatternDto, request: EditPatternDto): Observable { + return this.patternsService.putPattern(this.appName, pattern.id, request, this.version).pipe( tap(dto => { this.next(s => { const patterns = s.patterns.replaceBy('id', update(pattern, request)).sortByStringAsc(x => x.name); @@ -98,8 +98,8 @@ export class PatternsState extends State { notify(this.dialogs)); } - public delete(pattern: AppPatternDto): Observable { - return this.appPatternsService.deletePattern(this.appName, pattern.id, this.version).pipe( + public delete(pattern: PatternDto): Observable { + return this.patternsService.deletePattern(this.appName, pattern.id, this.version).pipe( tap(dto => { this.next(s => { const patterns = s.patterns.filter(c => c.id !== pattern.id); @@ -119,5 +119,5 @@ export class PatternsState extends State { } } -const update = (pattern: AppPatternDto, request: EditAppPatternDto) => +const update = (pattern: PatternDto, request: EditPatternDto) => pattern.with(request); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index eb8c5f59b..69391e2dc 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -9,11 +9,11 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppRoleDto, - AppRolesDto, - AppRolesService, AppsState, DialogService, + RoleDto, + RolesDto, + RolesService, RolesState, Version, Versioned @@ -25,13 +25,13 @@ describe('RolesState', () => { const newVersion = new Version('2'); const oldRoles = [ - new AppRoleDto('Role1', 3, 5, ['P1']), - new AppRoleDto('Role2', 7, 9, ['P2']) + new RoleDto('Role1', 3, 5, ['P1']), + new RoleDto('Role2', 7, 9, ['P2']) ]; let dialogs: IMock; let appsState: IMock; - let rolesService: IMock; + let rolesService: IMock; let rolesState: RolesState; beforeEach(() => { @@ -42,10 +42,10 @@ describe('RolesState', () => { appsState.setup(x => x.appName) .returns(() => app); - rolesService = Mock.ofType(); + rolesService = Mock.ofType(); rolesService.setup(x => x.getRoles(app)) - .returns(() => of(new AppRolesDto(oldRoles, version))); + .returns(() => of(new RolesDto(oldRoles, version))); rolesState = new RolesState(rolesService.object, appsState.object, dialogs.object); rolesState.load().subscribe(); @@ -68,12 +68,12 @@ describe('RolesState', () => { }); it('should add role to snapshot when added', () => { - const newRole = new AppRoleDto('Role3', 0, 0, ['P3']); + const newRole = new RoleDto('Role3', 0, 0, ['P3']); const request = { name: newRole.name }; rolesService.setup(x => x.postRole(app, request, version)) - .returns(() => of(new Versioned(newVersion, newRole))); + .returns(() => of(new Versioned(newVersion, newRole))); rolesState.add(request).subscribe(); diff --git a/src/Squidex/app/shared/state/roles.state.ts b/src/Squidex/app/shared/state/roles.state.ts index b2f6b631b..276a5b505 100644 --- a/src/Squidex/app/shared/state/roles.state.ts +++ b/src/Squidex/app/shared/state/roles.state.ts @@ -20,15 +20,15 @@ import { import { AppsState } from './apps.state'; import { - AppRoleDto, - AppRolesService, - CreateAppRoleDto, - UpdateAppRoleDto -} from './../services/app-roles.service'; + CreateRoleDto, + RoleDto, + RolesService, + UpdateRoleDto +} from './../services/roles.service'; interface Snapshot { // The current roles. - roles: ImmutableArray; + roles: ImmutableArray; // The app version. version: Version; @@ -48,7 +48,7 @@ export class RolesState extends State { distinctUntilChanged()); constructor( - private readonly appRolesService: AppRolesService, + private readonly rolesService: RolesService, private readonly appsState: AppsState, private readonly dialogs: DialogService ) { @@ -60,7 +60,7 @@ export class RolesState extends State { this.resetState(); } - return this.appRolesService.getRoles(this.appName).pipe( + return this.rolesService.getRoles(this.appName).pipe( tap(dtos => { if (isReload) { this.dialogs.notifyInfo('Roles reloaded.'); @@ -75,8 +75,8 @@ export class RolesState extends State { notify(this.dialogs)); } - public add(request: CreateAppRoleDto): Observable { - return this.appRolesService.postRole(this.appName, request, this.version).pipe( + public add(request: CreateRoleDto): Observable { + return this.rolesService.postRole(this.appName, request, this.version).pipe( tap(dto => { this.next(s => { const roles = s.roles.push(dto.payload).sortByStringAsc(x => x.name); @@ -87,8 +87,8 @@ export class RolesState extends State { notify(this.dialogs)); } - public delete(role: AppRoleDto): Observable { - return this.appRolesService.deleteRole(this.appName, role.name, this.version).pipe( + public delete(role: RoleDto): Observable { + return this.rolesService.deleteRole(this.appName, role.name, this.version).pipe( tap(dto => { this.next(s => { const roles = s.roles.filter(c => c.name !== role.name); @@ -99,8 +99,8 @@ export class RolesState extends State { notify(this.dialogs)); } - public update(role: AppRoleDto, request: UpdateAppRoleDto): Observable { - return this.appRolesService.putRole(this.appName, role.name, request, this.version).pipe( + public update(role: RoleDto, request: UpdateRoleDto): Observable { + return this.rolesService.putRole(this.appName, role.name, request, this.version).pipe( tap(dto => { this.next(s => { const roles = s.roles.replaceBy('name', update(role, request)); @@ -120,5 +120,5 @@ export class RolesState extends State { } } -const update = (role: AppRoleDto, request: UpdateAppRoleDto) => +const update = (role: RoleDto, request: UpdateRoleDto) => role.with({ permissions: request.permissions }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 09cf0b43f..2624f51b8 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -23,9 +23,7 @@ import { SchemaDetailsDto, SchemaDto, SchemasService, - UpdateFieldDto, UpdateSchemaCategoryDto, - UpdateSchemaDto, Version, Versioned } from './../'; @@ -248,7 +246,7 @@ describe('SchemasState', () => { }); it('should update properties and update user info when updated', () => { - const request = new UpdateSchemaDto('name2_label', 'name2_hints'); + const request = { label: 'name2_label', hints: 'name2_hints' }; schemasService.setup(x => x.putSchema(app, schema.name, It.isAny(), version)) .returns(() => of(new Versioned(newVersion, {}))); @@ -257,8 +255,8 @@ describe('SchemasState', () => { const schema_1 = schemasState.snapshot.schemas.at(1); - expect(schema_1.properties.label).toEqual('name2_label'); - expect(schema_1.properties.hints).toEqual('name2_hints'); + expect(schema_1.properties.label).toEqual(request.label); + expect(schema_1.properties.hints).toEqual(request.hints); expectToBeModified(schema_1); }); @@ -395,7 +393,7 @@ describe('SchemasState', () => { }); it('should update field properties and update user info when field updated', () => { - const request = new UpdateFieldDto(createProperties('String')); + const request = { properties: createProperties('String') }; schemasService.setup(x => x.putField(app, schema.name, field1.fieldId, request, undefined, version)) .returns(() => of(new Versioned(newVersion, {}))); @@ -409,7 +407,7 @@ describe('SchemasState', () => { }); it('should update field properties and update user info when nested field updated', () => { - const request = new UpdateFieldDto(createProperties('String')); + const request = { properties: createProperties('String') }; schemasService.setup(x => x.putField(app, schema.name, nested1.fieldId, request, 2, version)) .returns(() => of(new Versioned(newVersion, {}))); diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index 900401b2c..34784c01a 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -33,7 +33,6 @@ import { SchemaPropertiesDto, SchemasService, UpdateFieldDto, - UpdateSchemaCategoryDto, UpdateSchemaDto } from './../services/schemas.service'; @@ -190,7 +189,7 @@ export class SchemasState extends State { } public changeCategory(schema: SchemaDto, name: string, now?: DateTime): Observable { - return this.schemasService.putCategory(this.appName, schema.name, new UpdateSchemaCategoryDto(name), schema.version).pipe( + return this.schemasService.putCategory(this.appName, schema.name, { name }, schema.version).pipe( tap(dto => { this.replaceSchema(changeCategory(schema, name, this.user, dto.version, now)); }), @@ -474,8 +473,8 @@ const setDisabled = (field: T, isDisabled: boolean) => const update = (field: T, properties: FieldPropertiesDto) => field.with({ properties }); -const pid = (field?: RootFieldDto) => - field ? field.fieldId : undefined; +const pidof = (field: T) => + Types.is(field, NestedFieldDto) ? field.parentId : undefined; -const pidof = (field: FieldDto) => - Types.is(field, NestedFieldDto) ? field.parentId : undefined; \ No newline at end of file +const pid = (field?: RootFieldDto) => + field ? field.fieldId : undefined; \ No newline at end of file From f805ae850cf5425522452de71267f3561d7af598 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 26 Apr 2019 17:58:57 +0200 Subject: [PATCH 03/20] More typed forms. --- .../pages/restore/restore-page.component.ts | 2 +- .../pages/users/user-page.component.ts | 3 +- .../administration/state/users.forms.ts | 26 ++------ .../pages/rules/rule-wizard.component.ts | 4 +- .../pages/schema/field-wizard.component.ts | 4 +- .../schema-preview-urls-form.component.ts | 4 +- .../pages/schemas/schema-form.component.ts | 2 +- .../pages/schemas/schemas-page.component.ts | 2 +- .../pages/clients/clients-page.component.ts | 2 +- .../contributors-page.component.ts | 2 +- .../pages/patterns/pattern.component.ts | 2 +- .../settings/pages/roles/role.component.ts | 2 +- .../pages/roles/roles-page.component.ts | 2 +- src/Squidex/app/framework/state.ts | 22 ++++--- .../shared/components/comments.component.ts | 2 +- .../shared/services/schemas.service.spec.ts | 4 +- src/Squidex/app/shared/state/apps.forms.ts | 2 +- src/Squidex/app/shared/state/assets.forms.ts | 4 +- src/Squidex/app/shared/state/backups.forms.ts | 6 +- src/Squidex/app/shared/state/clients.forms.ts | 4 +- src/Squidex/app/shared/state/comments.form.ts | 2 +- .../app/shared/state/contents.forms.ts | 6 +- .../app/shared/state/contributors.forms.ts | 4 +- .../app/shared/state/languages.forms.ts | 6 +- .../app/shared/state/patterns.forms.ts | 2 +- src/Squidex/app/shared/state/roles.forms.ts | 10 ++-- src/Squidex/app/shared/state/schemas.forms.ts | 60 +++++++++---------- 27 files changed, 93 insertions(+), 98 deletions(-) diff --git a/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts b/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts index c0f6304ab..e23671154 100644 --- a/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts +++ b/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts @@ -51,7 +51,7 @@ export class RestorePageComponent extends ResourceOwner implements OnInit { const value = this.restoreForm.submit(); if (value) { - this.restoreForm.submitCompleted({}); + this.restoreForm.submitCompleted({ url: '' }); this.backupsService.postRestore(value) .subscribe(() => { diff --git a/src/Squidex/app/features/administration/pages/users/user-page.component.ts b/src/Squidex/app/features/administration/pages/users/user-page.component.ts index e2be65749..fa4f43c82 100644 --- a/src/Squidex/app/features/administration/pages/users/user-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/user-page.component.ts @@ -12,6 +12,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { ResourceOwner } from '@app/shared'; import { + CreateUserDto, UserDto, UserForm, UsersState @@ -61,7 +62,7 @@ export class UserPageComponent extends ResourceOwner implements OnInit { this.userForm.submitFailed(error); }); } else { - this.usersState.create(value) + this.usersState.create(value) .subscribe(() => { this.back(); }, error => { diff --git a/src/Squidex/app/features/administration/state/users.forms.ts b/src/Squidex/app/features/administration/state/users.forms.ts index e998d449f..ca3effe38 100644 --- a/src/Squidex/app/features/administration/state/users.forms.ts +++ b/src/Squidex/app/features/administration/state/users.forms.ts @@ -2,9 +2,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Form, ValidatorsEx } from '@app/shared'; -import { UserDto } from './../services/users.service'; +import { UpdateUserDto } from './../services/users.service'; -export class UserForm extends Form { +export class UserForm extends Form { constructor( formBuilder: FormBuilder ) { @@ -36,25 +36,11 @@ export class UserForm extends Form { })); } - public load(user?: UserDto) { - if (user) { - this.form.controls['password'].setValidators(null); - - super.load({ ...user, permissions: user.permissions.join('\n') }); - } else { - this.form.controls['password'].setValidators(Validators.required); - - super.load(undefined); - } + protected transformLoad(user: UpdateUserDto) { + return { ...user, permissions: user.permissions.join('\n') }; } - public submit() { - const result = super.submit(); - - if (result) { - result['permissions'] = result['permissions'].split('\n').filter((x: any) => !!x); - } - - return result; + protected transformSubmit(value: any): UpdateUserDto { + return { ...value, permissions: value['permissions'].split('\n').filter((x: any) => !!x) }; } } \ No newline at end of file diff --git a/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts b/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts index a6339aa75..c9b1a77a2 100644 --- a/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts +++ b/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.ts @@ -27,11 +27,11 @@ export const MODE_EDIT_ACTION = 'EditAction'; templateUrl: './rule-wizard.component.html' }) export class RuleWizardComponent implements OnInit { - public actionForm = new Form(new FormGroup({})); + public actionForm = new Form(new FormGroup({})); public actionType: string; public action: any = {}; - public triggerForm = new Form(new FormGroup({})); + public triggerForm = new Form(new FormGroup({})); public triggerType: string; public trigger: any = {}; diff --git a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts index ea4a99529..f89b9ebb3 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/field-wizard.component.ts @@ -21,6 +21,8 @@ import { Types } from '@app/shared'; +const DEFAULT_FIELD = { name: '', partitioning: 'invariant', properties: createProperties('String') }; + @Component({ selector: 'sqx-field-wizard', styleUrls: ['./field-wizard.component.scss'], @@ -73,7 +75,7 @@ export class FieldWizardComponent implements OnInit { .subscribe(dto => { this.field = dto; - this.addFieldForm.submitCompleted({ type: fieldTypes[0].type }); + this.addFieldForm.submitCompleted({ ...DEFAULT_FIELD }); if (addNew) { if (Types.isFunction(this.nameInput.nativeElement.focus)) { diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts index 8522190d5..9f8574a04 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts @@ -46,7 +46,7 @@ export class SchemaPreviewUrlsFormComponent implements OnInit { } public cancelAdd() { - this.addForm.submitCompleted({}); + this.addForm.submitCompleted({ name: '', url: '' }); } public add() { @@ -55,7 +55,7 @@ export class SchemaPreviewUrlsFormComponent implements OnInit { if (value) { this.editForm.add(value); - this.addForm.submitCompleted({}); + this.cancelAdd(); } } diff --git a/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts index fdac8d2fd..d6f7f53bb 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts @@ -44,7 +44,7 @@ export class SchemaFormComponent implements OnInit { } public ngOnInit() { - this.createForm.load({ import: this.import }); + this.createForm.load({ name: '', import: this.import }); this.showImport = !!this.import; } diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index cf0ac2093..8650792c5 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -77,7 +77,7 @@ export class SchemasPageComponent extends ResourceOwner implements OnInit { try { this.schemasState.addCategory(value.name); } finally { - this.addCategoryForm.submitCompleted({}); + this.addCategoryForm.submitCompleted({ name: '' }); } } } diff --git a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts index bb73da085..ab81b8776 100644 --- a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts @@ -47,7 +47,7 @@ export class ClientsPageComponent implements OnInit { const value = this.addClientForm.submit(); if (value) { - this.clientsState.attach(value) + this.clientsState.attach({ id: value.name }) .subscribe(() => { this.addClientForm.submitCompleted(); }, error => { diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts index c3807c899..4bf0a1b52 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts @@ -99,7 +99,7 @@ export class ContributorsPageComponent implements OnInit { this.contributorsState.assign(requestDto) .subscribe(isCreated => { - this.assignContributorForm.submitCompleted({}); + this.assignContributorForm.submitCompleted({ user: '' }); if (isCreated) { this.dialogs.notifyInfo('A new user with the entered email address has been created and assigned as contributor.'); diff --git a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts index 8b02c9a52..4a64c1f4d 100644 --- a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts @@ -58,7 +58,7 @@ export class PatternComponent implements OnInit { } else { this.patternsState.create(value) .subscribe(() => { - this.editForm.submitCompleted({}); + this.editForm.submitCompleted({ pattern: '', name: '' }); }, error => { this.editForm.submitFailed(error); }); diff --git a/src/Squidex/app/features/settings/pages/roles/role.component.ts b/src/Squidex/app/features/settings/pages/roles/role.component.ts index a0980abfc..7c02be173 100644 --- a/src/Squidex/app/features/settings/pages/roles/role.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/role.component.ts @@ -85,7 +85,7 @@ export class RoleComponent implements OnChanges { if (value) { this.editForm.add(value.permission); - this.addPermissionForm.submitCompleted({}); + this.addPermissionForm.submitCompleted({ permission: '' }); this.addPermissionInput.focus(); } } diff --git a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts index ddf0607e8..843b92360 100644 --- a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts @@ -67,7 +67,7 @@ export class RolesPageComponent implements OnInit { if (value) { this.rolesState.add(value) .subscribe(() => { - this.addRoleForm.submitCompleted({}); + this.addRoleForm.submitCompleted({ name: '' }); }, error => { this.addRoleForm.submitFailed(error); }); diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index 4a529406d..1319ad555 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -20,7 +20,7 @@ export interface FormState { error?: string | null; } -export class Form { +export class Form { private readonly state = new State({ submitted: false }); public submitted = @@ -42,12 +42,20 @@ export class Form { this.form.enable(); } - protected reset(value: V | undefined) { - this.form.reset(value); + protected setValue(value?: V) { + if (value) { + this.form.reset(this.transformLoad(value)); + } else { + this.form.reset(); + } + } + + protected transformLoad(value: V): any { + return value; } - protected setValue(value: V | undefined) { - this.form.reset(value, { emitEvent: true }); + protected transformSubmit(value: any): V { + return value; } public load(value: V | undefined) { @@ -60,7 +68,7 @@ export class Form { this.state.next(_ => ({ submitted: true })); if (this.form.valid) { - const value = fullValue(this.form); + const value = this.transformSubmit(fullValue(this.form)); this.disable(); @@ -76,7 +84,7 @@ export class Form { this.enable(); if (newValue) { - this.reset(newValue); + this.setValue(newValue); } else { this.form.markAsPristine(); } diff --git a/src/Squidex/app/shared/components/comments.component.ts b/src/Squidex/app/shared/components/comments.component.ts index 5cbea6db8..cb493d69a 100644 --- a/src/Squidex/app/shared/components/comments.component.ts +++ b/src/Squidex/app/shared/components/comments.component.ts @@ -69,7 +69,7 @@ export class CommentsComponent extends ResourceOwner implements OnInit { if (value) { this.state.create(value.text).pipe(onErrorResumeNext()).subscribe(); - this.commentForm.submitCompleted({}); + this.commentForm.submitCompleted({ text: '' }); } } diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index 6bfd583e4..0a9bed879 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -419,7 +419,7 @@ describe('SchemasService', () => { const dto = new AddFieldDto('name', 'invariant', createProperties('Number')); - let field: FieldDto; + let field: FieldDto; schemasService.postField('my-app', 'my-schema', dto, undefined, version).subscribe(result => { field = result.payload; @@ -466,7 +466,7 @@ describe('SchemasService', () => { const dto = new AddFieldDto('name', 'invariant', createProperties('Number')); - let field: FieldDto; + let field: FieldDto; schemasService.postField('my-app', 'my-schema', dto, 13, version).subscribe(result => { field = result.payload; diff --git a/src/Squidex/app/shared/state/apps.forms.ts b/src/Squidex/app/shared/state/apps.forms.ts index 16d37f9de..b69ecd676 100644 --- a/src/Squidex/app/shared/state/apps.forms.ts +++ b/src/Squidex/app/shared/state/apps.forms.ts @@ -16,7 +16,7 @@ import { const FALLBACK_NAME = 'my-app'; -export class CreateAppForm extends Form { +export class CreateAppForm extends Form { public appName = value$(this.form.controls['name']).pipe(map(v => v || FALLBACK_NAME)); constructor(formBuilder: FormBuilder) { diff --git a/src/Squidex/app/shared/state/assets.forms.ts b/src/Squidex/app/shared/state/assets.forms.ts index 324bd7258..7d711093a 100644 --- a/src/Squidex/app/shared/state/assets.forms.ts +++ b/src/Squidex/app/shared/state/assets.forms.ts @@ -13,7 +13,7 @@ import { Form, Types } from '@app/framework'; import { AssetDto } from './../services/assets.service'; -export class AnnotateAssetForm extends Form { +export class AnnotateAssetForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ fileName: ['', @@ -37,7 +37,7 @@ export class AnnotateAssetForm extends Form { public submit(asset?: AssetDto) { const result = super.submit(); - if (asset) { + if (asset && result) { let index = asset.fileName.lastIndexOf('.'); if (index > 0) { diff --git a/src/Squidex/app/shared/state/backups.forms.ts b/src/Squidex/app/shared/state/backups.forms.ts index 6de3c6168..3decfeff7 100644 --- a/src/Squidex/app/shared/state/backups.forms.ts +++ b/src/Squidex/app/shared/state/backups.forms.ts @@ -13,18 +13,18 @@ import { ValidatorsEx } from '@app/framework'; -export class RestoreForm extends Form { +export class RestoreForm extends Form { public hasNoUrl = hasNoValue$(this.form.controls['url']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ - name: [null, + name: ['', [ Validators.maxLength(40), ValidatorsEx.pattern('[a-z0-9]+(\-[a-z0-9]+)*', 'Name can contain lower case letters (a-z), numbers and dashes (not at the end).') ] ], - url: [null, + url: ['', [ Validators.required ] diff --git a/src/Squidex/app/shared/state/clients.forms.ts b/src/Squidex/app/shared/state/clients.forms.ts index 1532c62ab..4b1ad2372 100644 --- a/src/Squidex/app/shared/state/clients.forms.ts +++ b/src/Squidex/app/shared/state/clients.forms.ts @@ -13,7 +13,7 @@ import { ValidatorsEx } from '@app/framework'; -export class RenameClientForm extends Form { +export class RenameClientForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ name: ['', @@ -25,7 +25,7 @@ export class RenameClientForm extends Form { } } -export class AttachClientForm extends Form { +export class AttachClientForm extends Form { public hasNoName = hasNoValue$(this.form.controls['name']); constructor(formBuilder: FormBuilder) { diff --git a/src/Squidex/app/shared/state/comments.form.ts b/src/Squidex/app/shared/state/comments.form.ts index a2620fbb4..1905d8b0d 100644 --- a/src/Squidex/app/shared/state/comments.form.ts +++ b/src/Squidex/app/shared/state/comments.form.ts @@ -9,7 +9,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Form } from '@app/framework'; -export class UpsertCommentForm extends Form { +export class UpsertCommentForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ text: ['', diff --git a/src/Squidex/app/shared/state/contents.forms.ts b/src/Squidex/app/shared/state/contents.forms.ts index 20c07a9bf..df52801fd 100644 --- a/src/Squidex/app/shared/state/contents.forms.ts +++ b/src/Squidex/app/shared/state/contents.forms.ts @@ -35,7 +35,7 @@ import { TagsFieldPropertiesDto } from './../services/schemas.types'; -export class SaveQueryForm extends Form { +export class SaveQueryForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ name: ['', @@ -298,7 +298,7 @@ export class FieldDefaultValue implements FieldPropertiesVisitor { } } -export class EditContentForm extends Form { +export class EditContentForm extends Form { constructor( private readonly schema: SchemaDetailsDto, private readonly languages: ImmutableArray @@ -466,7 +466,7 @@ export class EditContentForm extends Form { } } -export class PatchContentForm extends Form { +export class PatchContentForm extends Form { constructor( private readonly schema: SchemaDetailsDto, private readonly language: AppLanguageDto diff --git a/src/Squidex/app/shared/state/contributors.forms.ts b/src/Squidex/app/shared/state/contributors.forms.ts index 1ce37b075..e709f5637 100644 --- a/src/Squidex/app/shared/state/contributors.forms.ts +++ b/src/Squidex/app/shared/state/contributors.forms.ts @@ -9,7 +9,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Form, hasNoValue$ } from '@app/framework'; -export class AssignContributorForm extends Form { +import { UserDto } from './../services/users.service'; + +export class AssignContributorForm extends Form { public hasNoUser = hasNoValue$(this.form.controls['user']); constructor(formBuilder: FormBuilder) { diff --git a/src/Squidex/app/shared/state/languages.forms.ts b/src/Squidex/app/shared/state/languages.forms.ts index bc2e57568..776ea1724 100644 --- a/src/Squidex/app/shared/state/languages.forms.ts +++ b/src/Squidex/app/shared/state/languages.forms.ts @@ -9,7 +9,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Form } from '@app/framework'; -export class EditLanguageForm extends Form { +import { LanguageDto } from '../services/languages.service'; + +export class EditLanguageForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ isMaster: false, @@ -32,7 +34,7 @@ export class EditLanguageForm extends Form { } } -export class AddLanguageForm extends Form { +export class AddLanguageForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ language: [null, diff --git a/src/Squidex/app/shared/state/patterns.forms.ts b/src/Squidex/app/shared/state/patterns.forms.ts index 4267d5da2..a3d571069 100644 --- a/src/Squidex/app/shared/state/patterns.forms.ts +++ b/src/Squidex/app/shared/state/patterns.forms.ts @@ -9,7 +9,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Form, ValidatorsEx } from '@app/framework'; -export class EditPatternForm extends Form { +export class EditPatternForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ name: ['', diff --git a/src/Squidex/app/shared/state/roles.forms.ts b/src/Squidex/app/shared/state/roles.forms.ts index c8d859591..e9783e796 100644 --- a/src/Squidex/app/shared/state/roles.forms.ts +++ b/src/Squidex/app/shared/state/roles.forms.ts @@ -13,7 +13,7 @@ import { hasValue$ } from '@app/framework'; -export class EditPermissionsForm extends Form { +export class EditPermissionsForm extends Form { constructor() { super(new FormArray([])); } @@ -39,12 +39,12 @@ export class EditPermissionsForm extends Form { } } -export class AddPermissionForm extends Form { +export class AddPermissionForm extends Form { public hasPermission = hasValue$(this.form.controls['permission']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ - permission: [null, + permission: ['', [ Validators.required ] @@ -53,12 +53,12 @@ export class AddPermissionForm extends Form { } } -export class AddRoleForm extends Form { +export class AddRoleForm extends Form { public hasNoName = hasNoValue$(this.form.controls['name']); constructor(formBuilder: FormBuilder) { super(formBuilder.group({ - name: [null, + name: ['', [ Validators.required ] diff --git a/src/Squidex/app/shared/state/schemas.forms.ts b/src/Squidex/app/shared/state/schemas.forms.ts index 6f7e52207..a7aebd973 100644 --- a/src/Squidex/app/shared/state/schemas.forms.ts +++ b/src/Squidex/app/shared/state/schemas.forms.ts @@ -14,11 +14,13 @@ import { value$ } from '@app/framework'; +import { AddFieldDto } from '../services/schemas.service'; + import { createProperties } from './../services/schemas.types'; const FALLBACK_NAME = 'my-schema'; -export class CreateCategoryForm extends Form { +export class CreateCategoryForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ name: [''] @@ -26,7 +28,7 @@ export class CreateCategoryForm extends Form { } } -export class CreateSchemaForm extends Form { +export class CreateSchemaForm extends Form { public schemaName = value$(this.form.controls['name']).pipe(n => n || FALLBACK_NAME); @@ -45,7 +47,7 @@ export class CreateSchemaForm extends Form { } } -export class AddPreviewUrlForm extends Form { +export class AddPreviewUrlForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ name: ['', @@ -62,7 +64,7 @@ export class AddPreviewUrlForm extends Form { } } -export class ConfigurePreviewUrlsForm extends Form { +export class ConfigurePreviewUrlsForm extends Form { constructor( private readonly formBuilder: FormBuilder ) { @@ -89,7 +91,9 @@ export class ConfigurePreviewUrlsForm extends Form { this.form.removeAt(index); } - public load(value?: any) { + public transformLoad(value: { [name: string]: string }) { + const result: { name: string, url: string }[] = []; + if (Types.isObject(value)) { const length = Object.keys(value).length; @@ -101,38 +105,28 @@ export class ConfigurePreviewUrlsForm extends Form { this.remove(this.form.controls.length - 1); } - const array: any[] = []; - for (let key in value) { if (value.hasOwnProperty(key)) { - array.push({ name: key, url: value[key] }); + result.push({ name: key, url: value[key] }); } } - - value = array; } - super.load(value); + return result; } - public submit() { - let result = super.submit(); + public transformSubmit(value: { name: string, url: string }[]): { [name: string]: string } { + const result: { [name: string]: string } = {}; - if (result) { - const hash: { [name: string]: string } = {}; - - for (let item of result) { - hash[item.name] = item.url; - } - - result = hash; + for (let item of value) { + result[item.name] = item.url; } return result; } } -export class EditScriptsForm extends Form { +export class EditScriptsForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ query: '', @@ -144,7 +138,7 @@ export class EditScriptsForm extends Form { } } -export class EditFieldForm extends Form { +export class EditFieldForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ label: ['', @@ -169,7 +163,7 @@ export class EditFieldForm extends Form { } } -export class EditSchemaForm extends Form { +export class EditSchemaForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ label: ['', @@ -186,7 +180,7 @@ export class EditSchemaForm extends Form { } } -export class AddFieldForm extends Form { +export class AddFieldForm extends Form { constructor(formBuilder: FormBuilder) { super(formBuilder.group({ type: ['String', @@ -205,16 +199,16 @@ export class AddFieldForm extends Form { })); } - public submit() { - const value = super.submit(); + public transformLoad(value: AddFieldDto) { + const isLocalizable = value.partitioning === 'language'; - if (value) { - const properties = createProperties(value.type); - const partitioning = value.isLocalizable ? 'language' : 'invariant'; + return { name: value.name, isLocalizable, type: value.properties.fieldType }; + } - return { name: value.name, partitioning, properties }; - } + public transformSubmit(value: any): AddFieldDto { + const properties = createProperties(value.type); + const partitioning = value.isLocalizable ? 'language' : 'invariant'; - return null; + return { name: value.name, partitioning, properties }; } } \ No newline at end of file From 073d630d8831cc9c77e12e553454ee4577d3e3d8 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 26 Apr 2019 19:46:55 +0200 Subject: [PATCH 04/20] Tests fixed. --- .../pages/restore/restore-page.component.ts | 2 +- .../administration/state/users.state.spec.ts | 2 +- .../schema-preview-urls-form.component.ts | 2 +- .../pages/schemas/schemas-page.component.ts | 2 +- .../contributors-page.component.ts | 2 +- .../pages/patterns/pattern.component.ts | 2 +- .../settings/pages/roles/role.component.ts | 2 +- .../pages/roles/roles-page.component.ts | 2 +- src/Squidex/app/framework/state.ts | 7 +-- .../shared/components/comments.component.ts | 2 +- .../services/app-languages.service.spec.ts | 7 ++- .../shared/services/app-languages.service.ts | 11 ++++ .../app/shared/services/plans.service.spec.ts | 2 +- src/Squidex/app/shared/state/_test-helpers.ts | 52 +++++++++++++++++++ .../app/shared/state/assets.state.spec.ts | 28 +++++----- .../app/shared/state/backups.state.spec.ts | 14 +++-- .../app/shared/state/clients.state.spec.ts | 19 +++---- .../app/shared/state/comments.state.spec.ts | 46 ++++++++-------- .../shared/state/contributors.state.spec.ts | 41 ++++++--------- .../app/shared/state/filter.state.spec.ts | 4 +- .../app/shared/state/languages.state.spec.ts | 29 +++++------ .../app/shared/state/languages.state.ts | 12 ++--- .../app/shared/state/patterns.state.spec.ts | 21 ++++---- .../app/shared/state/plans.state.spec.ts | 33 +++++------- .../app/shared/state/roles.state.spec.ts | 19 +++---- .../shared/state/rule-events.state.spec.ts | 14 +++-- .../app/shared/state/rules.state.spec.ts | 40 ++++++-------- .../app/shared/state/schemas.state.spec.ts | 36 +++++-------- src/Squidex/app/shared/state/ui.state.spec.ts | 22 +++----- 29 files changed, 237 insertions(+), 238 deletions(-) create mode 100644 src/Squidex/app/shared/state/_test-helpers.ts diff --git a/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts b/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts index e23671154..32437b609 100644 --- a/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts +++ b/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts @@ -51,7 +51,7 @@ export class RestorePageComponent extends ResourceOwner implements OnInit { const value = this.restoreForm.submit(); if (value) { - this.restoreForm.submitCompleted({ url: '' }); + this.restoreForm.submitCompleted(); this.backupsService.postRestore(value) .subscribe(() => { diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts index 53bd4f3e3..cc7939542 100644 --- a/src/Squidex/app/features/administration/state/users.state.spec.ts +++ b/src/Squidex/app/features/administration/state/users.state.spec.ts @@ -177,7 +177,7 @@ describe('UsersState', () => { const user_1 = usersState.snapshot.users.at(0); expect(user_1.user.email).toEqual(request.email); - expect(user_1.user.displayName).toEqual(request.permissions); + expect(user_1.user.displayName).toEqual(request.displayName); expect(user_1.user.permissions).toEqual(request.permissions); expect(user_1).toBe(usersState.snapshot.selectedUser!); }); diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts index 9f8574a04..72a59074e 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/schema-preview-urls-form.component.ts @@ -46,7 +46,7 @@ export class SchemaPreviewUrlsFormComponent implements OnInit { } public cancelAdd() { - this.addForm.submitCompleted({ name: '', url: '' }); + this.addForm.submitCompleted(); } public add() { diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index 8650792c5..75d6d9b30 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -77,7 +77,7 @@ export class SchemasPageComponent extends ResourceOwner implements OnInit { try { this.schemasState.addCategory(value.name); } finally { - this.addCategoryForm.submitCompleted({ name: '' }); + this.addCategoryForm.submitCompleted(); } } } diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts index 4bf0a1b52..498cd0b5f 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts @@ -99,7 +99,7 @@ export class ContributorsPageComponent implements OnInit { this.contributorsState.assign(requestDto) .subscribe(isCreated => { - this.assignContributorForm.submitCompleted({ user: '' }); + this.assignContributorForm.submitCompleted(); if (isCreated) { this.dialogs.notifyInfo('A new user with the entered email address has been created and assigned as contributor.'); diff --git a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts index 4a64c1f4d..e1a45b953 100644 --- a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts @@ -58,7 +58,7 @@ export class PatternComponent implements OnInit { } else { this.patternsState.create(value) .subscribe(() => { - this.editForm.submitCompleted({ pattern: '', name: '' }); + this.editForm.submitCompleted(); }, error => { this.editForm.submitFailed(error); }); diff --git a/src/Squidex/app/features/settings/pages/roles/role.component.ts b/src/Squidex/app/features/settings/pages/roles/role.component.ts index 7c02be173..78e77aa06 100644 --- a/src/Squidex/app/features/settings/pages/roles/role.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/role.component.ts @@ -85,7 +85,7 @@ export class RoleComponent implements OnChanges { if (value) { this.editForm.add(value.permission); - this.addPermissionForm.submitCompleted({ permission: '' }); + this.addPermissionForm.submitCompleted(); this.addPermissionInput.focus(); } } diff --git a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts index 843b92360..edad41b92 100644 --- a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts @@ -67,7 +67,7 @@ export class RolesPageComponent implements OnInit { if (value) { this.rolesState.add(value) .subscribe(() => { - this.addRoleForm.submitCompleted({ name: '' }); + this.addRoleForm.submitCompleted(); }, error => { this.addRoleForm.submitFailed(error); }); diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index 1319ad555..5a9faa7cc 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -82,12 +82,7 @@ export class Form { this.state.next(_ => ({ submitted: false, error: null })); this.enable(); - - if (newValue) { - this.setValue(newValue); - } else { - this.form.markAsPristine(); - } + this.setValue(newValue); } public submitFailed(error?: string | ErrorDto) { diff --git a/src/Squidex/app/shared/components/comments.component.ts b/src/Squidex/app/shared/components/comments.component.ts index cb493d69a..5fe06b302 100644 --- a/src/Squidex/app/shared/components/comments.component.ts +++ b/src/Squidex/app/shared/components/comments.component.ts @@ -69,7 +69,7 @@ export class CommentsComponent extends ResourceOwner implements OnInit { if (value) { this.state.create(value.text).pipe(onErrorResumeNext()).subscribe(); - this.commentForm.submitCompleted({ text: '' }); + this.commentForm.submitCompleted(); } } diff --git a/src/Squidex/app/shared/services/app-languages.service.spec.ts b/src/Squidex/app/shared/services/app-languages.service.spec.ts index 5fd7d0cab..273a57ba4 100644 --- a/src/Squidex/app/shared/services/app-languages.service.spec.ts +++ b/src/Squidex/app/shared/services/app-languages.service.spec.ts @@ -94,7 +94,12 @@ describe('AppLanguagesService', () => { expect(req.request.method).toEqual('POST'); expect(req.request.headers.get('If-Match')).toEqual(version.value); - req.flush({ iso2Code: 'de', englishName: 'German' }); + req.flush({ + iso2Code: 'de', + isMaster: false, + isOptional: false, + englishName: 'German' + }); expect(language!).toEqual(new AppLanguageDto('de', 'German', false, false, [])); })); diff --git a/src/Squidex/app/shared/services/app-languages.service.ts b/src/Squidex/app/shared/services/app-languages.service.ts index 5a83f059e..3f35b6ebd 100644 --- a/src/Squidex/app/shared/services/app-languages.service.ts +++ b/src/Squidex/app/shared/services/app-languages.service.ts @@ -20,6 +20,8 @@ import { Versioned } from '@app/framework'; +import { LanguageDto } from './languages.service'; + export class AppLanguagesDto extends Model { constructor( public readonly languages: AppLanguageDto[], @@ -39,6 +41,15 @@ export class AppLanguageDto extends Model { ) { super(); } + + public static fromLanguage(language: LanguageDto, isMaster = false, isOptional = false, fallback: string[] = []) { + return new AppLanguageDto( + language.iso2Code, + language.englishName, + isMaster, + isOptional, + fallback); + } } export interface AddAppLanguageDto { diff --git a/src/Squidex/app/shared/services/plans.service.spec.ts b/src/Squidex/app/shared/services/plans.service.spec.ts index 35396170d..27cb2f149 100644 --- a/src/Squidex/app/shared/services/plans.service.spec.ts +++ b/src/Squidex/app/shared/services/plans.service.spec.ts @@ -110,7 +110,7 @@ describe('PlansService', () => { const req = httpMock.expectOne('http://service/p/api/apps/my-app/plan'); - req.flush({ redirectUri: 'my-url' }); + req.flush({ redirectUri: 'http://url' }); expect(req.request.method).toEqual('PUT'); expect(req.request.headers.get('If-Match')).toBe(version.value); diff --git a/src/Squidex/app/shared/state/_test-helpers.ts b/src/Squidex/app/shared/state/_test-helpers.ts new file mode 100644 index 000000000..69d6e55ce --- /dev/null +++ b/src/Squidex/app/shared/state/_test-helpers.ts @@ -0,0 +1,52 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { of } from 'rxjs'; +import { Mock } from 'typemoq'; + +import { + AppsState, + AuthService, + DateTime, + Version +} from './../'; + +const app = 'my-app'; +const creation = DateTime.today().addDays(-2); +const creator = 'me'; +const modified = DateTime.now().addDays(-1); +const modifier = 'now-me'; +const now = DateTime.now(); +const version = new Version('1'); +const newVersion = new Version('2'); + +const appsState = Mock.ofType(); + +appsState.setup(x => x.appName) + .returns(() => app); + +appsState.setup(x => x.selectedApp) + .returns(() => of({ name: app })); + +const authService = Mock.ofType(); + +authService.setup(x => x.user) + .returns(() => { id: modifier, token: modifier }); + +export const TestValues = { + app, + appsState, + authService, + creation, + creator, + modified, + modifier, + now, + newVersion, + userId: modifier, + version +}; \ No newline at end of file diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index aa32d70f3..702954a2f 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -9,25 +9,27 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, AssetDto, AssetsDto, AssetsService, AssetsState, - DateTime, DialogService, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('AssetsState', () => { - const app = 'my-app'; - const creation = DateTime.today(); - const creator = 'not-me'; - const modified = DateTime.now(); - const modifier = 'me'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + creation, + creator, + modified, + modifier, + newVersion, + version + } = TestValues; const oldAssets = [ new AssetDto('id1', creator, creator, creation, creation, 'name1', 'hash1', 'type1', 1, 1, 'mime1', false, false, null, null, 'slug1', ['tag1', 'shared'], 'url1', version), @@ -35,18 +37,12 @@ describe('AssetsState', () => { ]; let dialogs: IMock; - let appsState: IMock; let assetsService: IMock; let assetsState: AssetsState; beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - assetsService = Mock.ofType(); assetsService.setup(x => x.getAssets(app, 30, 0, undefined, [])) diff --git a/src/Squidex/app/shared/state/backups.state.spec.ts b/src/Squidex/app/shared/state/backups.state.spec.ts index a82eeba7a..46d1119b1 100644 --- a/src/Squidex/app/shared/state/backups.state.spec.ts +++ b/src/Squidex/app/shared/state/backups.state.spec.ts @@ -10,7 +10,6 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, BackupDto, BackupsService, BackupsState, @@ -18,8 +17,13 @@ import { DialogService } from './../'; +import { TestValues } from './_test-helpers'; + describe('BackupsState', () => { - const app = 'my-app'; + const { + app, + appsState + } = TestValues; const oldBackups = [ new BackupDto('id1', DateTime.now(), null, 1, 1, 'Started'), @@ -27,18 +31,12 @@ describe('BackupsState', () => { ]; let dialogs: IMock; - let appsState: IMock; let backupsService: IMock; let backupsState: BackupsState; beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - backupsService = Mock.ofType(); backupsService.setup(x => x.getBackups(app)) diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index 6462f20b7..82971fc19 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -9,20 +9,23 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, ClientDto, ClientsDto, ClientsService, ClientsState, DialogService, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('ClientsState', () => { - const app = 'my-app'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + newVersion, + version + } = TestValues; const oldClients = [ new ClientDto('id1', 'name1', 'secret1'), @@ -30,18 +33,12 @@ describe('ClientsState', () => { ]; let dialogs: IMock; - let appsState: IMock; let clientsService: IMock; let clientsState: ClientsState; beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - clientsService = Mock.ofType(); clientsService.setup(x => x.getClients(app)) diff --git a/src/Squidex/app/shared/state/comments.state.spec.ts b/src/Squidex/app/shared/state/comments.state.spec.ts index 7a101a793..ad1d1347d 100644 --- a/src/Squidex/app/shared/state/comments.state.spec.ts +++ b/src/Squidex/app/shared/state/comments.state.spec.ts @@ -9,41 +9,39 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, CommentDto, CommentsDto, CommentsService, CommentsState, - DateTime, DialogService, ImmutableArray, Version } from './../'; +import { TestValues } from './_test-helpers'; + describe('CommentsState', () => { - const app = 'my-app'; + const { + app, + appsState, + creator, + now + } = TestValues; + const commentsId = 'my-comments'; - const now = DateTime.today(); - const user = 'not-me'; const oldComments = new CommentsDto([ - new CommentDto('1', now, 'text1', user), - new CommentDto('2', now, 'text2', user) + new CommentDto('1', now, 'text1', creator), + new CommentDto('2', now, 'text2', creator) ], [], [], new Version('1')); let dialogs: IMock; - let appsState: IMock; let commentsService: IMock; let commentsState: CommentsState; beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - commentsService = Mock.ofType(); commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) @@ -55,9 +53,9 @@ describe('CommentsState', () => { it('should load and merge comments', () => { const newComments = new CommentsDto([ - new CommentDto('3', now, 'text3', user) + new CommentDto('3', now, 'text3', creator) ], [ - new CommentDto('2', now, 'text2_2', user) + new CommentDto('2', now, 'text2_2', creator) ], ['1'], new Version('2')); commentsService.setup(x => x.getComments(app, commentsId, new Version('1'))) @@ -67,15 +65,15 @@ describe('CommentsState', () => { expect(commentsState.snapshot.isLoaded).toBeTruthy(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('2', now, 'text2_2', user), - new CommentDto('3', now, 'text3', user) + new CommentDto('2', now, 'text2_2', creator), + new CommentDto('3', now, 'text3', creator) ])); commentsService.verify(x => x.getComments(app, commentsId, It.isAny()), Times.exactly(2)); }); it('should add comment to snapshot when created', () => { - const newComment = new CommentDto('3', now, 'text3', user); + const newComment = new CommentDto('3', now, 'text3', creator); const request = { text: 'text3' }; @@ -85,9 +83,9 @@ describe('CommentsState', () => { commentsState.create('text3').subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', user), - new CommentDto('2', now, 'text2', user), - new CommentDto('3', now, 'text3', user) + new CommentDto('1', now, 'text1', creator), + new CommentDto('2', now, 'text2', creator), + new CommentDto('3', now, 'text3', creator) ])); }); @@ -100,8 +98,8 @@ describe('CommentsState', () => { commentsState.update('2', 'text2_2', now).subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', user), - new CommentDto('2', now, 'text2_2', user) + new CommentDto('1', now, 'text1', creator), + new CommentDto('2', now, 'text2_2', creator) ])); commentsService.verify(x => x.putComment(app, commentsId, '2', request), Times.once()); @@ -114,7 +112,7 @@ describe('CommentsState', () => { commentsState.delete('2').subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', user) + new CommentDto('1', now, 'text1', creator) ])); commentsService.verify(x => x.deleteComment(app, commentsId, '2'), Times.once()); diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index b98051959..8d217321a 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -9,49 +9,40 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, - AuthService, ContributorAssignedDto, ContributorDto, ContributorsDto, ContributorsService, ContributorsState, DialogService, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('ContributorsState', () => { - const app = 'my-app'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + authService, + newVersion, + userId, + version + } = TestValues; const oldContributors = [ new ContributorDto('id1', 'Developer'), - new ContributorDto('id2', 'Developer') + new ContributorDto(userId, 'Developer') ]; let dialogs: IMock; - let appsState: IMock; - let authService: IMock; let contributorsService: IMock; let contributorsState: ContributorsState; beforeEach(() => { dialogs = Mock.ofType(); - authService = Mock.ofType(); - - authService.setup(x => x.user) - .returns(() => { id: 'id2' }); - - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - contributorsService = Mock.ofType(); - contributorsService.setup(x => x.getContributors(app)) .returns(() => of(new ContributorsDto(oldContributors, 3, version))); @@ -83,10 +74,11 @@ describe('ContributorsState', () => { it('should add contributor to snapshot when assigned', () => { const newContributor = new ContributorDto('id3', 'Developer'); - const request = { contributorId: 'mail2stehle@gmail.com', role: 'Developer' }; + const request = { contributorId: 'mail2stehle@gmail.com', role: newContributor.role }; + const response = { contributorId: newContributor.contributorId, isCreated: true }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, { contributorId: '123', isCreated: true }))); + .returns(() => of(new Versioned(newVersion, response))); contributorsState.assign(request).subscribe(); @@ -101,12 +93,13 @@ describe('ContributorsState', () => { }); it('should update contributor in snapshot when assigned and already added', () => { - const newContributor = new ContributorDto('id2', 'Owner'); + const newContributor = new ContributorDto(userId, 'Owner'); const request = { ...newContributor }; + const response = { contributorId: newContributor.contributorId, isCreated: true }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, { contributorId: '123', isCreated: true }))); + .returns(() => of(new Versioned(newVersion, response))); contributorsState.assign(request).subscribe(); diff --git a/src/Squidex/app/shared/state/filter.state.spec.ts b/src/Squidex/app/shared/state/filter.state.spec.ts index 381420547..24840bdaf 100644 --- a/src/Squidex/app/shared/state/filter.state.spec.ts +++ b/src/Squidex/app/shared/state/filter.state.spec.ts @@ -12,10 +12,10 @@ import { } from './../'; describe('FilterState', () => { - let filterState: FilterState; let query: string | undefined; - let filter: string | undefined; let fullText: string | undefined; + let filterState: FilterState; + let filter: string | undefined; let order: string | undefined; beforeEach(() => { diff --git a/src/Squidex/app/shared/state/languages.state.spec.ts b/src/Squidex/app/shared/state/languages.state.spec.ts index 97ab66264..56f98080b 100644 --- a/src/Squidex/app/shared/state/languages.state.spec.ts +++ b/src/Squidex/app/shared/state/languages.state.spec.ts @@ -12,20 +12,23 @@ import { AppLanguageDto, AppLanguagesDto, AppLanguagesService, - AppsState, DialogService, ImmutableArray, LanguageDto, LanguagesService, LanguagesState, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('LanguagesState', () => { - const app = 'my-app'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + newVersion, + version + } = TestValues; const languageDE = new LanguageDto('de', 'German'); const languageEN = new LanguageDto('en', 'English'); @@ -33,12 +36,11 @@ describe('LanguagesState', () => { const languageES = new LanguageDto('es', 'Spanish'); const oldLanguages = [ - new AppLanguageDto(languageEN.iso2Code, languageEN.englishName, true, false, []), - new AppLanguageDto(languageDE.iso2Code, languageDE.englishName, false, true, [languageEN.iso2Code]) + AppLanguageDto.fromLanguage(languageEN, true), + AppLanguageDto.fromLanguage(languageDE, false, true, [languageEN.iso2Code]) ]; let dialogs: IMock; - let appsState: IMock; let allLanguagesService: IMock; let languagesService: IMock; let languagesState: LanguagesState; @@ -46,11 +48,6 @@ describe('LanguagesState', () => { beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - allLanguagesService = Mock.ofType(); allLanguagesService.setup(x => x.getLanguages()) @@ -120,15 +117,15 @@ describe('LanguagesState', () => { }); it('should update language in snapshot when updated', () => { - const request = { isMaster: true }; + const request = { isMaster: true, isOptional: false, fallback: [] }; languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) .returns(() => of(new Versioned(newVersion, {}))); languagesState.update(oldLanguages[1], request).subscribe(); - const newLanguage1 = new AppLanguageDto(languageDE.iso2Code, languageDE.englishName, true, false, []); - const newLanguage2 = new AppLanguageDto(languageEN.iso2Code, languageEN.englishName, false, false, []); + const newLanguage1 = AppLanguageDto.fromLanguage(languageDE, true); + const newLanguage2 = AppLanguageDto.fromLanguage(languageEN); expect(languagesState.snapshot.languages.values).toEqual([ { diff --git a/src/Squidex/app/shared/state/languages.state.ts b/src/Squidex/app/shared/state/languages.state.ts index 9910fe399..74210b669 100644 --- a/src/Squidex/app/shared/state/languages.state.ts +++ b/src/Squidex/app/shared/state/languages.state.ts @@ -132,13 +132,13 @@ export class LanguagesState extends State { public update(language: AppLanguageDto, request: UpdateAppLanguageDto): Observable { return this.appLanguagesService.putLanguage(this.appName, language.iso2Code, request, this.version).pipe( tap(dto => { - const languages = this.snapshot.plainLanguages.map(l => { - if (l.iso2Code === language.iso2Code) { - return update(l, request); - } else if (l.isMaster && request.isMaster) { - return update(l, { isMaster: false }); + const languages = this.snapshot.plainLanguages.map(x => { + if (x.iso2Code === language.iso2Code) { + return update(x, request); + } else if (x.isMaster && request.isMaster) { + return update(x, { isMaster: false }); } else { - return l; + return x; } }); diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index 60d6d5653..94863afd3 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -9,20 +9,23 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, DialogService, PatternDto, PatternsDto, PatternsService, PatternsState, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('PatternsState', () => { - const app = 'my-app'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + newVersion, + version + } = TestValues; const oldPatterns = [ new PatternDto('id1', 'name1', 'pattern1', ''), @@ -30,18 +33,12 @@ describe('PatternsState', () => { ]; let dialogs: IMock; - let appsState: IMock; let patternsService: IMock; let patternsState: PatternsState; beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - patternsService = Mock.ofType(); patternsService.setup(x => x.getPatterns(app)) @@ -88,7 +85,7 @@ describe('PatternsState', () => { patternsState.update(oldPatterns[1], request).subscribe(); - const pattern_1 = patternsState.snapshot.patterns.at(0); + const pattern_1 = patternsState.snapshot.patterns.at(1); expect(pattern_1.name).toBe(request.name); expect(pattern_1.pattern).toBe(request.pattern); diff --git a/src/Squidex/app/shared/state/plans.state.spec.ts b/src/Squidex/app/shared/state/plans.state.spec.ts index e30c52238..e1555e27e 100644 --- a/src/Squidex/app/shared/state/plans.state.spec.ts +++ b/src/Squidex/app/shared/state/plans.state.spec.ts @@ -10,22 +10,25 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, - AuthService, DialogService, PlanChangedDto, PlanDto, PlansDto, PlansService, PlansState, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('PlansState', () => { - const app = 'my-app'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + authService, + newVersion, + version + } = TestValues; const oldPlans = new PlansDto('id1', 'id2', true, [ @@ -35,24 +38,12 @@ describe('PlansState', () => { version); let dialogs: IMock; - let appsState: IMock; - let authService: IMock; let plansService: IMock; let plansState: PlansState; beforeEach(() => { dialogs = Mock.ofType(); - authService = Mock.ofType(); - - authService.setup(x => x.user) - .returns(() => { id: 'id3' }); - - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - plansService = Mock.ofType(); plansService.setup(x => x.getPlans(app)) @@ -102,8 +93,10 @@ describe('PlansState', () => { it('should redirect when returning url', () => { plansState.window = { location: {} }; + const result = { redirectUri: 'http://url' }; + plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, { redirectUri: 'http://url' }))); + .returns(() => of(new Versioned(newVersion, result))); plansState.load().subscribe(); plansState.change('free').pipe(onErrorResumeNext()).subscribe(); @@ -112,7 +105,7 @@ describe('PlansState', () => { { isSelected: true, isYearlySelected: false, plan: oldPlans.plans[0] }, { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[1] } ]); - expect(plansState.window.location.href).toBe('URI'); + expect(plansState.window.location.href).toBe(result.redirectUri); expect(plansState.snapshot.version).toEqual(version); }); diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index 69391e2dc..ce0786c92 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -9,20 +9,23 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, DialogService, RoleDto, RolesDto, RolesService, RolesState, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('RolesState', () => { - const app = 'my-app'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + newVersion, + version + } = TestValues; const oldRoles = [ new RoleDto('Role1', 3, 5, ['P1']), @@ -30,18 +33,12 @@ describe('RolesState', () => { ]; let dialogs: IMock; - let appsState: IMock; let rolesService: IMock; let rolesState: RolesState; beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - rolesService = Mock.ofType(); rolesService.setup(x => x.getRoles(app)) diff --git a/src/Squidex/app/shared/state/rule-events.state.spec.ts b/src/Squidex/app/shared/state/rule-events.state.spec.ts index acc4eee03..50ca944f0 100644 --- a/src/Squidex/app/shared/state/rule-events.state.spec.ts +++ b/src/Squidex/app/shared/state/rule-events.state.spec.ts @@ -9,7 +9,6 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - AppsState, DateTime, DialogService, RuleEventDto, @@ -18,15 +17,19 @@ import { RulesService } from './../'; +import { TestValues } from './_test-helpers'; + describe('RuleEventsState', () => { - const app = 'my-app'; + const { + app, + appsState + } = TestValues; const oldRuleEvents = [ new RuleEventDto('id1', DateTime.now(), null, 'event1', 'description', 'dump1', 'result1', 'result1', 1), new RuleEventDto('id2', DateTime.now(), null, 'event2', 'description', 'dump2', 'result2', 'result2', 2) ]; - let appsState: IMock; let dialogs: IMock; let rulesService: IMock; let ruleEventsState: RuleEventsState; @@ -34,11 +37,6 @@ describe('RuleEventsState', () => { beforeEach(() => { dialogs = Mock.ofType(); - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - rulesService = Mock.ofType(); rulesService.setup(x => x.getEvents(app, 10, 0)) diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index 5181981ab..6fd8c7cbe 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -11,25 +11,27 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { RulesState } from './rules.state'; import { - AppsState, - AuthService, - DateTime, DialogService, RuleDto, RulesService, UpdateRuleDto, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('RulesState', () => { - const app = 'my-app'; - const creation = DateTime.today(); - const creator = 'not-me'; - const modified = DateTime.now(); - const modifier = 'me'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + authService, + creation, + creator, + modified, + modifier, + newVersion, + version + } = TestValues; const oldRules = [ new RuleDto('id1', creator, creator, creation, creation, version, false, {}, 'trigger1', {}, 'action1'), @@ -37,24 +39,12 @@ describe('RulesState', () => { ]; let dialogs: IMock; - let appsState: IMock; - let authService: IMock; let rulesService: IMock; let rulesState: RulesState; beforeEach(() => { dialogs = Mock.ofType(); - authService = Mock.ofType(); - - authService.setup(x => x.user) - .returns(() => { id: '1', token: modifier }); - - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - rulesService = Mock.ofType(); rulesService.setup(x => x.getRules(app)) @@ -95,7 +85,7 @@ describe('RulesState', () => { it('should update action and update and user info when updated action', () => { const newAction = {}; - rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(i => true), version)) + rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(() => true), version)) .returns(() => of(new Versioned(newVersion, {}))); rulesState.updateAction(oldRules[0], newAction, modified).subscribe(); @@ -109,7 +99,7 @@ describe('RulesState', () => { it('should update trigger and update and user info when updated trigger', () => { const newTrigger = {}; - rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(i => true), version)) + rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(() => true), version)) .returns(() => of(new Versioned(newVersion, {}))); rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe(); diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 2624f51b8..067b022a5 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -12,11 +12,8 @@ import { SchemasState } from './schemas.state'; import { AddFieldDto, - AppsState, - AuthService, createProperties, CreateSchemaDto, - DateTime, DialogService, NestedFieldDto, RootFieldDto, @@ -24,18 +21,23 @@ import { SchemaDto, SchemasService, UpdateSchemaCategoryDto, - Version, Versioned } from './../'; +import { TestValues } from './_test-helpers'; + describe('SchemasState', () => { - const app = 'my-app'; - const creation = DateTime.today(); - const creator = 'not-me'; - const modified = DateTime.now(); - const modifier = 'me'; - const version = new Version('1'); - const newVersion = new Version('2'); + const { + app, + appsState, + authService, + creation, + creator, + modified, + modifier, + newVersion, + version + } = TestValues; const oldSchemas = [ new SchemaDto('id1', 'name1', 'category1', {}, false, false, creation, creator, creation, creator, version), @@ -56,24 +58,12 @@ describe('SchemasState', () => { [field1, field2]); let dialogs: IMock; - let appsState: IMock; - let authService: IMock; let schemasService: IMock; let schemasState: SchemasState; beforeEach(() => { dialogs = Mock.ofType(); - authService = Mock.ofType(); - - authService.setup(x => x.user) - .returns(() => { id: '1', token: modifier }); - - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - schemasService = Mock.ofType(); schemasService.setup(x => x.getSchemas(app)) diff --git a/src/Squidex/app/shared/state/ui.state.spec.ts b/src/Squidex/app/shared/state/ui.state.spec.ts index 171a4e3a5..8ca7da532 100644 --- a/src/Squidex/app/shared/state/ui.state.spec.ts +++ b/src/Squidex/app/shared/state/ui.state.spec.ts @@ -8,14 +8,15 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; -import { - AppsState, - UIService, - UIState -} from './../'; +import { UIService, UIState } from './../'; + +import { TestValues } from './_test-helpers'; describe('UIState', () => { - const app = 'my-app'; + const { + app, + appsState + } = TestValues; const appSettings = { mapType: 'GM', @@ -29,19 +30,10 @@ describe('UIState', () => { canCreateApps: true }; - let appsState: IMock; let uiService: IMock; let uiState: UIState; beforeEach(() => { - appsState = Mock.ofType(); - - appsState.setup(x => x.appName) - .returns(() => app); - - appsState.setup(x => x.selectedApp) - .returns(() => of({ name: app })); - uiService = Mock.ofType(); uiService.setup(x => x.getSettings(app)) From d99a3998bdfe2c916feb4bea77f1298f05d9b34b Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 27 Apr 2019 16:31:18 +0200 Subject: [PATCH 05/20] Test --- .../event-consumers-page.component.ts | 16 +- .../state/event-consumers.state.ts | 88 +- .../angular/forms/progress-bar.component.ts | 9 +- .../app/framework/utils/immutable-array.ts | 4 + src/Squidex/app/framework/utils/modal-view.ts | 12 +- .../components/asset-uploader.component.html | 31 + .../components/asset-uploader.component.scss | 70 ++ .../components/asset-uploader.component.ts | 49 + .../shared/components/asset.component.html | 20 +- .../app/shared/components/asset.component.ts | 91 +- .../components/assets-list.component.html | 17 +- .../components/assets-list.component.ts | 34 +- .../components/assets-selector.component.ts | 4 +- src/Squidex/app/shared/declarations.ts | 1 + src/Squidex/app/shared/module.ts | 7 +- .../app/shared/state/assets.state.spec.ts | 12 +- src/Squidex/app/shared/state/assets.state.ts | 194 ++- .../pages/internal/apps-menu.component.html | 1 - .../internal/internal-area.component.html | 4 + src/Squidex/app/theme/icomoon/Read Me.txt | 7 - .../app/theme/icomoon/demo-files/demo.css | 4 +- src/Squidex/app/theme/icomoon/demo.html | 1118 +++++++++-------- .../app/theme/icomoon/fonts/icomoon.eot | Bin 28292 -> 29216 bytes .../app/theme/icomoon/fonts/icomoon.svg | 4 + .../app/theme/icomoon/fonts/icomoon.ttf | Bin 28128 -> 29052 bytes .../app/theme/icomoon/fonts/icomoon.woff | Bin 28204 -> 29128 bytes src/Squidex/app/theme/icomoon/selection.json | 2 +- src/Squidex/app/theme/icomoon/style.css | 172 +-- 28 files changed, 1164 insertions(+), 807 deletions(-) create mode 100644 src/Squidex/app/shared/components/asset-uploader.component.html create mode 100644 src/Squidex/app/shared/components/asset-uploader.component.scss create mode 100644 src/Squidex/app/shared/components/asset-uploader.component.ts delete mode 100644 src/Squidex/app/theme/icomoon/Read Me.txt diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts index c23849a99..da06f82c7 100644 --- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts +++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts @@ -29,25 +29,25 @@ export class EventConsumersPageComponent extends ResourceOwner implements OnInit } public ngOnInit() { - this.eventConsumersState.load().pipe(onErrorResumeNext()).subscribe(); + this.eventConsumersState.load(); this.own(timer(5000, 5000).pipe(switchMap(() => this.eventConsumersState.load(true, true)), onErrorResumeNext())); } public reload() { - this.eventConsumersState.load(true, false).pipe(onErrorResumeNext()).subscribe(); + this.eventConsumersState.load(true, false); } - public start(es: EventConsumerDto) { - this.eventConsumersState.start(es).pipe(onErrorResumeNext()).subscribe(); + public start(eventConsumer: EventConsumerDto) { + this.eventConsumersState.start(eventConsumer); } - public stop(es: EventConsumerDto) { - this.eventConsumersState.stop(es).pipe(onErrorResumeNext()).subscribe(); + public stop(eventConsumer: EventConsumerDto) { + this.eventConsumersState.stop(eventConsumer); } - public reset(es: EventConsumerDto) { - this.eventConsumersState.reset(es).pipe(onErrorResumeNext()).subscribe(); + public reset(eventConsumer: EventConsumerDto) { + this.eventConsumersState.reset(eventConsumer); } public trackByEventConsumer(index: number, es: EventConsumerDto) { diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.ts b/src/Squidex/app/features/administration/state/event-consumers.state.ts index b333fa44a..80a89eac8 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.ts @@ -6,13 +6,12 @@ */ import { Injectable } from '@angular/core'; -import { Observable, throwError } from 'rxjs'; -import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, State } from '@app/shared'; @@ -43,54 +42,67 @@ export class EventConsumersState extends State { super({ eventConsumers: ImmutableArray.empty() }); } - public load(isReload = false, silent = false): Observable { + public load(isReload = false, silent = false): Observable { if (!isReload) { this.resetState(); } - return this.eventConsumersService.getEventConsumers().pipe( - tap(dtos => { - if (isReload && !silent) { - this.dialogs.notifyInfo('Event Consumers reloaded.'); - } - - this.next(s => { - const eventConsumers = ImmutableArray.of(dtos); - - return { ...s, eventConsumers, isLoaded: true }; - }); - }), - catchError(error => { - if (!silent) { - this.dialogs.notifyError(error); - } - - return throwError(error); - })); + const stream = this.eventConsumersService.getEventConsumers().pipe(share()); + + stream.subscribe(dtos => { + if (isReload && !silent) { + this.dialogs.notifyInfo('Event Consumers reloaded.'); + } + + this.next(s => { + const eventConsumers = ImmutableArray.of(dtos); + + return { ...s, eventConsumers, isLoaded: true }; + }); + + }, error => { + if (!silent) { + this.dialogs.notifyError(error); + } + }); + + return stream; } public start(eventConsumer: EventConsumerDto): Observable { - return this.eventConsumersService.putStart(eventConsumer.name).pipe( - tap(() => { - this.replaceEventConsumer(setStopped(eventConsumer, false)); - }), - notify(this.dialogs)); + const stream = this.eventConsumersService.putStart(eventConsumer.name).pipe(share()); + + stream.subscribe(() => { + this.replaceEventConsumer(setStopped(eventConsumer, false)); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } public stop(eventConsumer: EventConsumerDto): Observable { - return this.eventConsumersService.putStop(eventConsumer.name).pipe( - tap(() => { - this.replaceEventConsumer(setStopped(eventConsumer, true)); - }), - notify(this.dialogs)); + const stream = this.eventConsumersService.putStop(eventConsumer.name).pipe(share()); + + stream.subscribe(() => { + this.replaceEventConsumer(setStopped(eventConsumer, true)); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } public reset(eventConsumer: EventConsumerDto): Observable { - return this.eventConsumersService.putReset(eventConsumer.name).pipe( - tap(() => { - this.replaceEventConsumer(reset(eventConsumer)); - }), - notify(this.dialogs)); + const stream = this.eventConsumersService.putReset(eventConsumer.name).pipe(share()); + + stream.subscribe(() => { + this.replaceEventConsumer(reset(eventConsumer)); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } private replaceEventConsumer(eventConsumer: EventConsumerDto) { diff --git a/src/Squidex/app/framework/angular/forms/progress-bar.component.ts b/src/Squidex/app/framework/angular/forms/progress-bar.component.ts index 4a4d99649..9bf8d0aea 100644 --- a/src/Squidex/app/framework/angular/forms/progress-bar.component.ts +++ b/src/Squidex/app/framework/angular/forms/progress-bar.component.ts @@ -35,6 +35,9 @@ export class ProgressBarComponent implements OnChanges, OnInit { @Input() public showText = true; + @Input() + public animated = true; + @Input() public value = 0; @@ -74,7 +77,11 @@ export class ProgressBarComponent implements OnChanges, OnInit { private updateValue() { const value = this.value; - this.progressBar.animate(value / 100); + if (this.animated) { + this.progressBar.animate(value / 100); + } else { + this.progressBar.set(value / 100); + } if (value > 0 && this.showText) { this.progressBar.setText(Math.round(value) + '%'); diff --git a/src/Squidex/app/framework/utils/immutable-array.ts b/src/Squidex/app/framework/utils/immutable-array.ts index 524d9f308..0779e947d 100644 --- a/src/Squidex/app/framework/utils/immutable-array.ts +++ b/src/Squidex/app/framework/utils/immutable-array.ts @@ -230,4 +230,8 @@ export class ImmutableArray implements Iterable { public replaceBy(field: string, newValue: T, replacer?: (o: T, n: T) => T) { return this.replaceAll(x => x[field] === newValue[field], o => replacer ? replacer(o, newValue) : newValue); } + + public removeBy(field: string, value: T) { + return this.removeAll(x => x[field] === value[field]); + } } \ No newline at end of file diff --git a/src/Squidex/app/framework/utils/modal-view.ts b/src/Squidex/app/framework/utils/modal-view.ts index a77cda5f6..28c00bc64 100644 --- a/src/Squidex/app/framework/utils/modal-view.ts +++ b/src/Squidex/app/framework/utils/modal-view.ts @@ -12,12 +12,16 @@ export interface Openable { } export class DialogModel implements Openable { - private readonly isOpen$ = new BehaviorSubject(false); + private readonly isOpen$: BehaviorSubject; public get isOpen(): Observable { return this.isOpen$; } + constructor(isOpen = false) { + this.isOpen$ = new BehaviorSubject(isOpen); + } + public show(): DialogModel { this.isOpen$.next(true); @@ -38,12 +42,16 @@ export class DialogModel implements Openable { } export class ModalModel implements Openable { - private readonly isOpen$ = new BehaviorSubject(false); + private readonly isOpen$: BehaviorSubject; public get isOpen(): Observable { return this.isOpen$; } + constructor(isOpen = false) { + this.isOpen$ = new BehaviorSubject(isOpen); + } + public show(): ModalModel { if (!this.isOpen$.value) { if (openModal && openModal !== this) { diff --git a/src/Squidex/app/shared/components/asset-uploader.component.html b/src/Squidex/app/shared/components/asset-uploader.component.html new file mode 100644 index 000000000..11d8cd704 --- /dev/null +++ b/src/Squidex/app/shared/components/asset-uploader.component.html @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset-uploader.component.scss b/src/Squidex/app/shared/components/asset-uploader.component.scss new file mode 100644 index 000000000..a6dd0a60e --- /dev/null +++ b/src/Squidex/app/shared/components/asset-uploader.component.scss @@ -0,0 +1,70 @@ +@import '_vars'; +@import '_mixins'; + +.nav { + & { + padding-right: 2rem; + } + .nav-item { + & { + line-height: 2rem; + } + + .nav-link { + color: $color-dark-foreground; + padding-top: 0; + padding-bottom: 0; + } + } +} + +.icon-upload-3 { + vertical-align: middle; + font-size: 1.4rem; + font-weight: lighter; + padding-right: .5rem; +} + +.dropdown-menu { + @include absolute(2.6rem, 0, auto, auto); + display: block; + min-width: 30rem; + max-width: 60%; + min-height: 4rem; + padding: 1rem; +} + +.uploads { + & { + border: 2px solid transparent; + } + + &-empty { + line-height: 2rem; + } +} + +.upload { + & { + line-height: 2rem; + min-height: 2rem; + max-height: 2rem; + margin-bottom: .5rem; + } + + &:last-child { + margin: 0; + } + + &-name { + @include truncate; + padding-right: .5rem; + padding-left: .5rem; + } +} + +.drag { + & > .uploads { + border-color: $color-theme-blue; + } +} \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset-uploader.component.ts b/src/Squidex/app/shared/components/asset-uploader.component.ts new file mode 100644 index 000000000..c8c5c8f5c --- /dev/null +++ b/src/Squidex/app/shared/components/asset-uploader.component.ts @@ -0,0 +1,49 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +import { + AssetsState, + DialogModel, + fadeAnimation, + UploadingAsset +} from '@app/shared/internal'; + +@Component({ + selector: 'sqx-asset-uploader', + styleUrls: ['./asset-uploader.component.scss'], + templateUrl: './asset-uploader.component.html', + animations: [ + fadeAnimation + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AssetUploaderComponent { + public modalMenu = new DialogModel(true); + + constructor( + public readonly assets: AssetsState + ) { + } + + public addFiles(files: File[]) { + for (let file of files) { + this.assets.upload(file).subscribe(); + } + + this.modalMenu.show(); + } + + public stopUpload(upload: UploadingAsset) { + this.assets.remove(upload); + } + + public trackByUpload(index: number, upload: UploadingAsset) { + return upload.id; + } +} \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset.component.html b/src/Squidex/app/shared/components/asset.component.html index bb466fb5c..9045a0e5d 100644 --- a/src/Squidex/app/shared/components/asset.component.html +++ b/src/Squidex/app/shared/components/asset.component.html @@ -1,7 +1,7 @@
-
+
{{asset.fileType}} @@ -46,11 +46,11 @@
-
- +
+
-
+
Drop to update
@@ -77,14 +77,14 @@
-
+
-
+
- +
@@ -113,11 +113,11 @@
-
- +
+
-
+
Drop to update
diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 6550d3bda..30fdd6eae 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -5,26 +5,15 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnInit, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core'; import { - AppsState, AssetDto, - AssetsService, - AuthService, - DateTime, DialogModel, - DialogService, fadeAnimation, - StatefulComponent, - Types, - Versioned + UploadingAsset } from '@app/shared/internal'; -interface State { - progress: number; -} - @Component({ selector: 'sqx-asset', styleUrls: ['./asset.component.scss'], @@ -34,9 +23,9 @@ interface State { ], changeDetection: ChangeDetectionStrategy.OnPush }) -export class AssetComponent extends StatefulComponent implements OnInit { +export class AssetComponent { @Input() - public initFile: File; + public upload: UploadingAsset; @Input() public asset: AssetDto; @@ -62,18 +51,15 @@ export class AssetComponent extends StatefulComponent implements OnInit { @Input() public allTags: string[]; - @Output() - public load = new EventEmitter(); - - @Output() - public loadError = new EventEmitter(); - @Output() public remove = new EventEmitter(); @Output() public update = new EventEmitter(); + @Output() + public uploadFile = new EventEmitter(); + @Output() public delete = new EventEmitter(); @@ -82,54 +68,9 @@ export class AssetComponent extends StatefulComponent implements OnInit { public editDialog = new DialogModel(); - constructor(changeDetector: ChangeDetectorRef, - private readonly appsState: AppsState, - private readonly assetsService: AssetsService, - private readonly authState: AuthService, - private readonly dialogs: DialogService - ) { - super(changeDetector, { - progress: 0 - }); - } - - public ngOnInit() { - const initFile = this.initFile; - - if (initFile) { - this.setProgress(1); - - this.assetsService.uploadFile(this.appsState.appName, initFile, this.authState.user!.token, DateTime.now()) - .subscribe(dto => { - if (Types.is(dto, AssetDto)) { - this.emitLoad(dto); - } else { - this.setProgress(dto); - } - }, error => { - this.dialogs.notifyError(error); - - this.emitLoadError(error); - }); - } - } - - public updateFile(files: FileList) { + public updateFile(files: File[]) { if (files.length === 1) { - this.setProgress(1); - - this.assetsService.replaceFile(this.appsState.appName, this.asset.id, files[0], this.asset.version) - .subscribe(dto => { - if (Types.is(dto, Versioned)) { - this.updateAsset(this.asset.update(dto.payload, this.authState.user!.token, dto.version), true); - } else { - this.setProgress(dto); - } - }, error => { - this.dialogs.notifyError(error); - - this.setProgress(0); - }); + this.uploadFile.emit(files[0]); } } @@ -151,14 +92,6 @@ export class AssetComponent extends StatefulComponent implements OnInit { this.delete.emit(this.asset); } - public emitLoad(asset: AssetDto) { - this.load.emit(asset); - } - - public emitLoadError(error: any) { - this.loadError.emit(error); - } - public emitUpdate() { this.update.emit(this.asset); } @@ -167,10 +100,6 @@ export class AssetComponent extends StatefulComponent implements OnInit { this.remove.emit(this.asset); } - private setProgress(progress: number) { - this.next(s => ({ ...s, progress })); - } - public updateAsset(asset: AssetDto, emitEvent: boolean) { this.asset = asset; @@ -178,8 +107,6 @@ export class AssetComponent extends StatefulComponent implements OnInit { this.emitUpdate(); } - this.next(s => ({ ...s, progress: 0 })); - this.cancelEdit(); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/components/assets-list.component.html b/src/Squidex/app/shared/components/assets-list.component.html index 592e44e29..abbc38f07 100644 --- a/src/Squidex/app/shared/components/assets-list.component.html +++ b/src/Squidex/app/shared/components/assets-list.component.html @@ -15,20 +15,21 @@
- - + + + + - - + diff --git a/src/Squidex/app/shared/components/assets-list.component.ts b/src/Squidex/app/shared/components/assets-list.component.ts index 674656236..1f4931b76 100644 --- a/src/Squidex/app/shared/components/assets-list.component.ts +++ b/src/Squidex/app/shared/components/assets-list.component.ts @@ -11,8 +11,7 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AssetDto, AssetsState, - DialogService, - ImmutableArray + AssetWithUpload } from '@app/shared/internal'; @Component({ @@ -22,8 +21,6 @@ import { changeDetection: ChangeDetectionStrategy.OnPush }) export class AssetsListComponent { - public newFiles = ImmutableArray.empty(); - @Input() public state: AssetsState; @@ -39,21 +36,6 @@ export class AssetsListComponent { @Output() public select = new EventEmitter(); - constructor( - private readonly dialogs: DialogService - ) { - } - - public add(file: File, asset: AssetDto) { - this.newFiles = this.newFiles.remove(file); - - if (asset.isDuplicate) { - this.dialogs.notifyError('The same asset has already been uploaded.'); - } else { - this.state.add(asset); - } - } - public search() { this.state.load().pipe(onErrorResumeNext()).subscribe(); } @@ -74,6 +56,10 @@ export class AssetsListComponent { this.state.update(asset); } + public updateFile(asset: AssetDto, file: File) { + this.state.replaceFile(asset, file).pipe(onErrorResumeNext()).subscribe(); + } + public emitSelect(asset: AssetDto) { this.select.emit(asset); } @@ -82,13 +68,9 @@ export class AssetsListComponent { return this.selectedIds && this.selectedIds[asset.id]; } - public remove(file: File) { - this.newFiles = this.newFiles.remove(file); - } - public addFiles(files: File[]) { for (let file of files) { - this.newFiles = this.newFiles.pushFront(file); + this.state.upload(file); } return true; @@ -97,5 +79,9 @@ export class AssetsListComponent { public trackByAsset(index: number, asset: AssetDto) { return asset.id; } + + public trackByUpload(index: number, upload: AssetWithUpload) { + return upload.asset.id; + } } diff --git a/src/Squidex/app/shared/components/assets-selector.component.ts b/src/Squidex/app/shared/components/assets-selector.component.ts index ec75bf464..507ea931a 100644 --- a/src/Squidex/app/shared/components/assets-selector.component.ts +++ b/src/Squidex/app/shared/components/assets-selector.component.ts @@ -10,7 +10,7 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AssetDto, - AssetsDialogState, + AssetsState, fadeAnimation, FilterState, LocalStoreService, @@ -40,7 +40,7 @@ export class AssetsSelectorComponent extends StatefulComponent implements public filter = new FilterState(); constructor(changeDector: ChangeDetectorRef, - public readonly assetsState: AssetsDialogState, + public readonly assetsState: AssetsState, public readonly localStore: LocalStoreService ) { super(changeDector, { diff --git a/src/Squidex/app/shared/declarations.ts b/src/Squidex/app/shared/declarations.ts index 5043458cf..f69259f8a 100644 --- a/src/Squidex/app/shared/declarations.ts +++ b/src/Squidex/app/shared/declarations.ts @@ -10,6 +10,7 @@ export * from './components/asset-dialog.component'; export * from './components/asset.component'; export * from './components/assets-list.component'; export * from './components/assets-selector.component'; +export * from './components/asset-uploader.component'; export * from './components/comment.component'; export * from './components/comments.component'; export * from './components/help-markdown.pipe'; diff --git a/src/Squidex/app/shared/module.ts b/src/Squidex/app/shared/module.ts index 044ad2167..21b9312e4 100644 --- a/src/Squidex/app/shared/module.ts +++ b/src/Squidex/app/shared/module.ts @@ -21,11 +21,11 @@ import { AssetComponent, AssetDialogComponent, AssetPreviewUrlPipe, - AssetsDialogState, AssetsListComponent, AssetsSelectorComponent, AssetsService, AssetsState, + AssetUploaderComponent, AssetUrlPipe, AuthInterceptor, AuthService, @@ -109,6 +109,7 @@ import { AssetUrlPipe, AssetsListComponent, AssetsSelectorComponent, + AssetUploaderComponent, CommentComponent, CommentsComponent, FileIconPipe, @@ -140,6 +141,7 @@ import { AssetUrlPipe, AssetsListComponent, AssetsSelectorComponent, + AssetUploaderComponent, CommentComponent, CommentsComponent, FileIconPipe, @@ -163,9 +165,6 @@ import { UserPicturePipe, UserPictureRefPipe, TableHeaderComponent - ], - providers: [ - AssetsDialogState ] }) export class SqxSharedModule { diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index 702954a2f..ebd4a8edc 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -23,6 +23,7 @@ describe('AssetsState', () => { const { app, appsState, + authService, creation, creator, modified, @@ -51,7 +52,7 @@ describe('AssetsState', () => { assetsService.setup(x => x.getTags(app)) .returns(() => of({ tag1: 1, shared: 2, tag2: 1 })); - assetsState = new AssetsState(appsState.object, assetsService.object, dialogs.object); + assetsState = new AssetsState(appsState.object, assetsService.object, authService.object, dialogs.object); assetsState.load().subscribe(); }); @@ -76,15 +77,6 @@ describe('AssetsState', () => { dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); }); - it('should add asset to snapshot when created', () => { - const newAsset = new AssetDto('id3', creator, creator, creation, creation, 'name3', 'hash3', 'type3', 3, 3, 'mime3', false, true, 0, 0, 'slug2', [], 'url3', version); - - assetsState.add(newAsset); - - expect(assetsState.snapshot.assets.values).toEqual([newAsset, ...oldAssets]); - expect(assetsState.snapshot.assetsPager.numberOfItems).toBe(201); - }); - it('should update properties when updated', () => { const newAsset = new AssetDto('id1', modifier, modifier, modified, modified, 'name3', 'hash3', 'type3', 3, 3, 'mime3', false, true, 0, 0, 'slug3', ['new'], 'url3', version); diff --git a/src/Squidex/app/shared/state/assets.state.ts b/src/Squidex/app/shared/state/assets.state.ts index 5c6fb58cd..5186a5e6d 100644 --- a/src/Squidex/app/shared/state/assets.state.ts +++ b/src/Squidex/app/shared/state/assets.state.ts @@ -6,20 +6,49 @@ */ import { Injectable } from '@angular/core'; -import { combineLatest, Observable } from 'rxjs'; +import { combineLatest, Observable, Subject, Subscription } from 'rxjs'; import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { + DateTime, DialogService, ImmutableArray, + MathHelper, notify, Pager, - State + State, + Types } from '@app/framework'; -import { AssetDto, AssetsService} from './../services/assets.service'; +import { AuthService } from '../services/auth.service'; +import { AssetDto, AssetsService } from './../services/assets.service'; import { AppsState } from './apps.state'; +export interface UploadingAsset { + // Unique id. + id: string; + + // The name of the asset. + name: string; + + // The upload subscription. + subscription: Subscription; + + // The progress. + progress: number; + + // Indicates if the upload has been completed. + isCompleted?: boolean; +} + +export interface AssetWithUpload { + // The asset. + asset: AssetDto; + + // The corresponding upload. + upload?: UploadingAsset; +} + interface Snapshot { // All assets tags. tags: { [name: string]: number }; @@ -27,6 +56,12 @@ interface Snapshot { // The selected asset tags. tagsSelected: { [name: string]: boolean }; + // The uploads. + uploadsDirect: ImmutableArray; + + // The uploads removed with a delay. + uploadsDelayed: ImmutableArray; + // The current assets. assets: ImmutableArray; @@ -58,6 +93,10 @@ export class AssetsState extends State { this.changes.pipe(map(x => x.assets), distinctUntilChanged()); + public assetsWithUploads = + this.changes.pipe(map(x => getAssetsWithUploads(x)), + distinctUntilChanged()); + public assetsQuery = this.changes.pipe(map(x => x.assetsQuery), distinctUntilChanged()); @@ -66,6 +105,14 @@ export class AssetsState extends State { this.changes.pipe(map(x => x.assetsPager), distinctUntilChanged()); + public uploads = + this.changes.pipe(map(x => x.uploadsDirect), + distinctUntilChanged()); + + public uploadsDelayed = + this.changes.pipe(map(x => x.uploadsDelayed), + distinctUntilChanged()); + public isLoaded = this.changes.pipe(map(x => !!x.isLoaded), distinctUntilChanged()); @@ -73,9 +120,17 @@ export class AssetsState extends State { constructor( private readonly appsState: AppsState, private readonly assetsService: AssetsService, + private readonly authService: AuthService, private readonly dialogs: DialogService ) { - super({ assets: ImmutableArray.empty(), assetsPager: new Pager(0, 0, 30), tags: {}, tagsSelected: {} }); + super({ + assets: ImmutableArray.empty(), + assetsPager: new Pager(0, 0, 30), + uploadsDirect: ImmutableArray.empty(), + uploadsDelayed: ImmutableArray.empty(), + tags: {}, + tagsSelected: {} + }); } public load(isReload = false): Observable { @@ -110,6 +165,100 @@ export class AssetsState extends State { notify(this.dialogs)); } + public remove(upload: UploadingAsset, delayed = false) { + upload.subscription.unsubscribe(); + + this.next(s => { + let uploadsDirect = s.uploadsDirect.removeBy('id', upload); + let uploadsDelayed = s.uploadsDelayed; + + if (!delayed) { + uploadsDelayed = s.uploadsDelayed.removeBy('id', upload); + } + + return { ...s, uploadsDirect, uploadsDelayed }; + }); + + if (!delayed) { + setTimeout(() => { + this.remove(upload, true); + }, 10000); + } + } + + public upload(file: File, now?: DateTime): Observable { + const observable = this.assetsService.uploadFile(this.appName, file, this.user, now || DateTime.now()); + + let upload: UploadingAsset; + + const subject = new Subject(); + const subscription = observable.subscribe(event => { + if (Types.isNumber(event)) { + this.setProgress(upload, event); + + subject.next(event); + } else { + if (event.isDuplicate) { + this.dialogs.notifyError('The same asset has already been uploaded.'); + } else { + this.add(event); + } + + subject.next(event); + } + + }, error => { + subject.error(error); + + this.remove(upload, true); + }, () => { + subject.complete(); + + this.remove(upload, true); + }); + + upload = { id: MathHelper.guid(), name: file.name, progress: 0, subscription }; + + this.addUpload(upload); + + return subject; + } + + public replaceFile(asset: AssetDto, file: File, now?: DateTime): Observable { + const observable = this.assetsService.replaceFile(this.appName, asset.id, file, asset.version); + + let upload: UploadingAsset; + + const subject = new Subject(); + const subscription = observable.subscribe(event => { + if (Types.isNumber(event)) { + this.setProgress(upload, event); + + subject.next(event); + } else { + const newAsset = asset.update(event.payload, this.user, event.version, now || DateTime.now()); + + this.update(newAsset); + + subject.next(newAsset); + } + }, error => { + subject.error(error); + + this.remove(upload, true); + }, () => { + subject.complete(); + + this.remove(upload, true); + }); + + upload = { id: asset.id, name: file.name, progress: 0, subscription }; + + this.addUpload(upload); + + return subject; + } + public add(asset: AssetDto) { this.next(s => { const assets = s.assets.pushFront(asset); @@ -224,9 +373,41 @@ export class AssetsState extends State { return Object.keys(this.snapshot.tagsSelected).length === 0; } + private setProgress(upload: UploadingAsset, progress: number) { + this.next(s => { + const newUpload = { ...upload, progress }; + + const uploadsDirect = s.uploadsDirect.replaceBy('id', newUpload); + const uploadsDelayed = s.uploadsDelayed.replaceBy('id', newUpload); + + return { ...s, uploadsDirect, uploadsDelayed }; + }); + } + + private addUpload(upload: UploadingAsset) { + this.next(s => { + const uploadsDirect = s.uploadsDirect.pushFront(upload); + const uploadsDelayed = s.uploadsDelayed.pushFront(upload); + + return { ...s, uploadsDirect, uploadsDelayed }; + }); + } + private get appName() { return this.appsState.appName; } + + private get user() { + return this.authService.user!.token; + } +} + +function getAssetsWithUploads(state: Snapshot) { + return state.assets.map(asset => { + const upload = state.uploadsDirect.find(x => x.id === x.id); + + return { upload, asset }; + }); } function addTags(asset: AssetDto, tags: { [x: string]: number; }) { @@ -262,7 +443,4 @@ function sort(tags: { [name: string]: number }) { }).map(key => { return { name: key, count: tags[key] }; }); -} - -@Injectable() -export class AssetsDialogState extends AssetsState { } \ No newline at end of file +} \ No newline at end of file diff --git a/src/Squidex/app/shell/pages/internal/apps-menu.component.html b/src/Squidex/app/shell/pages/internal/apps-menu.component.html index 59222a51b..6df3356b2 100644 --- a/src/Squidex/app/shell/pages/internal/apps-menu.component.html +++ b/src/Squidex/app/shell/pages/internal/apps-menu.component.html @@ -17,7 +17,6 @@ {{apps.length}} - diff --git a/src/Squidex/app/shell/pages/internal/internal-area.component.html b/src/Squidex/app/shell/pages/internal/internal-area.component.html index 3038d993d..74e738c30 100644 --- a/src/Squidex/app/shell/pages/internal/internal-area.component.html +++ b/src/Squidex/app/shell/pages/internal/internal-area.component.html @@ -16,6 +16,10 @@
+ +
+ +
diff --git a/src/Squidex/app/theme/icomoon/Read Me.txt b/src/Squidex/app/theme/icomoon/Read Me.txt deleted file mode 100644 index 8491652f8..000000000 --- a/src/Squidex/app/theme/icomoon/Read Me.txt +++ /dev/null @@ -1,7 +0,0 @@ -Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. - -To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts - -You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. - -You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection. diff --git a/src/Squidex/app/theme/icomoon/demo-files/demo.css b/src/Squidex/app/theme/icomoon/demo-files/demo.css index 9da135403..4000bb796 100644 --- a/src/Squidex/app/theme/icomoon/demo-files/demo.css +++ b/src/Squidex/app/theme/icomoon/demo-files/demo.css @@ -156,10 +156,10 @@ p { font-size: 32px; } .fs4 { - font-size: 20px; + font-size: 32px; } .fs5 { - font-size: 24px; + font-size: 20px; } .fs6 { font-size: 28px; diff --git a/src/Squidex/app/theme/icomoon/demo.html b/src/Squidex/app/theme/icomoon/demo.html index c575fd9ad..316c3a7d3 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: 114)

+

Font Name: icomoon (Glyphs: 119)

Grid Size: 24

+
+
+ + + + icon-upload-2 +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-translate +
+
+ + +
+
+ liga: + +
+
@@ -22,7 +54,7 @@
- +
liga: @@ -38,7 +70,7 @@
- +
liga: @@ -54,7 +86,7 @@
- +
liga: @@ -70,7 +102,7 @@
- +
liga: @@ -86,7 +118,7 @@
- +
liga: @@ -102,7 +134,7 @@
- +
liga: @@ -118,7 +150,7 @@
- +
liga: @@ -134,7 +166,7 @@
- +
liga: @@ -150,7 +182,7 @@
- +
liga: @@ -166,7 +198,7 @@
- +
liga: @@ -175,17 +207,17 @@
-

Grid Size: 14

+

Grid Size: 16

- + - icon-clone + icon-upload
- - + +
liga: @@ -194,14 +226,14 @@
- + - icon-control-Tags + icon-caret-bottom
- - + +
liga: @@ -210,14 +242,14 @@
- + - icon-control-Checkboxes + icon-caret-top
- - + +
liga: @@ -226,14 +258,14 @@
- + - icon-control-Html + icon-show
- - + +
liga: @@ -242,14 +274,14 @@
- + - icon-single-content + icon-show-all
- - + +
liga: @@ -258,14 +290,14 @@
- + - icon-multiple-content + icon-hide
- - + +
liga: @@ -274,14 +306,14 @@
- + - icon-type-Array + icon-hide-all
- - + +
liga: @@ -290,14 +322,14 @@
- + - icon-exclamation + icon-spinner2
- - + +
liga: @@ -306,14 +338,14 @@
- + - icon-orleans + icon-star-full
- - + +
liga: @@ -322,14 +354,14 @@
- + - icon-document-lock + icon-star-empty
- - + +
liga: @@ -338,14 +370,14 @@
- + - icon-document-unpublish + icon-twitter
- - + +
liga: @@ -354,14 +386,14 @@
- + - icon-angle-down + icon-hour-glass
- - + +
liga: @@ -370,14 +402,14 @@
- + - icon-angle-left + icon-spinner
- - + +
liga: @@ -386,14 +418,14 @@
- + - icon-angle-right + icon-clock
- - + +
liga: @@ -402,14 +434,14 @@
- + - icon-angle-up + icon-bin2
- - + +
liga: @@ -418,30 +450,30 @@
- + - icon-api + icon-earth
- - + +
liga: - +
- + - icon-assets + icon-elapsed
- - + +
liga: @@ -450,14 +482,14 @@
- + - icon-bug + icon-google
- - + +
liga: @@ -466,14 +498,14 @@
- + - icon-caret-down + icon-lock
- - + +
liga: @@ -482,14 +514,14 @@
- + - icon-caret-left + icon-microsoft
- - + +
liga: @@ -498,14 +530,14 @@
- + - icon-caret-right + icon-pause
- - + +
liga: @@ -514,14 +546,14 @@
- + - icon-caret-up + icon-play
- - + +
liga: @@ -530,14 +562,14 @@
- + - icon-contents + icon-reset
- - + +
liga: @@ -546,14 +578,14 @@
- + - icon-trigger-ContentChanged + icon-settings2
- - + +
liga: @@ -562,14 +594,14 @@
- + - icon-control-Date + icon-timeout
- - + +
liga: @@ -578,113 +610,113 @@
- + - icon-control-DateTime + icon-unlocked
- - + +
liga:
-
+
+
+

Grid Size: Unknown

+
- + - icon-control-Markdown + icon-prerender
- - + +
liga:
-
+
- + - icon-grid + icon-circle
- - + +
liga:
-
+
- + - icon-list1 + icon-control-Slug
- - + +
liga:
-
+
- + - icon-user-o + icon-type-Tags
- - + +
liga:
-
+
- + - icon-rules + icon-activity
- - + +
liga:
-
-
-

Grid Size: 16

- + - icon-caret-bottom + icon-history
- - + +
liga: @@ -693,14 +725,14 @@
- + - icon-caret-top + icon-time
- - + +
liga: @@ -709,14 +741,14 @@
- + - icon-show + icon-add
- - + +
liga: @@ -725,14 +757,14 @@
- + - icon-show-all + icon-plus
- - + +
liga: @@ -741,14 +773,14 @@
- + - icon-hide + icon-check-circle
- - + +
liga: @@ -757,14 +789,14 @@
- + - icon-hide-all + icon-check-circle-filled
- - + +
liga: @@ -773,14 +805,14 @@
- + - icon-spinner2 + icon-close
- - + +
liga: @@ -789,14 +821,14 @@
- + - icon-star-full + icon-type-References
- - + +
liga: @@ -805,14 +837,14 @@
- + - icon-star-empty + icon-control-Checkbox
- - + +
liga: @@ -821,14 +853,14 @@
- + - icon-twitter + icon-control-Dropdown
- - + +
liga: @@ -837,14 +869,14 @@
- + - icon-hour-glass + icon-control-Input
- - + +
liga: @@ -853,14 +885,14 @@
- + - icon-spinner + icon-control-Radio
- - + +
liga: @@ -869,14 +901,14 @@
- + - icon-clock + icon-control-TextArea
- - + +
liga: @@ -885,14 +917,14 @@
- + - icon-bin2 + icon-control-Toggle
- - + +
liga: @@ -901,30 +933,30 @@
- + - icon-earth + icon-copy
- - + +
liga: - +
- + - icon-elapsed + icon-dashboard
- - + +
liga: @@ -933,14 +965,14 @@
- + - icon-google + icon-delete
- - + +
liga: @@ -949,14 +981,14 @@
- + - icon-lock + icon-bin
- - + +
liga: @@ -965,14 +997,14 @@
- + - icon-microsoft + icon-delete-filled
- - + +
liga: @@ -981,14 +1013,14 @@
- + - icon-pause + icon-document-delete
- - + +
liga: @@ -997,14 +1029,14 @@
- + - icon-play + icon-document-disable
- - + +
liga: @@ -1013,14 +1045,14 @@
- + - icon-reset + icon-document-publish
- - + +
liga: @@ -1029,14 +1061,14 @@
- + - icon-settings2 + icon-drag
- - + +
liga: @@ -1045,14 +1077,14 @@
- + - icon-timeout + icon-filter
- - + +
liga: @@ -1061,487 +1093,535 @@
- + - icon-unlocked + icon-github
- - + +
liga:
-
-
-

Grid Size: 20

-
+
- + - icon-grid1 + icon-help
- - + +
liga:
-
+
- + - icon-list + icon-location
- - + +
liga:
-
+
- + - icon-info + icon-control-Map
- - + +
liga:
-
-
-

Grid Size: 32

-
+
- + - icon-control-Color + icon-type-Geolocation
- - + +
liga:
-
+
- + - icon-browser + icon-logo
- - + +
liga:
-
+
- + - icon-checkmark + icon-media
- - + +
liga:
-
+
- + - icon-control-Stars + icon-type-Assets
- - + +
liga:
-
-
-

Grid Size: Unknown

-
+
- + - icon-prerender + icon-trigger-AssetChanged
- - + +
liga:
-
+
- + - icon-circle + icon-more
- - + +
liga:
-
+
- + - icon-control-Slug + icon-dots
- - + +
liga:
-
+
- + - icon-type-Tags + icon-pencil
- - + +
liga:
-
+
- + - icon-activity + icon-reference
- - + +
liga:
-
+
- + - icon-history + icon-schemas
- - + +
liga:
-
+
- + - icon-time + icon-search
- - + +
liga:
-
+
- + - icon-add + icon-settings
- - + +
liga:
-
+
- + - icon-plus + icon-type-Boolean
- - + +
liga:
-
+
- + - icon-check-circle + icon-type-DateTime
- - + +
liga:
-
+
- + - icon-check-circle-filled + icon-type-Json
- - + +
liga:
-
+
- + - icon-close + icon-json
- - + +
liga:
-
+
- + - icon-type-References + icon-type-Number
- - + + +
+
+ liga: + +
+
+
+
+ + + + icon-type-String +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-user +
+
+ + +
+
+ liga: + +
+
+
+
+ + + + icon-upload-3 +
+
+ +
liga:
-
+
- + - icon-control-Checkbox + icon-upload-4
- - + +
liga:
-
+
+
+

Grid Size: 32

+
- + - icon-control-Dropdown + icon-control-Color
- - + +
liga:
-
+
- + - icon-control-Input + icon-browser
- - + +
liga:
-
+
- + - icon-control-Radio + icon-checkmark
- - + +
liga:
-
+
- + - icon-control-TextArea + icon-control-Stars
- - + +
liga:
-
+
+
+

Grid Size: 20

+
- + - icon-control-Toggle + icon-grid1
- - + +
liga:
-
+
- + - icon-copy + icon-list
- - + +
liga:
-
+
- + - icon-dashboard + icon-info
- - + +
liga:
+
+
+

Grid Size: 14

- + - icon-delete + icon-clone
- - + +
liga: @@ -1550,14 +1630,14 @@
- + - icon-bin + icon-control-Tags
- - + +
liga: @@ -1566,14 +1646,14 @@
- + - icon-delete-filled + icon-control-Checkboxes
- - + +
liga: @@ -1582,14 +1662,14 @@
- + - icon-document-delete + icon-control-Html
- - + +
liga: @@ -1598,14 +1678,14 @@
- + - icon-document-disable + icon-single-content
- - + +
liga: @@ -1614,14 +1694,14 @@
- + - icon-document-publish + icon-multiple-content
- - + +
liga: @@ -1630,14 +1710,14 @@
- + - icon-drag + icon-type-Array
- - + +
liga: @@ -1646,14 +1726,14 @@
- + - icon-filter + icon-exclamation
- - + +
liga: @@ -1662,14 +1742,14 @@
- + - icon-github + icon-orleans
- - + +
liga: @@ -1678,14 +1758,14 @@
- + - icon-help + icon-document-lock
- - + +
liga: @@ -1694,14 +1774,14 @@
- + - icon-location + icon-document-unpublish
- - + +
liga: @@ -1710,14 +1790,14 @@
- + - icon-control-Map + icon-angle-down
- - + +
liga: @@ -1726,14 +1806,14 @@
- + - icon-type-Geolocation + icon-angle-left
- - + +
liga: @@ -1742,14 +1822,14 @@
-
- - + +
liga: @@ -1758,14 +1838,14 @@
- + - icon-media + icon-angle-up
- - + +
liga: @@ -1774,14 +1854,14 @@
- + - icon-type-Assets + icon-api
- - + +
liga: @@ -1790,14 +1870,14 @@
- + - icon-trigger-AssetChanged + icon-assets
- - + +
liga: @@ -1806,14 +1886,14 @@
- + - icon-more + icon-bug
- - + +
liga: @@ -1822,14 +1902,14 @@
- + - icon-dots + icon-caret-down
- - + +
liga: @@ -1838,14 +1918,14 @@
- + - icon-pencil + icon-caret-left
- - + +
liga: @@ -1854,14 +1934,14 @@
- + - icon-reference + icon-caret-right
- - + +
liga: @@ -1870,14 +1950,14 @@
- + - icon-schemas + icon-caret-up
- - + +
liga: @@ -1886,14 +1966,14 @@
- + - icon-search + icon-contents
- - + +
liga: @@ -1902,14 +1982,14 @@
- + - icon-settings + icon-trigger-ContentChanged
- - + +
liga: @@ -1918,14 +1998,14 @@
- + - icon-type-Boolean + icon-control-Date
- - + +
liga: @@ -1934,14 +2014,14 @@
- + - icon-type-DateTime + icon-control-DateTime
- - + +
liga: @@ -1950,14 +2030,14 @@
- + - icon-type-Json + icon-control-Markdown
- - + +
liga: @@ -1966,14 +2046,14 @@
- + - icon-json + icon-grid
- - + +
liga: @@ -1982,14 +2062,14 @@
- + - icon-type-Number + icon-list1
- - + +
liga: @@ -1998,14 +2078,14 @@
- + - icon-type-String + icon-user-o
- - + +
liga: @@ -2014,14 +2094,14 @@
- + - icon-user + icon-rules
- - + +
liga: diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 8bab83dc259e112aa2388fd9ddca35003d28c791..23c4229213fdca031886c95366998184d7f25d5b 100644 GIT binary patch delta 1193 zcmZ`&OKcle6uo!ed_4Ay=VN=u6YSve#I}?ML;OuuXe&S}0t76Y3MdjdNoi8z#7Tpw z)JpaOv7w6wud*m&!zNCVP*`-)g_j5wsS6yCDqs_Vkhh1-qxWXsefQq; zj?Q`W@z40hE{dsDfNLx3Vue3-OPyIi{gKfHfIBqbo2}Ox_g}j|x&CdUdFjC~F96^T zfJ?jc7ix3XDeqrNf`Cp2Ep!!c5%a_-HQ3h7t@$9_on>#C=yYL5UUlP2q_s^Y15x^o2T$PpdW zam>yUs3S)Va=6jI=-1%J^#M|k$nZQ->~Lov zZEbGiIF4_2&TWz2X`y}xM(DnEqdGhFyHtB)-haw64;vV>r%QrFS?Yol8 z9@-^|kBuQahUEv=(Bi-|TAaYbp@+702tm0j_IzTNkho0t4I+IzilTZdCpPVz zrrT10XPl;lp3wD7)Seu%f(gSuo^sD*$6n23Urat(h(sJw;DgGsq~e8DPO;K*fbo1Z ztmWc%Ihj0>7_B-Z6Nc#ocuT7ouCB&IAyWzjIb^(`2Sbjo1p{(g!?*gs51b)dirVyu z7u^$j$ehlAXkBq5(TRAx=)|9~qv^0_2jn0oO7v%typqkoks?0S z=$srQ8p$cgnJ|r!fJF2nnoqAZ8a5@7ILNlDrF0{$>&dWU`DAo1C~v>?{#lloQE#1k zS9|tP2=Ttp@Y5gn{@MSwZ!c8w>h{BhA5osB^bSqd?tbuBvQ+r4uv@%aS}o_xtMpd_ VT*WuR@*9C`uPjBje_i|%{{wa*&#C|b delta 262 zcmZ4Rgt6r=BU?)z1H*&diEL&p!57q5PIM?2+|R(kum^|}l5-OaZhPHUop?f~{y?cF z7Xt(11O|rmgpAb06wz8HcLs)x4?uNh89)I}Ce{iDhD;40UnL{Aq+*Z1OaYMZ1JrXT zCqFq+o6GqM14A}Q{zGnJMFB$}V-y2Jjs%deke8U7I@62uH;``uRNq#RUtGe#43uHW zJphttU}k1KGdYE^n=ya#2S#PqRRY=kYd1?US*C2hn(56fvr_#+a6G@wR|aktkS2y3 p{c(?B^kkb{bH?(`CArrbCr9Uh;ND=IW4wWZ5hz{0Ij-OkBLHOUO?LnQ diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg index 19e5f0d83..ac7ef81fc 100644 --- a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg +++ b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg @@ -119,6 +119,10 @@ + + + + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index 0efafcddbc818ec1c0892cf7a2e3e02974950c1e..41e95e3a6b665e4908705a7eb3fcd49637840468 100644 GIT binary patch delta 1203 zcmZ`&OKcle6n%HzjAzE4=lOU%;|aF$cw$>hgWLFZyztH2J7I>w>UqTt=AemZ|;l{0&%pL=4&er+%>d6!(EzR zy7}Ri-Jf1Z`wk&jo-WMQE?Z;2UdPZ?^j8+}Lgs`|(B4FQc%i;}_EPzJzxPS^fs?)YV#jZvDLc58B^j!l#Ypl~n|a-^cIyenRQv zFFK#Y%GxA&!hLO7eXz9(CoeZ!BtQ(zDC$KSiguL2OHdYcA)`a5)!8F^q|<>+?^5p) zt}Tvm1X_Sp?2*Q7{qEiR?45pu-wA!wBud+Kp1ejDv1Zf^h+!BE&rN4@c^HgWpp^B} zfdrUM%TB^z6x~9ldKw1fc|;U+(<&A!W!<(4)k^6&jKdgK$)^3PcoqYu@1fJcfk3Iq z^Ai7T0~cPTRKQEeFdRV;!m=Co9sfg59z5hG-Dm%hBw?T2 z108btCgi+*RdU%wxx~P8VNi}i_<=NdIM56ar=W1Cp=}+OKwlNQKDjeUrJ}TvTq^ql zA-`=!VIJcGO*^M*wkYwGQP-S{P_EmzxVewbFm7ywk8*U0C^hS+c@c3{G&f3rNYC))8eDj TwQ|0E4gX3)Zfzx(zJvb&FM7;z delta 286 zcmezKi1EQ~#(D-u1_lOhh6V;^1_S?KeItG$-u*z4JwTk0oSRs1+v~O}0|TQBke`#D zSX=<41%UhxAkC4UQ<-+4RFezHpTNM7o{*86m?B!sMc&ODgvG%K**D^a1L*lart9n5fO=e1(A_8>HYvZem3NLmy)l&@KreUm-6sH+7~L z=Wih20;r*_AiuZ-=ujZYJphttU}iou@jy3Y{$w9UW!6;!+5BramoQqUY&OjFW|mp0 zejzxX-{va=Hw#D$!;Sv9$1r;Gj2v^u^34}=t}{;Fp7()!gK>`W25?xEZ{C%Eh!Fs! C+D+pC diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.woff b/src/Squidex/app/theme/icomoon/fonts/icomoon.woff index 28bd524641f5351065c5ea973bfce71f8b6afcdf..ec1235808ca818e45ee6a7a4ade6719075ac5f6a 100644 GIT binary patch delta 1245 zcmZuw&2Jl35P!38*Sl-)dOy70^#(h5y|FE&#t?s|Dij2$l>oIpG?k!-;-n!?h?~$9 zQPfKIi3>ddzBGsSjN*WV@();?DpaH%>VVXW3l$Yo4_puxs7~jt^L1b~v-{r6yqVwr ze!H6w;m+@1eRlf92?7MKPwtRN@VwqNE+xJ$#M=G2R%4YAXkvJo`GZprrWP7&EOsCF z(yr?Z%b$OQv4?~#Jz~D}nW<=JwPdpEfawv8TA7U@mjQ^=9kJRYF=x zJpY9G-P5Vt%PVtOcWQ+VV8u_nvzx1}##J1QMo2pFZ{UMVjn+KIa1UQFUw=pbZ*^tu z3ck&^`*jpol>XdR;7eHR-UMIxUSH9E*y_X4i|q~x5fhJ=jj{}7C$7RvP!$XzYe2u# z-yu7s--qn*{O~;9I~?H%bN~t4A**w(Ten(sUj-F7f?#fj#A%N%kT=O9_KaI0F$yE| zy-Y4&gps`lm7JdmrNC<2&Nz&$?3HTu<1n(_iZ~dST`twChGUoNwaUvd4O7@9mtkFT zEru+Xp)24pdd~Rd}O!sMVnnJ=1l~-l0~9Mg%!nA1<&OSicc;8Xy>+M~H)9(1@*V zGSjA$^a!COOi0~}dv(K?!8f+Kv(Gj+HeeDaH+ttbk?+aj_Ri=KMT&<=ae>@MivORU zBKXKnCSd=7Bw>%-eI4?}Hst+1Rr0w5xx~<}Fet~Ud|w(|>}!ULV^BKK(6J9%V6F}W zM(!+9sVF@pm&!~acvtl=7t15tQ<)xepKZYJ0nY!=dGxgPdL?7>R58T?v51<)0KEzs~MiICL$42l)@ZP zUeLo4SJ%RloYCO@;p0FVgr%r$A93M#f)|R@3xKv1FJ=`IiL#q`#j!F`&5`6VBrDE1 z!Wa_}hU_`cw3j}a%f6c{o=GDfJm?;uKp3fM*DaXFm?R>+n8x5$#-pYfLJYE_YH8ib z=z1!u*bI!$h2^ck=FigPtoq&S7qnOZCJ~R delta 342 zcmX@{m~qV=Mv-!VH#Y`G1|Z1OVc-VQxeq39EEJ!pEmFTfIXAI@fq^jtD4GMpx4mww zrY9DI#I6AO98fHfo>Q3y6uZN~ke&d-2TC=$GEx&$7#K2bfNIP@ShSYOJp(8R6e|Jp zRX~`NiM1jlx1<6nHUpxc@y;H9nSz}BWS}~~Y>>haAgs;hd?h!r0%&m#&`<^iFz#cF z%1g{m1&Xx*HMfEAOfSyg1^LB5eR(`^b<98(GxM3rJdE9p`IBcbDzmN<$mUKB6J`E9;3aI*l_GBDiek9!QGCqKzCXDr_=lY5?1Pn3Z&B_H!83A~7RzCm$ diff --git a/src/Squidex/app/theme/icomoon/selection.json b/src/Squidex/app/theme/icomoon/selection.json index 5024aa79b..acd68b247 100644 --- a/src/Squidex/app/theme/icomoon/selection.json +++ b/src/Squidex/app/theme/icomoon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M678 726h138l-70-186zM790 426l192 512h-86l-48-128h-202l-48 128h-86l192-512h86zM550 642l-34 88-132-132-214 212-60-60 218-214c-54-60-96-124-128-194h86c26 50 58 98 98 142 62-68 108-146 136-228h-478v-86h300v-84h84v84h300v86h-126c-32 100-84 196-158 278l-2 2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["translate"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59759,"name":"translate"},"setIdx":0,"setId":9,"iconIdx":0},{"icon":{"paths":["M854 470v84h-520l238 240-60 60-342-342 342-342 60 60-238 240h520z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["arrow_back"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59758,"name":"arrow_back"},"setIdx":3,"setId":6,"iconIdx":0},{"icon":{"paths":["M768 512c-25.6 0-42.667 17.067-42.667 42.667v256c0 25.6-17.067 42.667-42.667 42.667h-469.333c-25.6 0-42.667-17.067-42.667-42.667v-469.333c0-25.6 17.067-42.667 42.667-42.667h256c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-256c-72.533 0-128 55.467-128 128v469.333c0 72.533 55.467 128 128 128h469.333c72.533 0 128-55.467 128-128v-256c0-25.6-17.067-42.667-42.667-42.667z","M934.4 110.933c-4.267-8.533-12.8-17.067-21.333-21.333-4.267-4.267-12.8-4.267-17.067-4.267h-256c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h153.6l-396.8 396.8c-17.067 17.067-17.067 42.667 0 59.733 8.533 8.533 17.067 12.8 29.867 12.8s21.333-4.267 29.867-12.8l396.8-396.8v153.6c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-256c0-4.267 0-12.8-4.267-17.067z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["external-link"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59757,"name":"external-link"},"setIdx":3,"setId":6,"iconIdx":1},{"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":2,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":3,"setId":6,"iconIdx":2},{"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":3,"name":"plus-square","prevSize":24,"code":59752},"setIdx":3,"setId":6,"iconIdx":3},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":4,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":3,"setId":6,"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":5,"name":"comments","prevSize":24,"code":59743},"setIdx":3,"setId":6,"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":6,"prevSize":24,"code":59739,"name":"backup"},"setIdx":3,"setId":6,"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":7,"prevSize":24,"code":59738,"name":"support"},"setIdx":3,"setId":6,"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":8,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":3,"setId":6,"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":9,"prevSize":24,"code":59710,"name":"download"},"setIdx":3,"setId":6,"iconIdx":9},{"icon":{"paths":["M66.337 575.491l276.668-171.531v-57.177l-331.627 207.614v42.189l331.627 207.614-0-57.177z","M957.663 575.49l-276.668-171.531v-57.177l331.627 207.614v42.189l-331.627 207.614 0-57.177z","M583.295 214.183l-200.825 621.623 53.007 17.527 200.837-621.623z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["prerender"],"grid":0},"attrs":[{},{},{}],"properties":{"order":114,"id":0,"name":"prerender","prevSize":32,"code":59724},"setIdx":1,"setId":8,"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,"tags":["circle"],"grid":0},"attrs":[{}],"properties":{"order":106,"id":1,"name":"circle","prevSize":32,"code":59729},"setIdx":1,"setId":8,"iconIdx":1},{"icon":{"paths":["M512 0c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h128v870.4h-128c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h307.2c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-128v-870.4h128c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.16 0-51.2 23.040-51.2 51.2v460.8c0 28.16 23.040 51.2 51.2 51.2h537.6v-51.2h-512c-15.36 0-25.6-10.24-25.6-25.6v-409.6c0-15.36 10.24-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c15.36 0 25.6 10.24 25.6 25.6v409.6c0 15.36-10.24 25.6-25.6 25.6h-204.8v51.2h230.4c28.16 0 51.2-23.040 51.2-51.2v-460.8c0-28.16-23.040-51.2-51.2-51.2h-230.4z","M386.56 606.72c0 12.8-7.68 23.040-20.48 25.6-28.16 10.24-58.88 15.36-92.16 15.36-35.84 0-66.56-10.24-84.48-25.6s-25.6-38.4-25.6-66.56 10.24-51.2 25.6-66.56c17.92-17.92 46.080-23.040 84.48-23.040h69.12v-38.4c0-35.84-25.6-53.76-64-53.76-23.040 0-46.080 7.68-69.12 20.48-2.56 2.56-5.12 2.56-10.24 2.56-10.24 0-20.48-7.68-20.48-20.48 0-7.68 2.56-12.8 10.24-17.92 30.72-20.48 61.44-25.6 92.16-25.6 56.32 0 104.96 30.72 104.96 92.16v181.76zM345.6 501.76h-69.12c-61.44 0-69.12 28.16-69.12 53.76s7.68 56.32 69.12 56.32c23.040 0 46.080-2.56 69.12-10.24v-99.84z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Slug"],"grid":0},"attrs":[{},{}],"properties":{"order":103,"id":2,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":1,"setId":8,"iconIdx":2},{"icon":{"paths":["M295.954 822.751h-94.705c-47.353 0-88.786-41.434-88.786-88.786v-491.283c0-47.353 41.434-88.786 88.786-88.786h94.705v-59.191h-94.705c-82.867 0-147.977 65.11-147.977 147.977v491.283c0 82.867 65.11 147.977 147.977 147.977h94.705v-59.191z","M970.728 473.526c-82.867-171.653-201.249-378.821-272.277-378.821h-112.462v59.191h112.462c35.514 11.838 136.139 177.572 213.087 337.387-76.948 153.896-177.572 325.549-213.087 337.387h-112.462v59.191h112.462c71.029 0 183.491-207.168 272.277-384.74l5.919-11.838-5.919-17.757z","M266.358 337.341v260.462h59.191v-260.462z","M479.422 337.341v260.462h59.191v-260.462z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["Tags"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":98,"id":3,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":1,"setId":8,"iconIdx":3},{"icon":{"paths":["M512 102.4c-200.4 0-366.954 144.072-402.4 334.2-0.031 0.165-0.069 0.335-0.1 0.5-2.974 16.061-4.76 32.441-5.8 49.1-0.017 0.271-0.084 0.529-0.1 0.8 0.019 0.004 0.080-0.004 0.1 0-0.503 8.31-1.3 16.564-1.3 25 0 226.202 183.398 409.6 409.6 409.6 208.165 0 379.707-155.44 405.8-356.5 0.004-0.033-0.004-0.067 0-0.1 1.94-14.978 3.124-30.16 3.4-45.6 0.044-2.487 0.4-4.903 0.4-7.4 0-226.202-183.398-409.6-409.6-409.6zM512 153.6c185.461 0 337.902 140.924 356.4 321.5-35.181-21.812-84.232-39.9-151.6-39.9-85.35 0-140.891 41.606-194.6 81.9-49.152 36.864-95.55 71.7-163.8 71.7-86.067 0-135.862-54.67-175.9-98.6-9.001-9.901-17.11-17.483-25.4-25.3 23.131-175.603 172.981-311.3 354.9-311.3zM716.8 486.4c77.828 0 125.173 28.221 152.2 52.8-13.96 185.173-168.254 331.2-357 331.2-190.097 0-345.175-148.14-357.2-335.2 41.826 45.372 102.577 104.8 203.6 104.8 85.35 0 140.891-41.606 194.6-81.9 49.152-36.915 95.55-71.7 163.8-71.7z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["activity"],"grid":0},"attrs":[{}],"properties":{"order":12,"id":4,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":1,"setId":8,"iconIdx":4},{"icon":{"paths":["M512 0c-35.392 0-64 28.608-64 64v384h-384c-35.392 0-64 28.608-64 64s28.608 64 64 64h384v384c0 35.392 28.608 64 64 64s64-28.608 64-64v-384h384c35.392 0 64-28.608 64-64s-28.608-64-64-64h-384v-384c0-35.392-28.608-64-64-64z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["add"],"grid":0},"attrs":[{}],"properties":{"order":13,"id":5,"name":"add, plus","prevSize":32,"code":59653},"setIdx":1,"setId":8,"iconIdx":5},{"icon":{"paths":["M512 102.4c-226.202 0-409.6 183.398-409.6 409.6s183.398 409.6 409.6 409.6c226.202 0 409.6-183.398 409.6-409.6s-183.398-409.6-409.6-409.6zM512 153.6c197.632 0 358.4 160.819 358.4 358.4s-160.768 358.4-358.4 358.4c-197.632 0-358.4-160.819-358.4-358.4s160.768-358.4 358.4-358.4zM691.9 333c-12.893 0.002-25.782 4.882-35.5 14.6l-222.2 221.9-67.7-67.5c-19.19-19.294-51.085-19.215-70.3 0-19.15 19.15-19.15 51.050 0 70.2 0.198 0.2 26.198 26.681 52 53 12.95 13.209 25.761 26.372 35.2 36 4.719 4.814 8.607 8.755 11.2 11.4 1.296 1.322 2.293 2.281 2.9 2.9 0.279 0.282 0.488 0.486 0.6 0.6 0.001 0.001 7.591-7.429 14.6-14.3l-14.5 14.4 0.2 0.2v0.1c19.43 19.327 51.57 19.327 71 0v-0.1l258.1-257.6c19.546-19.447 19.521-51.885-0.1-71.3-9.731-9.679-22.607-14.502-35.5-14.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle"],"grid":0},"attrs":[{}],"properties":{"order":14,"id":6,"name":"check-circle","prevSize":32,"code":59654},"setIdx":1,"setId":8,"iconIdx":6},{"icon":{"paths":["M512 1024c-282.778 0-512-229.222-512-512s229.222-512 512-512 512 229.222 512 512-229.222 512-512 512zM855.808 270.592c-19.2-19.2-50.278-19.2-69.478 0l-376.73 376.73-171.878-171.93c-19.2-19.2-50.278-19.2-69.478 0s-19.2 50.278 0 69.478c0 0 201.523 205.261 204.8 208.486 9.984 10.138 23.347 14.643 36.557 14.080 13.21 0.563 26.573-3.942 36.608-14.029 3.277-3.226 409.6-413.286 409.6-413.286 19.2-19.2 19.2-50.33 0-69.53z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle-filled"],"grid":0},"attrs":[{}],"properties":{"order":27,"id":7,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":1,"setId":8,"iconIdx":7},{"icon":{"paths":["M601.024 512l276.736 276.736c24.512 24.576 24.512 64.384 0 89.024-24.64 24.576-64.384 24.576-89.024 0l-276.736-276.736-276.736 276.736c-24.512 24.576-64.384 24.576-89.024 0-24.512-24.64-24.512-64.448 0-89.024l276.736-276.736-276.736-276.736c-24.512-24.576-24.512-64.384 0-89.024 24.64-24.576 64.512-24.576 89.024 0l276.736 276.736 276.736-276.736c24.64-24.576 64.384-24.576 89.024 0 24.512 24.64 24.512 64.448 0 89.024l-276.736 276.736z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["close"],"grid":0},"attrs":[{}],"properties":{"order":28,"id":8,"name":"close","prevSize":32,"code":59656},"setIdx":1,"setId":8,"iconIdx":8},{"icon":{"paths":["M409.6 435.2h-153.6v51.2h153.6v-51.2zM409.6 332.8h-153.6v51.2h153.6v-51.2zM256 691.2h409.6v-51.2h-409.6v51.2zM409.6 230.4h-153.6v51.2h153.6v-51.2zM870.4 179.2h-51.2v-51.2c0-28.262-22.938-51.2-51.2-51.2h-614.4c-28.262 0-51.2 22.938-51.2 51.2v665.6c0 28.262 22.938 51.2 51.2 51.2h51.2v51.2c0 28.262 22.938 51.2 51.2 51.2h614.4c28.262 0 51.2-22.938 51.2-51.2v-665.6c0-28.262-22.938-51.2-51.2-51.2zM179.2 793.6c-14.157 0-25.6-11.443-25.6-25.6v-614.4c0-14.131 11.443-25.6 25.6-25.6h563.2c14.157 0 25.6 11.469 25.6 25.6v614.4c0 14.157-11.443 25.6-25.6 25.6h-563.2zM870.4 870.4c0 14.157-11.443 25.6-25.6 25.6h-563.2c-14.157 0-25.6-11.443-25.6-25.6v-25.6h512c28.262 0 51.2-22.938 51.2-51.2v-563.2h25.6c14.157 0 25.6 11.469 25.6 25.6v614.4zM614.4 230.4h-102.4c-28.262 0-51.2 22.938-51.2 51.2v153.6c0 28.262 22.938 51.2 51.2 51.2h102.4c28.262 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.938-51.2-51.2-51.2zM614.4 435.2h-102.4v-153.6h102.4v153.6zM256 588.8h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":0},"attrs":[{}],"properties":{"order":37,"id":9,"name":"type-References","prevSize":32,"code":59657},"setIdx":1,"setId":8,"iconIdx":9},{"icon":{"paths":["M793.6 844.8c0 14.157-11.443 25.6-25.6 25.6h-665.6c-14.131 0-25.6-11.443-25.6-25.6v-665.6c0-14.157 11.469-25.6 25.6-25.6h665.6c14.157 0 25.6 11.443 25.6 25.6v102.4h51.2v-128c0-28.262-22.938-51.2-51.2-51.2h-716.8c-28.262 0-51.2 22.938-51.2 51.2v716.8c0 28.262 22.938 51.2 51.2 51.2h716.8c28.262 0 51.2-22.938 51.2-51.2v-281.6h-51.2v256zM991.078 237.747c-9.958-9.958-26.035-9.958-35.968 0l-391.91 391.91-238.31-238.31c-9.958-9.958-26.061-9.958-35.942 0-9.958 9.907-9.958 26.010 0 35.942l254.874 254.874c0.461 0.538 0.614 1.203 1.126 1.69 5.043 5.018 11.674 7.475 18.278 7.373 6.605 0.102 13.235-2.355 18.278-7.373 0.512-0.512 0.666-1.178 1.126-1.69l408.448-408.474c9.933-9.933 9.933-26.035 0-35.942z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-checkbox"],"grid":0},"attrs":[{}],"properties":{"order":38,"id":10,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":1,"setId":8,"iconIdx":10},{"icon":{"paths":["M51.2 0c-28.262 0-51.2 22.938-51.2 51.2v281.6c0 28.262 22.938 51.2 51.2 51.2h921.6c28.262 0 51.2-22.938 51.2-51.2v-281.6c0-28.262-22.938-51.2-51.2-51.2h-921.6zM76.8 51.2h512v281.6h-512c-14.157 0-25.6-11.443-25.6-25.6v-230.4c0-14.157 11.443-25.6 25.6-25.6zM640 51.2h307.2c14.157 0 25.6 11.443 25.6 25.6v230.4c0 14.157-11.443 25.6-25.6 25.6h-307.2v-281.6zM716.8 153.6c-0.41 0.358 89.139 102.938 89.6 102.4 0.512 0 89.6-95.36 89.6-102.4 0 0.384-172.16 0-179.2 0zM128 435.2c-42.394 0-76.8 34.406-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.406 76.8-76.8s-34.406-76.8-76.8-76.8zM128 486.4c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 486.4c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 640c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 691.2c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 691.2c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 844.8c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 896c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 896c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-dropdown"],"grid":0},"attrs":[{}],"properties":{"order":39,"id":11,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":1,"setId":8,"iconIdx":11},{"icon":{"paths":["M512 0c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h128v870.4h-128c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h307.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-128v-870.4h128c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.262 0-51.2 22.938-51.2 51.2v460.8c0 28.262 22.938 51.2 51.2 51.2h537.6v-51.2h-512c-14.131 0-25.6-11.443-25.6-25.6v-409.6c0-14.157 11.469-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c14.157 0 25.6 11.443 25.6 25.6v409.6c0 14.157-11.443 25.6-25.6 25.6h-204.8v51.2h230.4c28.262 0 51.2-22.938 51.2-51.2v-460.8c0-28.262-22.938-51.2-51.2-51.2h-230.4zM285.9 307c-0.589 0.051-1.161 0.048-1.75 0.15-8.243 0.051-16.396 4.474-20.85 13.050l-132.55 306.25c-6.656 12.749-2.866 28.981 8.5 36.2 11.341 7.219 25.97 2.749 32.6-10l27.65-63.85h170.5c0.512 0 0.914-0.224 1.4-0.25l27.45 64.050c6.63 12.749 21.136 17.269 32.4 10.050s15.005-23.451 8.4-36.2l-131.3-306.25c-4.454-8.576-12.432-12.973-20.65-13.050-0.614-0.102-1.211-0.099-1.8-0.15zM285.9 389.15l63.65 148.45h-127.9l64.25-148.45z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-input"],"grid":0},"attrs":[{}],"properties":{"order":41,"id":12,"name":"control-Input","prevSize":32,"code":59660},"setIdx":1,"setId":8,"iconIdx":12},{"icon":{"paths":["M153.6 716.8c-84.787 0-153.6 68.813-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.813 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 972.8c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM153.6 0c-84.787 0-153.6 68.787-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.787 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 256c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 358.4c-84.787 0-153.6 68.787-153.6 153.6 0 84.787 68.813 153.6 153.6 153.6s153.6-68.813 153.6-153.6c0-84.813-68.813-153.6-153.6-153.6zM153.6 614.4c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 102.4c-28.262 0-51.2 22.938-51.2 51.2s22.938 51.2 51.2 51.2c28.262 0 51.2-22.938 51.2-51.2s-22.938-51.2-51.2-51.2zM998.4 844.8h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-radio"],"grid":0},"attrs":[{}],"properties":{"order":42,"id":13,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":1,"setId":8,"iconIdx":13},{"icon":{"paths":["M0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8h-204.8zM819.2 0v204.8h204.8v-204.8h-204.8zM51.2 51.2h102.4v102.4h-102.4v-102.4zM870.4 51.2h102.4v102.4h-102.4v-102.4zM281.6 76.8v51.2h102.4v-51.2h-102.4zM486.4 76.8v51.2h102.4v-51.2h-102.4zM691.2 76.8v51.2h102.4v-51.2h-102.4zM333.25 204.8c-7.091-0.307-14.348 2.097-19.75 7.55l-74.75 74.75c-10.317 10.291-10.317 27.083 0 37.4s27.059 10.317 37.35 0l68.45-68.5h141.85v486.4h-50.7c-7.117-0.307-14.348 2.097-19.75 7.55l-23.6 23.55c-10.317 10.317-10.317 27.083 0 37.4 10.291 10.317 27.109 10.317 37.4 0l17.25-17.3h129.75l18.050 18c10.394 10.368 27.181 10.368 37.6 0 10.368-10.394 10.368-27.181 0-37.6l-24-24c-5.478-5.478-12.682-7.907-19.85-7.6h-50.95v-486.4h141.55l69.25 69.2c10.394 10.368 27.155 10.368 37.6 0 10.368-10.368 10.368-27.181 0-37.6l-75.2-75.2c-5.478-5.478-12.706-7.907-19.9-7.6h-357.65zM896 281.6v102.4h51.2v-102.4h-51.2zM76.8 384v102.4h51.2v-102.4h-51.2zM896 486.4v102.4h51.2v-102.4h-51.2zM76.8 588.8v102.4h51.2v-102.4h-51.2zM896 691.2v102.4h51.2v-102.4h-51.2zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6h-51.2zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8h-204.8zM51.2 870.4h102.4v102.4h-102.4v-102.4zM870.4 870.4h102.4v102.4h-102.4v-102.4zM384 896v51.2h102.4v-51.2h-102.4zM588.8 896v51.2h102.4v-51.2h-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-textarea"],"grid":0},"attrs":[{}],"properties":{"order":17,"id":14,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":1,"setId":8,"iconIdx":14},{"icon":{"paths":["M332.8 25.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 76.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM332.8 128c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM332.8 179.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8zM332.8 537.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 588.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM691.2 640c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM691.2 691.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-toggle"],"grid":0},"attrs":[{}],"properties":{"order":16,"id":15,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":1,"setId":8,"iconIdx":15},{"icon":{"paths":["M204.8 51.2c-56.525 0-102.4 45.875-102.4 102.4v512c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4h-409.6zM204.8 102.4h409.6c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2v-512c0-28.314 22.938-51.2 51.2-51.2zM768 204.8v51.2c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2h-51.2c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["copy"],"grid":0},"attrs":[{}],"properties":{"order":90,"id":16,"name":"copy","prevSize":32,"code":59664},"setIdx":1,"setId":8,"iconIdx":16},{"icon":{"paths":["M828.8 1024h-633.6c-105.6 0-195.2-89.6-195.2-195.2v-320c0-281.6 227.2-508.8 505.6-508.8 288 0 518.4 230.4 518.4 518.4v310.4c0 105.6-89.6 195.2-195.2 195.2zM505.6 64c-243.2 0-441.6 198.4-441.6 441.6v320c0 73.6 60.8 134.4 131.2 134.4h630.4c73.6 0 131.2-60.8 131.2-131.2v-310.4c3.2-249.6-201.6-454.4-451.2-454.4z","M512 668.8c-3.2 0-6.4 0-6.4 0-32-3.2-64-19.2-80-48l-192-278.4c-9.6-9.6-9.6-25.6-0-38.4 9.6-9.6 25.6-12.8 38.4-6.4l294.4 172.8c28.8 16 48 44.8 51.2 76.8s-6.4 64-28.8 89.6c-19.2 22.4-48 32-76.8 32zM364.8 428.8l108.8 160c6.4 9.6 19.2 19.2 32 19.2s25.6-3.2 35.2-12.8c9.6-9.6 12.8-22.4 9.6-35.2s-9.6-22.4-19.2-32l-166.4-99.2z","M678.4 364.8c-6.4 0-12.8-3.2-19.2-6.4-16-9.6-19.2-28.8-9.6-44.8l54.4-83.2c9.6-16 28.8-19.2 44.8-9.6 19.2 12.8 22.4 35.2 12.8 48l-54.4 83.2c-6.4 9.6-16 12.8-28.8 12.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["dashboard"],"grid":0},"attrs":[{},{},{}],"properties":{"order":26,"id":17,"name":"dashboard","prevSize":32,"code":59665},"setIdx":1,"setId":8,"iconIdx":17},{"icon":{"paths":["M597.35 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.418 25.6 25.6 25.6zM776.55 204.8h-153.6v-51.2c0-28.314-22.886-51.2-51.2-51.2h-102.4c-28.262 0-51.2 22.886-51.2 51.2v51.2h-153.6c-28.262 0-51.2 22.886-51.2 51.2v102.4c0 28.314 22.938 51.2 51.2 51.2v460.8c0 28.314 22.938 51.2 51.2 51.2h409.6c28.314 0 51.2-22.886 51.2-51.2v-460.8c28.314 0 51.2-22.886 51.2-51.2v-102.4c0-28.314-22.938-51.2-51.2-51.2zM469.35 153.6h102.4v51.2h-102.4v-51.2zM725.35 870.4h-409.6v-460.8h409.6v460.8zM776.55 358.4h-512v-102.4h512v102.4zM443.75 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete"],"grid":0},"attrs":[{}],"properties":{"order":29,"id":18,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":1,"setId":8,"iconIdx":18},{"icon":{"paths":["M832 128h-192v-64c0-35.392-28.608-64-64-64h-128c-35.328 0-64 28.608-64 64v64h-192c-35.328 0-64 28.608-64 64v128c0 35.392 28.672 64 64 64v512c0 35.392 28.672 64 64 64h512c35.392 0 64-28.608 64-64v-512c35.392 0 64-28.608 64-64v-128c0-35.392-28.608-64-64-64zM448 64h128v64h-128v-64zM448 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM640 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM832 320h-640v-128h640v128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete-filled"],"grid":0},"attrs":[{}],"properties":{"order":36,"id":19,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":1,"setId":8,"iconIdx":19},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c98.816 0 179.2 80.384 179.2 179.2s-80.384 179.2-179.2 179.2c-98.816 0-179.2-80.384-179.2-179.2s80.384-179.2 179.2-179.2zM227.2 665.6c-12.39 0-22.4 10.061-22.4 22.4v6.4c0 12.39 10.010 22.4 22.4 22.4h211.2c12.39 0 22.4-10.010 22.4-22.4v-6.4c0-12.39-10.061-22.4-22.4-22.4h-211.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-delete"],"grid":0},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":1,"setId":8,"iconIdx":20},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c39.934 0 76.475 13.533 106.3 35.7l-250.4 249c-21.807-29.683-35.1-65.924-35.1-105.5 0-98.816 80.384-179.2 179.2-179.2zM477 585.7c21.785 29.674 35 65.947 35 105.5 0 98.816-80.384 179.2-179.2 179.2-39.906 0-76.386-13.561-106.2-35.7l250.4-249z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-disable"],"grid":0},"attrs":[{}],"properties":{"order":40,"id":21,"name":"document-disable","prevSize":32,"code":59669},"setIdx":1,"setId":8,"iconIdx":21},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2l-230.4-256zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7l161.5-179.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-publish"],"grid":0},"attrs":[{}],"properties":{"order":44,"id":22,"name":"document-publish","prevSize":32,"code":59670},"setIdx":1,"setId":8,"iconIdx":22},{"icon":{"paths":["M665.6 51.2v102.4h102.4v-102.4h-102.4zM460.8 153.6h102.4v-102.4h-102.4v102.4zM460.8 358.4h102.4v-102.4h-102.4v102.4zM665.6 358.4h102.4v-102.4h-102.4v102.4zM665.6 563.2h102.4v-102.4h-102.4v102.4zM460.8 563.2h102.4v-102.4h-102.4v102.4zM460.8 768h102.4v-102.4h-102.4v102.4zM665.6 768h102.4v-102.4h-102.4v102.4zM665.6 972.8h102.4v-102.4h-102.4v102.4zM460.8 972.8h102.4v-102.4h-102.4v102.4zM256 153.6h102.4v-102.4h-102.4v102.4zM256 358.4h102.4v-102.4h-102.4v102.4zM256 563.2h102.4v-102.4h-102.4v102.4zM256 768h102.4v-102.4h-102.4v102.4zM256 972.8h102.4v-102.4h-102.4v102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag"],"grid":0},"attrs":[{}],"properties":{"order":43,"id":23,"name":"drag","prevSize":32,"code":59671},"setIdx":1,"setId":8,"iconIdx":23},{"icon":{"paths":["M921.6 281.958c0-70.707-171.878-128.154-384-128.154s-384 57.19-384 127.898c0 10.035 3.789 19.712 10.342 29.030 0-0.051 296.858 406.067 296.858 406.067v256l153.6-51.2v-204.8c0 0 298.752-408.166 299.725-409.702 0 0 7.475-16.64 7.475-25.139zM537.6 204.8c206.899 0 318.208 53.248 332.083 76.8-13.875 23.552-125.184 76.8-332.083 76.8s-318.208-53.248-332.083-76.8c13.875-23.552 125.184-76.8 332.083-76.8zM869.376 345.856v0 0zM573.030 686.592c-6.4 8.755-9.83 19.354-9.83 30.208v167.885l-51.2 17.050v-184.934c0-10.854-3.43-21.453-9.83-30.208l-228.147-312.115c68.762 21.709 161.382 35.123 263.578 35.123 102.298 0 195.021-13.414 263.834-35.174-0.102 0.051-0.205 0.051-0.307 0.102l-228.096 312.064z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["filter"],"grid":0},"attrs":[{}],"properties":{"order":18,"id":24,"name":"filter","prevSize":32,"code":59672},"setIdx":1,"setId":8,"iconIdx":24},{"icon":{"paths":["M512 0c-282.88 0-512 229.248-512 512 0 226.24 146.688 418.112 350.080 485.76 25.6 4.8 35.008-11.008 35.008-24.64 0-12.16-0.448-44.352-0.64-87.040-142.464 30.912-172.48-68.672-172.48-68.672-23.296-59.136-56.96-74.88-56.96-74.88-46.4-31.744 3.584-31.104 3.584-31.104 51.392 3.584 78.4 52.736 78.4 52.736 45.696 78.272 119.872 55.68 149.12 42.56 4.608-33.088 17.792-55.68 32.448-68.48-113.728-12.8-233.216-56.832-233.216-252.992 0-55.872 19.84-101.568 52.672-137.408-5.76-12.928-23.040-64.96 4.48-135.488 0 0 42.88-13.76 140.8 52.48 40.96-11.392 84.48-17.024 128-17.28 43.52 0.256 87.040 5.888 128 17.28 97.28-66.24 140.16-52.48 140.16-52.48 27.52 70.528 10.24 122.56 5.12 135.488 32.64 35.84 52.48 81.536 52.48 137.408 0 196.672-119.68 240-233.6 252.608 17.92 15.36 34.56 46.72 34.56 94.72 0 68.48-0.64 123.52-0.64 140.16 0 13.44 8.96 29.44 35.2 24.32 204.864-67.136 351.424-259.136 351.424-485.056 0-282.752-229.248-512-512-512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["brand","github"],"grid":0},"attrs":[{}],"properties":{"order":77,"id":25,"name":"github","prevSize":32,"code":59713},"setIdx":1,"setId":8,"iconIdx":25},{"icon":{"paths":["M512 512h-204.8v51.2h204.8v-51.2zM768 153.6h-51.2c0-28.314-22.886-51.2-51.2-51.2h-307.2c-28.314 0-51.2 22.886-51.2 51.2h-51.2c-28.314 0-51.2 22.886-51.2 51.2v665.6c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-665.6c0-28.314-22.886-51.2-51.2-51.2zM358.4 153.6h307.2v51.2h-307.2v-51.2zM768 819.2c0 28.314-22.886 51.2-51.2 51.2h-409.6c-28.314 0-51.2-22.886-51.2-51.2v-563.2c0-28.314 22.886-51.2 51.2-51.2 0 28.314 22.886 51.2 51.2 51.2h307.2c28.314 0 51.2-22.886 51.2-51.2 28.314 0 51.2 22.886 51.2 51.2v563.2zM307.2 460.8h409.6v-51.2h-409.6v51.2zM307.2 665.6h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["help"],"grid":0},"attrs":[{}],"properties":{"order":19,"id":26,"name":"help","prevSize":32,"code":59673},"setIdx":1,"setId":8,"iconIdx":26},{"icon":{"paths":["M512 0c-169.421 0-307.2 137.779-307.2 307.2 0 78.643 15.258 164.915 45.261 256.41 23.859 72.55 56.986 148.582 98.56 226.099 70.707 131.635 140.339 220.774 143.309 224.512 4.813 6.195 12.288 9.779 20.070 9.779 7.834 0 15.258-3.584 20.122-9.779 2.97-3.686 72.602-92.826 143.309-224.512 41.574-77.517 74.701-153.549 98.56-226.099 29.952-91.494 45.21-177.766 45.21-256.41 0-169.421-137.83-307.2-307.2-307.2zM630.682 764.672c-46.234 86.374-92.979 154.982-118.682 190.822-25.6-35.635-72.038-103.885-118.221-189.952-62.874-117.146-137.779-291.738-137.779-458.342 0-141.158 114.842-256 256-256s256 114.842 256 256c0 166.298-74.65 340.582-137.318 457.472zM512 153.6c-84.685 0-153.6 68.915-153.6 153.6s68.915 153.6 153.6 153.6 153.6-68.915 153.6-153.6-68.915-153.6-153.6-153.6zM512 409.6c-56.525 0-102.4-45.875-102.4-102.4 0-56.474 45.875-102.4 102.4-102.4 56.474 0 102.4 45.926 102.4 102.4 0 56.525-45.926 102.4-102.4 102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["location"],"grid":0},"attrs":[{}],"properties":{"order":25,"id":27,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":1,"setId":8,"iconIdx":27},{"icon":{"paths":["M512.273 83.782c-0.141 0.056-182.959 84.073-229.418 256.782-4.481 16.584 32.696 9.296 31.036 27.527-2.034 22.136-44.668 31.201-39.109 94.764 5.659 64.734 60.321 130.141 68.527 169.673v27.655c-0.497 8.54-4.566 31.715-18.018 43.036-7.378 6.19-17.322 8.421-30.436 6.782-18.205-2.275-25.449-14.468-28.345-24.309-4.753-16.218-0.322-35.123 10.345-44 10.724-8.924 12.17-24.842 3.236-35.564-8.934-10.712-24.858-12.161-35.582-3.218-25.995 21.64-36.887 61.52-26.491 97 9.815 33.392 36.197 55.884 70.6 60.182 4.903 0.609 9.566 0.909 14 0.909 26.623 0 44.661-10.175 55.582-19.455 32.866-27.97 35.449-74.593 35.636-79.818 0.009-0.309 0.018-0.618 0.018-0.927v-21.218h0.109v-1.418c0-12.351 10.008-22.364 22.382-22.364 11.944 0 21.609 9.346 22.273 21.109v202.491c-0.206 2.912-2.536 29.892-17.891 42.945-7.368 6.274-17.384 8.53-30.545 6.873-18.214-2.275-25.476-14.468-28.364-24.291-4.762-16.228-0.322-35.151 10.345-44.018 10.724-8.933 12.188-24.833 3.255-35.564-8.924-10.694-24.876-12.161-35.6-3.218-26.013 21.631-36.887 61.52-26.491 97 9.796 33.392 36.197 55.893 70.6 60.2 4.903 0.609 9.566 0.891 14 0.891 26.623 0 44.671-10.156 55.564-19.436 32.875-27.97 35.458-74.611 35.636-79.836 0.019-0.328 0.018-0.609 0.018-0.909v-225.636l0.127-0.055v-1c0-12.595 10.219-22.8 22.836-22.8 12.349 0 22.333 9.824 22.727 22.073v227.418c0 0.309-0 0.591 0.018 0.909 0.187 5.216 2.779 51.866 35.655 79.836 10.912 9.28 28.959 19.436 55.582 19.436 4.443 0 9.088-0.282 13.982-0.891 34.394-4.307 60.804-26.818 70.6-60.2 10.405-35.48-0.487-75.36-26.491-97-10.743-8.943-26.676-7.466-35.6 3.218-8.934 10.74-7.488 26.63 3.236 35.564 10.668 8.868 15.135 27.79 10.364 44.018-2.878 9.823-10.159 22.015-28.364 24.291-13.105 1.648-23.050-0.592-30.418-6.782-13.508-11.358-17.558-34.657-18.036-43v-201.818c0.297-12.093 10.14-21.818 22.327-21.818 12.374 0 22.4 10.003 22.4 22.364v1.418h0.073v21.218c0 0.318-0 0.628 0.018 0.927 0.178 5.216 2.779 51.848 35.655 79.818 10.912 9.28 28.941 19.455 55.564 19.455 4.434 0 9.107-0.292 14-0.891 34.394-4.298 60.786-26.818 70.582-60.2 10.405-35.48-0.487-75.351-26.491-97-10.743-8.933-26.667-7.476-35.582 3.236-8.943 10.722-7.488 26.622 3.236 35.545 10.668 8.877 15.117 27.8 10.345 44.018-2.878 9.842-10.159 22.025-28.364 24.291-13.086 1.648-23.050-0.583-30.418-6.764-13.508-11.368-17.549-34.675-18.018-43v-21.018c5.305-54.103 63.095-107.777 69.091-176.364 5.531-63.563-37.121-72.627-39.145-94.764-1.669-18.232 35.498-10.944 31.036-27.527-46.468-172.709-229.269-256.726-229.4-256.782z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["logo"],"grid":0},"attrs":[{}],"properties":{"order":31,"id":28,"name":"logo","prevSize":32,"code":59676},"setIdx":1,"setId":8,"iconIdx":28},{"icon":{"paths":["M947.2 0h-870.4c-42.342 0-76.8 34.458-76.8 76.8v870.4c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-870.4c0-42.342-34.458-76.8-76.8-76.8zM972.8 947.2c0 14.157-11.443 25.6-25.6 25.6h-870.4c-14.131 0-25.6-11.443-25.6-25.6v-870.4c0-14.131 11.469-25.6 25.6-25.6h870.4c14.157 0 25.6 11.469 25.6 25.6v870.4zM665.6 460.8c56.448 0 102.4-45.926 102.4-102.4s-45.952-102.4-102.4-102.4c-56.448 0-102.4 45.926-102.4 102.4s45.952 102.4 102.4 102.4zM665.6 307.2c28.211 0 51.2 22.989 51.2 51.2s-22.989 51.2-51.2 51.2c-28.211 0-51.2-22.989-51.2-51.2s22.989-51.2 51.2-51.2zM896 102.4h-768c-14.131 0-25.6 11.469-25.6 25.6v614.4c0 14.157 11.469 25.6 25.6 25.6h768c14.157 0 25.6-11.443 25.6-25.6v-614.4c0-14.131-11.443-25.6-25.6-25.6zM153.6 716.8v-118.246l164.301-184.858c4.198-4.787 9.728-7.373 15.462-7.475 5.734-0.051 11.29 2.458 15.642 7.040l283.238 303.539h-478.643zM870.4 716.8h-168.090l-315.853-338.432c-14.285-15.334-33.331-23.603-53.709-23.347-20.326 0.256-39.219 9.011-53.094 24.627l-126.054 141.798v-367.846h716.8v563.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["media"],"grid":0},"attrs":[{}],"properties":{"order":30,"id":29,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":1,"setId":8,"iconIdx":29},{"icon":{"paths":["M128 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM512 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM896 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["more"],"grid":0},"attrs":[{}],"properties":{"order":34,"id":30,"name":"more, dots","prevSize":32,"code":59678},"setIdx":1,"setId":8,"iconIdx":30},{"icon":{"paths":["M877.12 311.104l-66.304 66.368-228.224-228.224 66.368-66.368c25.216-25.152 66.048-25.152 91.264 0l136.896 137.024c25.216 25.216 25.216 65.984 0 91.2zM760.896 427.392l-386.176 386.112c-25.216 25.28-66.048 25.28-91.264 0l-136.96-136.896c-25.216-25.28-25.216-66.112 0-91.264l386.24-386.24 228.16 228.288zM64 896v-191.872l191.936 191.872h-191.936z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pencil"],"grid":0},"attrs":[{}],"properties":{"order":47,"id":31,"name":"pencil","prevSize":32,"code":59679},"setIdx":1,"setId":8,"iconIdx":31},{"icon":{"paths":["M892.083 131.917c-73.523-73.498-193.152-73.498-266.65 0l-157.184 157.107c-9.958 10.035-9.958 26.214 0 36.275 10.061 9.984 26.24 9.984 36.25 0l157.133-157.107c53.504-53.555 140.672-53.555 194.176 0 53.581 53.504 53.581 140.672 0 194.176l-186.138 186.163c-53.53 53.581-140.672 53.581-194.176 0-10.086-10.010-26.24-10.010-36.275 0-10.035 10.086-10.035 26.189 0 36.25 36.787 36.736 84.992 55.117 133.325 55.117s96.589-18.432 133.376-55.117l186.163-186.214c73.498-73.472 73.498-193.152 0-266.65zM519.45 698.726l-157.082 157.082c-53.504 53.555-140.672 53.555-194.176 0-53.581-53.504-53.581-140.672 0-194.176l186.138-186.163c53.53-53.581 140.672-53.581 194.176 0 10.086 9.984 26.189 9.984 36.275 0 10.035-10.086 10.035-26.214 0-36.25-73.549-73.498-193.203-73.498-266.701 0l-186.163 186.163c-73.498 73.574-73.498 193.203 0 266.701 36.787 36.71 85.043 55.117 133.325 55.117 48.333 0 96.538-18.406 133.325-55.117l157.133-157.133c10.010-10.010 10.010-26.189 0-36.224-10.010-9.984-26.189-9.984-36.25 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["reference"],"grid":0},"attrs":[{}],"properties":{"order":45,"id":32,"name":"reference","prevSize":32,"code":59680},"setIdx":1,"setId":8,"iconIdx":32},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-300.8c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v300.8c0 124.8-99.2 224-224 224zM224 339.2c-89.6 0-160 70.4-160 160v300.8c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-300.8c0-89.6-70.4-160-160-160h-576z","M828.8 201.6h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M716.8 64h-409.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h412.8c19.2 0 32 12.8 32 32s-16 32-35.2 32z","M800 416v64c0 48-38.4 83.2-83.2 83.2h-409.6c-44.8 3.2-83.2-35.2-83.2-83.2v-64h-54.4v64c0 76.8 64 140.8 140.8 140.8h406.4c76.8 0 140.8-64 140.8-140.8v-64h-57.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["schemas"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":46,"id":33,"name":"schemas","prevSize":32,"code":59681},"setIdx":1,"setId":8,"iconIdx":33},{"icon":{"paths":["M939.776 1003.776c-27.2 27.008-71.232 27.008-98.368 0l-168.96-168.96c-66.176 38.464-142.016 62.080-224 62.080-247.744 0-448.448-200.832-448.448-448.448 0-247.744 200.704-448.448 448.448-448.448 247.68 0 448.512 200.704 448.512 448.448 0 115.136-44.672 218.944-115.904 298.304l158.656 158.656c27.008 27.136 27.008 71.168 0.064 98.368zM448.448 128.128c-176.896 0-320.32 143.36-320.32 320.32s143.424 320.32 320.32 320.32c176.96 0 320.384-143.36 320.384-320.32s-143.488-320.32-320.384-320.32z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["search"],"grid":0},"attrs":[{}],"properties":{"order":23,"id":34,"name":"search","prevSize":32,"code":59682},"setIdx":1,"setId":8,"iconIdx":34},{"icon":{"paths":["M1019.11 440.755c-1.946-13.747-14.438-23.398-28.16-21.888-16.947 1.843-34.253-0.589-50.048-7.091-52.25-21.504-77.261-81.459-55.757-133.709 6.605-15.846 16.947-29.85 30.208-40.602 10.803-8.653 12.698-24.294 4.352-35.354-28.902-37.99-62.797-71.706-100.838-100.045-10.701-8.090-25.805-6.451-34.662 3.661-28.8 33.254-75.546 44.262-116.198 27.546-40.704-16.742-66.099-57.498-63.206-101.453 0.845-13.338-8.755-25.19-21.99-27.008-47.002-6.605-94.797-6.605-142.054 0.077-13.722 1.946-23.398 14.387-21.862 28.211 1.843 16.896-0.614 34.202-7.168 49.997-21.504 52.25-81.408 77.21-133.632 55.706-15.821-6.502-29.85-16.947-40.602-30.157-8.653-10.752-24.32-12.698-35.379-4.301-37.99 28.851-71.68 62.694-100.045 100.762-8.090 10.701-6.451 25.83 3.635 34.637 33.28 28.902 44.288 75.597 27.546 116.301-16.742 40.653-57.498 66.048-101.427 63.155-13.363-0.845-25.19 8.755-26.982 21.99-6.63 47.002-6.63 94.822 0.102 142.080 1.946 13.696 14.387 23.322 28.16 21.811 16.896-1.818 34.202 0.691 50.022 7.168 52.224 21.53 77.21 81.459 55.706 133.734-6.502 15.795-16.947 29.773-30.157 40.525-10.803 8.73-12.698 24.346-4.352 35.354 28.877 38.042 62.822 71.731 100.813 100.122 1.741 1.357 3.661 2.355 5.606 3.2 9.933 4.045 21.709 1.536 29.082-6.938 28.826-33.178 75.571-44.262 116.275-27.52 40.653 16.742 66.048 57.498 63.13 101.453-0.819 13.338 8.755 25.165 22.067 27.059 47.002 6.579 94.72 6.554 142.029-0.102 13.645-1.971 23.347-14.464 21.811-28.237-1.843-16.947 0.691-34.253 7.194-50.048 21.504-52.25 81.459-77.21 133.658-55.68 15.795 6.528 29.85 16.947 40.55 30.157 8.704 10.803 24.346 12.698 35.405 4.326 37.99-28.902 71.654-62.746 100.096-100.813 7.987-10.675 6.4-25.805-3.712-34.662-33.254-28.826-44.288-75.571-27.546-116.224 16.742-40.73 57.498-66.099 101.453-63.232 13.338 0.922 25.139-8.678 27.008-21.965 6.554-47.002 6.502-94.771-0.128-142.003zM971.059 554.010c-56.141 5.274-105.702 41.114-127.642 94.464s-12.058 113.613 24.090 156.902c-17.69 21.478-37.453 41.318-58.854 59.315-12.749-11.213-27.392-20.352-43.238-26.854-78.259-32.282-168.243 5.197-200.499 83.584-6.502 15.718-10.291 32.563-11.29 49.536-27.853 2.56-55.859 2.637-83.61 0.077-5.274-56.090-41.114-105.677-94.464-127.616-53.35-21.99-113.613-11.981-156.928 24.064-21.504-17.69-41.318-37.453-59.29-58.88 11.213-12.723 20.352-27.392 26.906-43.136 32.205-78.387-5.274-168.294-83.584-200.55-15.821-6.502-32.589-10.342-49.613-11.366-2.534-27.853-2.586-55.859 0-83.558 56.090-5.299 105.626-41.088 127.565-94.438 21.965-53.402 12.058-113.638-24.090-156.902 17.69-21.555 37.478-41.395 58.88-59.341 12.749 11.213 27.392 20.352 43.213 26.854 78.285 32.256 168.218-5.248 200.474-83.558 6.528-15.795 10.342-32.589 11.366-49.613 27.853-2.509 55.808-2.56 83.558 0 5.299 56.090 41.139 105.6 94.49 127.59 53.35 21.939 113.638 12.006 156.902-24.090 21.504 17.741 41.293 37.453 59.29 58.854-11.213 12.8-20.352 27.392-26.854 43.213-32.256 78.31 5.248 168.294 83.507 200.499 15.846 6.502 32.691 10.342 49.638 11.392 2.56 27.853 2.611 55.808 0.077 83.558zM512 307.2c-113.101 0-204.8 91.699-204.8 204.8 0 113.126 91.699 204.826 204.8 204.826s204.8-91.699 204.8-204.826c0-113.101-91.699-204.8-204.8-204.8zM512 665.626c-84.813 0-153.6-68.813-153.6-153.626 0-84.838 68.787-153.6 153.6-153.6 84.838 0 153.6 68.762 153.6 153.6 0 84.813-68.762 153.626-153.6 153.626z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings"],"grid":0},"attrs":[{}],"properties":{"order":22,"id":35,"name":"settings","prevSize":32,"code":59683},"setIdx":1,"setId":8,"iconIdx":35},{"icon":{"paths":["M77.005 102.605h128v332.8c0 14.131 11.418 25.6 25.6 25.6 14.106 0 25.6-11.469 25.6-25.6v-332.8h128c14.106 0 25.6-11.469 25.6-25.6 0-14.157-11.494-25.6-25.6-25.6h-307.2c-14.182 0-25.6 11.443-25.6 25.6 0 14.106 11.418 25.6 25.6 25.6zM947.405 716.979h-179.2v-102.4h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-204.8c-14.182 0-25.6 11.443-25.6 25.6v358.4c0 14.157 11.418 25.6 25.6 25.6 14.157 0 25.6-11.443 25.6-25.6v-179.2h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.494-25.6-25.6-25.6zM965.094 58.47c-9.958-9.933-26.112-9.933-36.045 0l-870.605 870.579c-9.958 9.984-9.958 26.086 0 36.045 10.010 9.984 26.112 9.984 36.045 0l870.605-870.579c9.958-9.933 9.958-26.086 0-36.045z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-boolean"],"grid":0},"attrs":[{}],"properties":{"order":21,"id":36,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":1,"setId":8,"iconIdx":36},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-datetime"],"grid":0},"attrs":[{}],"properties":{"order":24,"id":37,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":1,"setId":8,"iconIdx":37},{"icon":{"paths":["M179.2 256c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6h-25.6c-56.55 0-102.4 45.85-102.4 102.4v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 56.55 45.85 102.4 102.4 102.4h25.6c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-30.746-13.85-58.061-35.328-76.8 21.478-18.765 35.328-46.029 35.328-76.8v-179.2zM972.8 486.4h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-56.55-45.85-102.4-102.4-102.4h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 30.771 13.85 58.035 35.328 76.8-21.478 18.739-35.328 46.054-35.328 76.8v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h25.6c56.55 0 102.4-45.85 102.4-102.4v-179.2c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6zM512 332.8c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6c0-14.131-11.443-25.6-25.6-25.6zM512 435.2c-14.157 0-25.6 11.469-25.6 25.6v204.8c0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6v-204.8c0-14.131-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["json"],"grid":0},"attrs":[{}],"properties":{"order":20,"id":38,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":1,"setId":8,"iconIdx":38},{"icon":{"paths":["M256 665.6h-76.8v-332.8c0-14.131-11.469-25.6-25.6-25.6h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h51.2v307.2h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6zM614.4 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6v179.2c0 14.131 11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-179.2v-128h179.2c14.131 0 25.6-11.469 25.6-25.6v-179.2c0-14.131-11.469-25.6-25.6-25.6zM972.8 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6v-358.4c0-14.131-11.469-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-number"],"grid":0},"attrs":[{}],"properties":{"order":32,"id":39,"name":"type-Number","prevSize":32,"code":59686},"setIdx":1,"setId":8,"iconIdx":39},{"icon":{"paths":["M870.4 921.6h-716.8c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h716.8c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM194.688 817.152c13.030 5.555 28.083-0.461 33.613-13.44l125.030-291.712h317.338l125.005 291.712c4.173 9.677 13.568 15.488 23.526 15.488 3.405 0 6.81-0.64 10.112-2.048 13.005-5.606 18.995-20.659 13.44-33.638l-131.61-306.944c-0.051-0.051-0.051-0.154-0.102-0.205l-175.488-409.6c-4.045-9.472-13.312-15.565-23.552-15.565s-19.507 6.093-23.552 15.514l-175.488 409.6c-0.051 0.051-0.051 0.154-0.102 0.205l-131.61 306.97c-5.53 13.005 0.461 28.058 13.44 33.664zM512 141.773l136.704 319.027h-273.408l136.704-319.027z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-string"],"grid":0},"attrs":[{}],"properties":{"order":48,"id":40,"name":"type-String","prevSize":32,"code":59687},"setIdx":1,"setId":8,"iconIdx":40},{"icon":{"paths":["M955.221 848c0-0.109 10.752 0 0 0-52.751-161.392-240.461-224-443.178-224-202.269 0-389.979 63.392-443.066 224-11.2-0.109 0-1.232 0 0 0 61.936 49.615 112 110.654 112h664.823c61.151 0 110.766-50.064 110.766-112zM290.399 288c0 123.648 99.231 336 221.645 336s221.645-212.352 221.645-336c0-123.648-99.231-224-221.645-224s-221.645 100.352-221.645 224z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user"],"grid":0},"attrs":[{}],"properties":{"order":33,"id":41,"name":"user","prevSize":32,"code":59688},"setIdx":1,"setId":8,"iconIdx":41},{"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":7,"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"],"width":1344,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59701,"name":"browser"},"setIdx":2,"setId":7,"iconIdx":1},{"icon":{"paths":["M927.936 272.992l-68.288-68.288c-12.608-12.576-32.96-12.576-45.536 0l-409.44 409.44-194.752-196.16c-12.576-12.576-32.928-12.576-45.536 0l-68.288 68.288c-12.576 12.608-12.576 32.96 0 45.536l285.568 287.488c12.576 12.576 32.96 12.576 45.536 0l500.736-500.768c12.576-12.544 12.576-32.96 0-45.536z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["checkmark","tick","approve","submit"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":2,"setId":7,"iconIdx":2},{"icon":{"paths":["M1020.192 401.824c-8.864-25.568-31.616-44.288-59.008-48.352l-266.432-39.616-115.808-240.448c-12.192-25.248-38.272-41.408-66.944-41.408s-54.752 16.16-66.944 41.408l-115.808 240.448-266.464 39.616c-27.36 4.064-50.112 22.784-58.944 48.352-8.8 25.632-2.144 53.856 17.184 73.12l195.264 194.944-45.28 270.432c-4.608 27.232 7.2 54.56 30.336 70.496 12.704 8.736 27.648 13.184 42.592 13.184 12.288 0 24.608-3.008 35.776-8.992l232.288-125.056 232.32 125.056c11.168 5.984 23.488 8.992 35.744 8.992 14.944 0 29.888-4.448 42.624-13.184 23.136-15.936 34.88-43.264 30.304-70.496l-45.312-270.432 195.328-194.944c19.296-19.296 25.92-47.52 17.184-73.12zM754.816 619.616c-16.384 16.32-23.808 39.328-20.064 61.888l45.312 270.432-232.32-124.992c-11.136-6.016-23.424-8.992-35.776-8.992-12.288 0-24.608 3.008-35.744 8.992l-232.32 124.992 45.312-270.432c3.776-22.56-3.648-45.568-20.032-61.888l-195.264-194.944 266.432-39.68c24.352-3.616 45.312-18.848 55.776-40.576l115.872-240.384 115.84 240.416c10.496 21.728 31.424 36.928 55.744 40.576l266.496 39.68-195.264 194.912z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star","favorite"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":3,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":2,"setId":7,"iconIdx":3},{"icon":{"paths":["M409.6 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM409.6 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["grid"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":4,"setId":5,"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":1,"name":"list","prevSize":20,"code":59726},"setIdx":4,"setId":5,"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":2,"prevSize":20,"code":59708,"name":"info"},"setIdx":4,"setId":5,"iconIdx":2},{"icon":{"paths":["M585.143 548.557c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z","M585.143 219.443c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-bottom"],"grid":16},"attrs":[{},{}],"properties":{"order":125,"id":0,"name":"caret-bottom","prevSize":24,"code":59755},"setIdx":5,"setId":4,"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"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-top"],"grid":16},"attrs":[{},{}],"properties":{"order":124,"id":1,"name":"caret-top","prevSize":24,"code":59756},"setIdx":5,"setId":4,"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,"tags":["show"],"grid":16},"attrs":[{},{},{}],"properties":{"order":123,"id":2,"name":"show","prevSize":24,"code":59748},"setIdx":5,"setId":4,"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,"tags":["show-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":122,"id":3,"name":"show-all","prevSize":24,"code":59749},"setIdx":5,"setId":4,"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,"tags":["hide"],"grid":16},"attrs":[{},{},{}],"properties":{"order":121,"id":4,"name":"hide","prevSize":24,"code":59750},"setIdx":5,"setId":4,"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,"tags":["hide-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":120,"id":5,"name":"hide-all","prevSize":24,"code":59751},"setIdx":5,"setId":4,"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":6,"prevSize":24,"code":59737,"name":"spinner2"},"setIdx":5,"setId":4,"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.538z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-full","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":24,"code":59741,"name":"star-full"},"setIdx":5,"setId":4,"iconIdx":7},{"icon":{"paths":["M1024 397.050l-353.78-51.408-158.22-320.582-158.216 320.582-353.784 51.408 256 249.538-60.432 352.352 316.432-166.358 316.432 166.358-60.434-352.352 256.002-249.538zM512 753.498l-223.462 117.48 42.676-248.83-180.786-176.222 249.84-36.304 111.732-226.396 111.736 226.396 249.836 36.304-180.788 176.222 42.678 248.83-223.462-117.48z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-empty","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":8,"prevSize":24,"code":59742,"name":"star-empty"},"setIdx":5,"setId":4,"iconIdx":8},{"icon":{"paths":["M1024 226.4c-37.6 16.8-78.2 28-120.6 33 43.4-26 76.6-67.2 92.4-116.2-40.6 24-85.6 41.6-133.4 51-38.4-40.8-93-66.2-153.4-66.2-116 0-210 94-210 210 0 16.4 1.8 32.4 5.4 47.8-174.6-8.8-329.4-92.4-433-219.6-18 31-28.4 67.2-28.4 105.6 0 72.8 37 137.2 93.4 174.8-34.4-1-66.8-10.6-95.2-26.2 0 0.8 0 1.8 0 2.6 0 101.8 72.4 186.8 168.6 206-17.6 4.8-36.2 7.4-55.4 7.4-13.6 0-26.6-1.4-39.6-3.8 26.8 83.4 104.4 144.2 196.2 146-72 56.4-162.4 90-261 90-17 0-33.6-1-50.2-3 93.2 59.8 203.6 94.4 322.2 94.4 386.4 0 597.8-320.2 597.8-597.8 0-9.2-0.2-18.2-0.6-27.2 41-29.4 76.6-66.4 104.8-108.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["twitter","brand","tweet","social"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":9,"prevSize":24,"code":59740,"name":"twitter"},"setIdx":5,"setId":4,"iconIdx":9},{"icon":{"paths":["M728.992 512c137.754-87.334 231.008-255.208 231.008-448 0-21.676-1.192-43.034-3.478-64h-889.042c-2.29 20.968-3.48 42.326-3.48 64 0 192.792 93.254 360.666 231.006 448-137.752 87.334-231.006 255.208-231.006 448 0 21.676 1.19 43.034 3.478 64h889.042c2.288-20.966 3.478-42.324 3.478-64 0.002-192.792-93.252-360.666-231.006-448zM160 960c0-186.912 80.162-345.414 224-397.708v-100.586c-143.838-52.29-224-210.792-224-397.706v0h704c0 186.914-80.162 345.416-224 397.706v100.586c143.838 52.294 224 210.796 224 397.708h-704zM619.626 669.594c-71.654-40.644-75.608-93.368-75.626-125.366v-64.228c0-31.994 3.804-84.914 75.744-125.664 38.504-22.364 71.808-56.348 97.048-98.336h-409.582c25.266 42.032 58.612 76.042 97.166 98.406 71.654 40.644 75.606 93.366 75.626 125.366v64.228c0 31.992-3.804 84.914-75.744 125.664-72.622 42.18-126.738 125.684-143.090 226.336h501.67c-16.364-100.708-70.53-184.248-143.212-226.406z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hour-glass","loading","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":24,"code":59732,"name":"hour-glass"},"setIdx":5,"setId":4,"iconIdx":10},{"icon":{"paths":["M192 512c0-12.18 0.704-24.196 2.030-36.022l-184.98-60.104c-5.916 31.14-9.050 63.264-9.050 96.126 0 147.23 62.166 279.922 161.654 373.324l114.284-157.296c-52.124-56.926-83.938-132.758-83.938-216.028zM832 512c0 83.268-31.812 159.102-83.938 216.028l114.284 157.296c99.488-93.402 161.654-226.094 161.654-373.324 0-32.862-3.132-64.986-9.048-96.126l-184.98 60.104c1.324 11.828 2.028 23.842 2.028 36.022zM576 198.408c91.934 18.662 169.544 76.742 214.45 155.826l184.978-60.102c-73.196-155.42-222.24-268.060-399.428-290.156v194.432zM233.55 354.232c44.906-79.084 122.516-137.164 214.45-155.826v-194.43c-177.188 22.096-326.23 134.736-399.426 290.154l184.976 60.102zM644.556 803.328c-40.39 18.408-85.272 28.672-132.556 28.672s-92.166-10.264-132.554-28.67l-114.292 157.31c73.206 40.366 157.336 63.36 246.846 63.36s173.64-22.994 246.848-63.36l-114.292-157.312z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["spinner","loading","loading-wheel","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":24,"code":59731,"name":"spinner"},"setIdx":5,"setId":4,"iconIdx":11},{"icon":{"paths":["M658.744 749.256l-210.744-210.746v-282.51h128v229.49l173.256 173.254zM512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384s-171.922 384-384 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["clock","time","schedule"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":12,"prevSize":24,"code":59728,"name":"clock"},"setIdx":5,"setId":4,"iconIdx":12},{"icon":{"paths":["M128 320v640c0 35.2 28.8 64 64 64h576c35.2 0 64-28.8 64-64v-640h-704zM320 896h-64v-448h64v448zM448 896h-64v-448h64v448zM576 896h-64v-448h64v448zM704 896h-64v-448h64v448z","M848 128h-208v-80c0-26.4-21.6-48-48-48h-224c-26.4 0-48 21.6-48 48v80h-208c-26.4 0-48 21.6-48 48v80h832v-80c0-26.4-21.6-48-48-48zM576 128h-192v-63.198h192v63.198z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bin","trashcan","remove","delete","recycle","dispose"],"grid":16},"attrs":[{},{}],"properties":{"order":1,"id":13,"name":"bin2","prevSize":24,"code":59650},"setIdx":5,"setId":4,"iconIdx":13},{"icon":{"paths":["M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 960.002c-62.958 0-122.872-13.012-177.23-36.452l233.148-262.29c5.206-5.858 8.082-13.422 8.082-21.26v-96c0-17.674-14.326-32-32-32-112.99 0-232.204-117.462-233.374-118.626-6-6.002-14.14-9.374-22.626-9.374h-128c-17.672 0-32 14.328-32 32v192c0 12.122 6.848 23.202 17.69 28.622l110.31 55.156v187.886c-116.052-80.956-192-215.432-192-367.664 0-68.714 15.49-133.806 43.138-192h116.862c8.488 0 16.626-3.372 22.628-9.372l128-128c6-6.002 9.372-14.14 9.372-22.628v-77.412c40.562-12.074 83.518-18.588 128-18.588 70.406 0 137.004 16.26 196.282 45.2-4.144 3.502-8.176 7.164-12.046 11.036-36.266 36.264-56.236 84.478-56.236 135.764s19.97 99.5 56.236 135.764c36.434 36.432 85.218 56.264 135.634 56.26 3.166 0 6.342-0.080 9.518-0.236 13.814 51.802 38.752 186.656-8.404 372.334-0.444 1.744-0.696 3.488-0.842 5.224-81.324 83.080-194.7 134.656-320.142 134.656z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["earth","globe","language","web","internet","sphere","planet"],"defaultCode":59850,"grid":16},"attrs":[],"properties":{"ligatures":"earth, globe2","name":"earth","id":14,"order":91,"prevSize":24,"code":59850},"setIdx":5,"setId":4,"iconIdx":14},{"icon":{"paths":["M512.002 193.212v-65.212h128v-64c0-35.346-28.654-64-64.002-64h-191.998c-35.346 0-64 28.654-64 64v64h128v65.212c-214.798 16.338-384 195.802-384 414.788 0 229.75 186.25 416 416 416s416-186.25 416-416c0-218.984-169.202-398.448-384-414.788zM706.276 834.274c-60.442 60.44-140.798 93.726-226.274 93.726s-165.834-33.286-226.274-93.726c-60.44-60.44-93.726-140.8-93.726-226.274s33.286-165.834 93.726-226.274c58.040-58.038 134.448-91.018 216.114-93.548l-21.678 314.020c-1.86 26.29 12.464 37.802 31.836 37.802s33.698-11.512 31.836-37.802l-21.676-314.022c81.666 2.532 158.076 35.512 216.116 93.55 60.44 60.44 93.726 140.8 93.726 226.274s-33.286 165.834-93.726 226.274z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["stopwatch","time","speed","meter","chronometer"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":15,"prevSize":24,"code":59715,"name":"elapsed"},"setIdx":5,"setId":4,"iconIdx":15},{"icon":{"paths":["M522.2 438.8v175.6h290.4c-11.8 75.4-87.8 220.8-290.4 220.8-174.8 0-317.4-144.8-317.4-323.2s142.6-323.2 317.4-323.2c99.4 0 166 42.4 204 79l139-133.8c-89.2-83.6-204.8-134-343-134-283 0-512 229-512 512s229 512 512 512c295.4 0 491.6-207.8 491.6-500.2 0-33.6-3.6-59.2-8-84.8l-483.6-0.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["google","brand"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":16,"prevSize":24,"code":59707,"name":"google"},"setIdx":5,"setId":4,"iconIdx":16},{"icon":{"paths":["M592 448h-16v-192c0-105.87-86.13-192-192-192h-128c-105.87 0-192 86.13-192 192v192h-16c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48zM192 256c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192h-256v-192z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["lock","secure","private","encrypted"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":17,"prevSize":24,"code":59700,"name":"lock"},"setIdx":5,"setId":4,"iconIdx":17},{"icon":{"paths":["M0.35 512l-0.35-312.074 384-52.144v364.218zM448 138.482l511.872-74.482v448h-511.872zM959.998 576l-0.126 448-511.872-72.016v-375.984zM384 943.836l-383.688-52.594-0.020-315.242h383.708z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["windows8","brand","os"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":18,"prevSize":24,"code":59712,"name":"microsoft"},"setIdx":5,"setId":4,"iconIdx":18},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":24,"code":59695,"name":"pause"},"setIdx":5,"setId":4,"iconIdx":19},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":20,"prevSize":24,"code":59696,"name":"play"},"setIdx":5,"setId":4,"iconIdx":20},{"icon":{"paths":["M889.68 166.32c-93.608-102.216-228.154-166.32-377.68-166.32-282.77 0-512 229.23-512 512h96c0-229.75 186.25-416 416-416 123.020 0 233.542 53.418 309.696 138.306l-149.696 149.694h352v-352l-134.32 134.32z","M928 512c0 229.75-186.25 416-416 416-123.020 0-233.542-53.418-309.694-138.306l149.694-149.694h-352v352l134.32-134.32c93.608 102.216 228.154 166.32 377.68 166.32 282.77 0 512-229.23 512-512h-96z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["loop","repeat","player","reload","refresh","update","synchronize","arrows"],"grid":16},"attrs":[{},{}],"properties":{"order":49,"id":21,"prevSize":24,"code":59694,"name":"reset"},"setIdx":5,"setId":4,"iconIdx":21},{"icon":{"paths":["M933.79 610.25c-53.726-93.054-21.416-212.304 72.152-266.488l-100.626-174.292c-28.75 16.854-62.176 26.518-97.846 26.518-107.536 0-194.708-87.746-194.708-195.99h-201.258c0.266 33.41-8.074 67.282-25.958 98.252-53.724 93.056-173.156 124.702-266.862 70.758l-100.624 174.292c28.97 16.472 54.050 40.588 71.886 71.478 53.638 92.908 21.512 211.92-71.708 266.224l100.626 174.292c28.65-16.696 61.916-26.254 97.4-26.254 107.196 0 194.144 87.192 194.7 194.958h201.254c-0.086-33.074 8.272-66.57 25.966-97.218 53.636-92.906 172.776-124.594 266.414-71.012l100.626-174.29c-28.78-16.466-53.692-40.498-71.434-71.228zM512 719.332c-114.508 0-207.336-92.824-207.336-207.334 0-114.508 92.826-207.334 207.336-207.334 114.508 0 207.332 92.826 207.332 207.334-0.002 114.51-92.824 207.334-207.332 207.334z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cog","gear","preferences","settings","generate","control","options"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":22,"prevSize":24,"code":59693,"name":"settings2"},"setIdx":5,"setId":4,"iconIdx":22},{"icon":{"paths":["M512 128c-247.424 0-448 200.576-448 448s200.576 448 448 448 448-200.576 448-448-200.576-448-448-448zM512 936c-198.824 0-360-161.178-360-360 0-198.824 161.176-360 360-360 198.822 0 360 161.176 360 360 0 198.822-161.178 360-360 360zM934.784 287.174c16.042-28.052 25.216-60.542 25.216-95.174 0-106.040-85.96-192-192-192-61.818 0-116.802 29.222-151.92 74.596 131.884 27.236 245.206 105.198 318.704 212.578v0zM407.92 74.596c-35.116-45.374-90.102-74.596-151.92-74.596-106.040 0-192 85.96-192 192 0 34.632 9.174 67.122 25.216 95.174 73.5-107.38 186.822-185.342 318.704-212.578z","M512 576v-256h-64v320h256v-64z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["alarm","time","clock"],"grid":16},"attrs":[{},{}],"properties":{"order":2,"id":23,"prevSize":24,"code":59716,"name":"timeout"},"setIdx":5,"setId":4,"iconIdx":23},{"icon":{"paths":["M768 64c105.87 0 192 86.13 192 192v192h-128v-192c0-35.29-28.71-64-64-64h-128c-35.29 0-64 28.71-64 64v192h16c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48h-544c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h400v-192c0-105.87 86.13-192 192-192h128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["unlocked","lock-open"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":24,"prevSize":24,"code":59699,"name":"unlocked"},"setIdx":5,"setId":4,"iconIdx":24},{"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":6,"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"],"width":1140,"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Tags"],"grid":14},"attrs":[{},{},{}],"properties":{"order":119,"id":1,"name":"control-Tags","prevSize":28,"code":59747},"setIdx":6,"setId":3,"iconIdx":1},{"icon":{"paths":["M384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM998.4 844.8h-614.4c-38.406 15.539-22.811 37.543 0 51.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z","M0 0v307.2h307.2v-307.2zM47.4 47.4h212.4v212.4h-212.4z","M0 716.8v307.2h307.2v-307.2zM47.4 764.2h212.4v212.4h-212.4z","M0 358.4v307.2h307.2v-307.2zM47.4 405.8h212.4v212.4h-212.4z","M89.6 89.6h128v128h-128v-128z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Checkboxes"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":2,"name":"control-Checkboxes","prevSize":28,"code":59746},"setIdx":6,"setId":3,"iconIdx":2},{"icon":{"paths":["M159.073 665.6l-159.073-134.055 159.073-133.819 36.818 37.29-117.062 96.057 117.062 97.237z","M493.247 536.029q0 33.042-9.441 57.115-9.205 24.073-25.961 40.122-16.521 15.813-39.178 23.601-22.657 7.552-49.327 7.552-26.197 0-48.855-4.012-22.421-3.776-42.954-10.385v-323.338h57.587v78.356l-2.36 47.203q12.981-16.757 30.21-26.905 17.465-10.149 41.774-10.149 21.241 0 37.762 8.496t27.614 24.309q11.329 15.577 17.229 37.998 5.9 22.185 5.9 50.035zM432.828 538.389q0-19.825-2.832-33.75t-8.26-22.893q-5.192-8.969-12.981-12.981-7.552-4.248-17.465-4.248-14.633 0-28.086 11.801-13.217 11.801-28.086 32.098v104.79q6.844 2.596 16.757 4.248 10.149 1.652 20.533 1.652 13.689 0 24.781-5.664 11.329-5.664 19.117-16.049 8.024-10.385 12.273-25.253 4.248-15.105 4.248-33.75z","M700.682 513.608q0.472-13.453-1.416-22.893-1.652-9.441-5.664-15.577-3.776-6.136-9.441-8.968t-12.981-2.832q-12.745 0-26.433 10.621-13.453 10.385-29.738 34.458v151.756h-59.003v-239.789h52.159l2.124 34.93q5.9-9.205 13.217-16.521 7.552-7.316 16.521-12.509 9.205-5.428 20.297-8.26t24.309-2.832q18.173 0 32.098 6.372 14.161 6.136 23.601 18.409 9.677 12.273 14.161 30.918 4.72 18.409 4.012 42.718z","M864.927 397.725l159.073 133.819-159.073 134.055-36.582-37.29 116.826-96.293-116.826-97.001z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Html"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":116,"id":3,"name":"control-Html","prevSize":28,"code":59744},"setIdx":6,"setId":3,"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"],"width":1029,"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["single-content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":112,"id":4,"name":"single-content","prevSize":28,"code":59736},"setIdx":6,"setId":3,"iconIdx":4},{"icon":{"paths":["M777.143 946.286h-525.714c-89.143 0-160-70.857-160-160v-297.143c0-89.143 70.857-160 160-160h525.714c89.143 0 160 70.857 160 160v297.143c0 89.143-70.857 160-160 160zM251.429 374.857c-64 0-114.286 50.286-114.286 114.286v297.143c0 64 50.286 114.286 114.286 114.286h525.714c64 0 114.286-50.286 114.286-114.286v-297.143c0-64-50.286-114.286-114.286-114.286h-525.714z","M731.429 580.571h-457.143c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h457.143c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M502.857 740.571h-228.571c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h228.571c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M777.143 260.571h-525.714c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h525.714c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M685.714 146.286h-342.857c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h342.857c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z"],"width":1029,"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["multiple-content"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":5,"name":"multiple-content","prevSize":28,"code":59735},"setIdx":6,"setId":3,"iconIdx":5},{"icon":{"paths":["M832 268.8h-657.92c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h657.92c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 453.12h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 642.56h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 832h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-Array"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":108,"id":6,"name":"type-Array","prevSize":28,"code":59734},"setIdx":6,"setId":3,"iconIdx":6},{"icon":{"paths":["M292.571 713.143v128c0 20-16.571 36.571-36.571 36.571h-146.286c-20 0-36.571-16.571-36.571-36.571v-128c0-20 16.571-36.571 36.571-36.571h146.286c20 0 36.571 16.571 36.571 36.571zM309.714 109.714l-16 438.857c-0.571 20-17.714 36.571-37.714 36.571h-146.286c-20 0-37.143-16.571-37.714-36.571l-16-438.857c-0.571-20 15.429-36.571 35.429-36.571h182.857c20 0 36 16.571 35.429 36.571z"],"width":366,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":28,"code":59733,"name":"exclamation"},"setIdx":6,"setId":3,"iconIdx":7},{"icon":{"paths":["M512 26.38l-424.96 242.8v485.64l424.96 242.8 424.96-242.8v-485.64l-424.96-242.8zM512 235.52l245.76 138.24v276.48l-245.76 138.24-245.76-138.24v-276.48l245.76-138.24z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["orleans"],"grid":14},"attrs":[{}],"properties":{"order":99,"id":8,"name":"orleans","prevSize":28,"code":59723},"setIdx":6,"setId":3,"iconIdx":8},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v204.8h51.2v-204.8h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-307.2v51.2h307.2c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4z","M153.6 640v281.6h358.4v-281.6zM179.2 640v-76.8c0-84.48 69.12-153.6 153.6-153.6s153.6 69.12 153.6 153.6v76.8h-51.2v-76.8c0-56.32-46.080-102.4-102.4-102.4s-102.4 46.080-102.4 102.4v76.8z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-lock"],"grid":14},"attrs":[{},{}],"properties":{"order":97,"id":9,"name":"document-lock","prevSize":28,"code":59721},"setIdx":6,"setId":3,"iconIdx":9},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v153.6h51.2v-153.6h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7z","M102.4 357.532h460.8v52.068h-460.8v-52.068z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-unpublish"],"grid":14},"attrs":[{},{}],"properties":{"order":96,"id":10,"name":"document-unpublish","prevSize":28,"code":59711},"setIdx":6,"setId":3,"iconIdx":10},{"icon":{"paths":["M614.286 420.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8-5.714 13.143-5.714 4.571 0 9.714 2.286 13.143 5.714l224.571 224.571 224.571-224.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":28,"code":59648,"name":"angle-down"},"setIdx":6,"setId":3,"iconIdx":11},{"icon":{"paths":["M358.286 310.857c0 4.571-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8 5.714 13.143z"],"width":384,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":12,"prevSize":28,"code":59649,"name":"angle-left"},"setIdx":6,"setId":3,"iconIdx":12},{"icon":{"paths":["M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8-5.714-13.143 0-4.571 2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":347,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":13,"prevSize":28,"code":59697,"name":"angle-right"},"setIdx":6,"setId":3,"iconIdx":13},{"icon":{"paths":["M614.286 676.571c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8 5.714-13.143 5.714-4.571 0-9.714-2.286-13.143-5.714l-224.571-224.571-224.571 224.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":14,"prevSize":28,"code":59651,"name":"angle-up"},"setIdx":6,"setId":3,"iconIdx":14},{"icon":{"paths":["M592 393.6h-156.8c-57.6 0-105.6-48-105.6-105.6v-182.4c0-57.6 48-105.6 105.6-105.6h156.8c57.6 0 105.6 48 105.6 105.6v182.4c-3.2 57.6-48 105.6-105.6 105.6zM432 64c-22.4 0-41.6 19.2-41.6 41.6v182.4c0 22.4 19.2 41.6 41.6 41.6h156.8c22.4 0 41.6-19.2 41.6-41.6v-182.4c0-22.4-19.2-41.6-41.6-41.6h-156.8z","M195.2 1024c-105.6 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c3.2 105.6-86.4 195.2-195.2 195.2zM195.2 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 134.4 131.2 134.4 73.6 0 131.2-60.8 131.2-131.2 3.2-73.6-57.6-134.4-131.2-134.4z","M828.8 1024c-108.8 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c0 105.6-89.6 195.2-195.2 195.2zM828.8 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 131.2 131.2 131.2 73.6 0 131.2-60.8 131.2-131.2s-60.8-131.2-131.2-131.2z","M332.8 640c-6.4 0-12.8 0-16-3.2-16-9.6-19.2-28.8-9.6-44.8l83.2-137.6c9.6-16 28.8-19.2 44.8-9.6s19.2 28.8 9.6 44.8l-83.2 137.6c-6.4 6.4-16 12.8-28.8 12.8z","M691.2 640c-9.6 0-22.4-6.4-28.8-16l-83.2-137.6c-9.6-16-3.2-35.2 9.6-44.8s35.2-3.2 44.8 9.6l83.2 137.6c9.6 16 3.2 35.2-9.6 44.8-6.4 6.4-12.8 6.4-16 6.4z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["api"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":15,"name":"api","prevSize":28,"code":59717},"setIdx":6,"setId":3,"iconIdx":15},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M771.2 860.8h-438.4c-12.8 0-22.4-6.4-28.8-19.2s-3.2-25.6 3.2-35.2l300.8-355.2c6.4-6.4 16-12.8 25.6-12.8s19.2 6.4 25.6 12.8l192 275.2c3.2 3.2 3.2 6.4 3.2 9.6 16 44.8 3.2 73.6-6.4 89.6-22.4 32-70.4 35.2-76.8 35.2zM403.2 796.8h371.2c6.4 0 22.4-3.2 25.6-9.6 3.2-3.2 3.2-12.8 0-25.6l-166.4-236.8-230.4 272z","M332.8 502.4c-76.8 0-140.8-64-140.8-140.8s64-140.8 140.8-140.8 140.8 64 140.8 140.8-60.8 140.8-140.8 140.8zM332.8 284.8c-41.6 0-76.8 32-76.8 76.8s35.2 76.8 76.8 76.8 76.8-35.2 76.8-76.8-32-76.8-76.8-76.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["assets"],"grid":14},"attrs":[{},{},{}],"properties":{"order":95,"id":16,"name":"assets","prevSize":28,"code":59720},"setIdx":6,"setId":3,"iconIdx":16},{"icon":{"paths":["M932.571 548.571c0 20-16.571 36.571-36.571 36.571h-128c0 71.429-15.429 125.143-38.286 165.714l118.857 119.429c14.286 14.286 14.286 37.143 0 51.429-6.857 7.429-16.571 10.857-25.714 10.857s-18.857-3.429-25.714-10.857l-113.143-112.571s-74.857 68.571-172 68.571v-512h-73.143v512c-103.429 0-178.857-75.429-178.857-75.429l-104.571 118.286c-7.429 8-17.143 12-27.429 12-8.571 0-17.143-2.857-24.571-9.143-14.857-13.714-16-36.571-2.857-52l115.429-129.714c-20-39.429-33.143-90.286-33.143-156.571h-128c-20 0-36.571-16.571-36.571-36.571s16.571-36.571 36.571-36.571h128v-168l-98.857-98.857c-14.286-14.286-14.286-37.143 0-51.429s37.143-14.286 51.429 0l98.857 98.857h482.286l98.857-98.857c14.286-14.286 37.143-14.286 51.429 0s14.286 37.143 0 51.429l-98.857 98.857v168h128c20 0 36.571 16.571 36.571 36.571zM658.286 219.429h-365.714c0-101.143 81.714-182.857 182.857-182.857s182.857 81.714 182.857 182.857z"],"width":951,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":17,"prevSize":28,"code":59709,"name":"bug"},"setIdx":6,"setId":3,"iconIdx":17},{"icon":{"paths":["M585.143 402.286c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857s-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714 0-20 16.571-36.571 36.571-36.571h512c20 0 36.571 16.571 36.571 36.571z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":18,"prevSize":28,"code":59692,"name":"caret-down"},"setIdx":6,"setId":3,"iconIdx":18},{"icon":{"paths":["M365.714 256v512c0 20-16.571 36.571-36.571 36.571-9.714 0-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714s4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857 20 0 36.571 16.571 36.571 36.571z"],"width":402,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":28,"code":59690,"name":"caret-left"},"setIdx":6,"setId":3,"iconIdx":19},{"icon":{"paths":["M329.143 512c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857-20 0-36.571-16.571-36.571-36.571v-512c0-20 16.571-36.571 36.571-36.571 9.714 0 18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":329,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":20,"prevSize":28,"code":59689,"name":"caret-right"},"setIdx":6,"setId":3,"iconIdx":20},{"icon":{"paths":["M585.143 694.857c0 20-16.571 36.571-36.571 36.571h-512c-20 0-36.571-16.571-36.571-36.571 0-9.714 4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857s18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":21,"prevSize":28,"code":59691,"name":"caret-up"},"setIdx":6,"setId":3,"iconIdx":21},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M480 448h-211.2c-57.6 0-105.6-48-105.6-105.6v-73.6c0-57.6 48-105.6 105.6-105.6h211.2c57.6 0 105.6 48 105.6 105.6v73.6c0 57.6-48 105.6-105.6 105.6zM268.8 227.2c-22.4 0-41.6 19.2-41.6 41.6v73.6c0 22.4 19.2 41.6 41.6 41.6h211.2c22.4 0 41.6-19.2 41.6-41.6v-73.6c0-22.4-19.2-41.6-41.6-41.6h-211.2z","M828.8 611.2h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M553.6 777.6h-358.4c-19.2 0-32-12.8-32-32s12.8-32 32-32h355.2c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":93,"id":22,"name":"contents, trigger-ContentChanged","prevSize":28,"code":59718},"setIdx":6,"setId":3,"iconIdx":22},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date"],"grid":14},"attrs":[{}],"properties":{"order":71,"id":23,"name":"control-Date","prevSize":28,"code":59702},"setIdx":6,"setId":3,"iconIdx":23},{"icon":{"paths":["M486.4 409.6h51.2c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM230.4 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM230.4 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM51.2 742.4v-435.2h665.6v102.4h51.2v-281.6c0-42.342-34.458-76.8-76.8-76.8h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-256v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v614.4c0 42.342 34.458 76.8 76.8 76.8h332.8v-51.2h-332.8c-14.080 0-25.6-11.469-25.6-25.6zM51.2 128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h256v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128h-665.6v-128zM384 409.6c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM742.4 460.8c-155.546 0-281.6 126.054-281.6 281.6s126.054 281.6 281.6 281.6 281.6-126.054 281.6-281.6-126.054-281.6-281.6-281.6zM742.4 972.8c-127.232 0-230.4-103.168-230.4-230.4s103.168-230.4 230.4-230.4 230.4 103.168 230.4 230.4-103.168 230.4-230.4 230.4zM384 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM384 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM844.8 716.8c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-102.4c-14.131 0-25.6-11.469-25.6-25.6v-102.4c0-14.131 11.469-25.6 25.6-25.6s25.6 11.469 25.6 25.6v76.8h76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date-time"],"grid":14},"attrs":[{}],"properties":{"order":70,"id":24,"name":"control-DateTime","prevSize":28,"code":59703},"setIdx":6,"setId":3,"iconIdx":24},{"icon":{"paths":["M793.6 609.416h-61.838v-28.108h-0.783q-21.135 33.092-62.034 33.092-37.573 0-60.469-26.912-22.896-27.112-22.896-75.554 0-50.635 25.244-81.136t66.144-30.501q38.747 0 54.011 28.308h0.783v-121.405h61.838v302.216zM732.936 510.139v-15.35q0-19.935-11.35-33.092t-29.549-13.157q-20.548 0-32.093 16.546-11.546 16.347-11.546 45.053 0 26.912 11.154 41.465t30.919 14.553q18.786 0 30.528-15.35 11.937-15.35 11.937-40.668zM548.594 609.416h-61.643v-116.421q0-44.455-32.093-44.455-15.264 0-24.853 13.357t-9.589 33.292v114.228h-61.839v-117.617q0-43.259-31.506-43.259-15.851 0-25.44 12.758-9.393 12.758-9.393 34.687v113.431h-61.838v-204.135h61.838v31.896h0.783q9.589-16.347 26.81-26.514 17.417-10.366 37.964-10.366 42.465 0 58.12 38.076 22.896-38.076 67.318-38.076 65.361 0 65.361 82.133v126.987zM0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8zM819.2 0v204.8h204.8v-204.8zM51.2 51.2h102.4v102.4h-102.4zM870.4 51.2h102.4v102.4h-102.4zM281.6 76.8v51.2h102.4v-51.2zM486.4 76.8v51.2h102.4v-51.2zM691.2 76.8v51.2h102.4v-51.2zM896 281.6v102.4h51.2v-102.4zM76.8 384v102.4h51.2v-102.4zM896 486.4v102.4h51.2v-102.4zM76.8 588.8v102.4h51.2v-102.4zM896 691.2v102.4h51.2v-102.4zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8zM51.2 870.4h102.4v102.4h-102.4zM870.4 870.4h102.4v102.4h-102.4zM384 896v51.2h102.4v-51.2zM588.8 896v51.2h102.4v-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Markdown"],"grid":14},"attrs":[{}],"properties":{"order":72,"id":25,"name":"control-Markdown","prevSize":28,"code":59704},"setIdx":6,"setId":3,"iconIdx":25},{"icon":{"paths":["M292.571 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857z"],"width":1024,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["th"],"defaultCode":61450,"grid":14},"attrs":[],"properties":{"name":"grid","id":26,"order":83,"prevSize":28,"code":61450},"setIdx":6,"setId":3,"iconIdx":26},{"icon":{"paths":["M877.714 768v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 475.429v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 182.857v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571z"],"width":877.7142857142857,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["bars","navicon","reorder"],"defaultCode":61641,"grid":14},"attrs":[],"properties":{"name":"list1","id":27,"order":89,"prevSize":28,"code":61641},"setIdx":6,"setId":3,"iconIdx":27},{"icon":{"paths":["M512 64c-131.696 0-239.125 107.4-239.125 239 0 65.8 24.831 146.717 65.375 215.25 19.653 33.221 43.902 63.853 71.75 87.125-59.423 7.524-122.009 9.415-172.125 32-79.809 35.967-144.343 94.74-172.375 178.625-1.5 9.499 0 0-1.5 9v0.499c0 73.995 60.563 134.501 134.375 134.501h627.125c73.888 0 134.5-60.506 134.5-134.5l-1.5-9.375c-27.845-84.263-92.273-143.119-172.125-179-50.17-22.544-112.844-24.421-172.375-31.875 27.792-23.26 52.002-53.831 71.625-87 40.544-68.533 65.375-149.45 65.375-215.25 0-131.6-107.304-239-239-239zM512 124c99.241 0 179 79.875 179 179 0 49.562-21.877 125.381-57 184.75s-81.435 98.75-122 98.75c-40.565 0-86.877-39.381-122-98.75s-57.125-135.188-57.125-184.75c0-99.125 79.884-179 179.125-179zM512 646.5c92.551 0 180.829 14.406 249.75 45.375 66.784 30.009 113.649 74.724 136.5 137.75-2.447 39.259-32.9 70.375-72.75 70.375h-627.125c-39.678 0-70.116-31.051-72.625-70.25 22.978-62.705 69.953-107.523 136.75-137.625 68.937-31.067 157.205-45.625 249.5-45.625z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user-o"],"grid":14},"attrs":[{}],"properties":{"order":64,"id":28,"name":"user-o","prevSize":28,"code":59698},"setIdx":6,"setId":3,"iconIdx":28},{"icon":{"paths":["M217.6 992c-3.2 0-3.2 0-6.4 0h-3.2c-144-25.6-208-144-208-249.6 0-99.2 57.6-208 185.6-240v-147.2c0-19.2 12.8-32 32-32s32 12.8 32 32v172.8c0 16-12.8 28.8-25.6 32-108.8 16-160 102.4-160 182.4s48 166.4 153.6 185.6h6.4c16 3.2 28.8 19.2 25.6 38.4-3.2 16-16 25.6-32 25.6z","M774.4 1001.6c0 0 0 0 0 0-102.4 0-211.2-60.8-243.2-185.6h-176c-19.2 0-32-12.8-32-32s12.8-32 32-32h201.6c16 0 28.8 12.8 32 25.6 16 108.8 102.4 156.8 182.4 160 80 0 166.4-48 185.6-153.6v-3.2c3.2-16 19.2-28.8 38.4-25.6 16 3.2 28.8 19.2 25.6 38.4v3.2c-22.4 140.8-140.8 204.8-246.4 204.8z","M787.2 678.4c-19.2 0-32-12.8-32-32v-176c0-16 12.8-28.8 25.6-32 108.8-16 156.8-102.4 160-182.4 0-80-48-166.4-153.6-185.6h-3.2c-19.2-6.4-32-22.4-28.8-38.4s19.2-28.8 38.4-25.6h3.2c144 25.6 208 144 208 249.6 0 99.2-60.8 208-185.6 240v150.4c0 16-16 32-32 32z","M41.6 246.4c-3.2 0-3.2 0-6.4 0-16-3.2-28.8-19.2-25.6-35.2v-3.2c25.6-144 140.8-208 246.4-208 0 0 3.2 0 3.2 0 99.2 0 208 60.8 240 185.6h147.2c19.2 0 32 12.8 32 32s-12.8 32-32 32h-172.8c-16 0-28.8-12.8-32-25.6-16-108.8-102.4-156.8-182.4-160-80 0-166.4 48-185.6 153.6v3.2c-3.2 16-16 25.6-32 25.6z","M256 387.2c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-25.6 22.4-57.6 35.2-92.8 35.2zM256 192c-16 0-32 6.4-44.8 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-32-19.2-44.8-28.8-19.2-48-19.2z","M771.2 873.6c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-25.6 57.6-38.4 92.8-38.4s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-28.8 25.6-60.8 38.4-92.8 38.4zM771.2 678.4c-19.2 0-35.2 6.4-48 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-35.2-19.2-48-28.8-16-44.8-16z","M745.6 387.2c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 60.8-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM745.6 192c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z","M259.2 873.6c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM259.2 678.4c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z"],"attrs":[{},{},{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["webhooks"],"grid":14},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":29,"name":"rules","prevSize":28,"code":59719},"setIdx":6,"setId":3,"iconIdx":29}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showCodes":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"name":"icomoon","classSelector":".icon"},"historySize":50}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M214 768h596v86h-596v-86zM384 682v-256h-170l298-298 298 298h-170v256h-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["file_upload"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59762,"name":"upload-2"},"setIdx":0,"setId":10,"iconIdx":0},{"icon":{"paths":["M678 726h138l-70-186zM790 426l192 512h-86l-48-128h-202l-48 128h-86l192-512h86zM550 642l-34 88-132-132-214 212-60-60 218-214c-54-60-96-124-128-194h86c26 50 58 98 98 142 62-68 108-146 136-228h-478v-86h300v-84h84v84h300v86h-126c-32 100-84 196-158 278l-2 2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["translate"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":24,"code":59759,"name":"translate"},"setIdx":4,"setId":6,"iconIdx":0},{"icon":{"paths":["M854 470v84h-520l238 240-60 60-342-342 342-342 60 60-238 240h520z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["arrow_back"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":24,"code":59758,"name":"arrow_back"},"setIdx":4,"setId":6,"iconIdx":1},{"icon":{"paths":["M768 512c-25.6 0-42.667 17.067-42.667 42.667v256c0 25.6-17.067 42.667-42.667 42.667h-469.333c-25.6 0-42.667-17.067-42.667-42.667v-469.333c0-25.6 17.067-42.667 42.667-42.667h256c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-256c-72.533 0-128 55.467-128 128v469.333c0 72.533 55.467 128 128 128h469.333c72.533 0 128-55.467 128-128v-256c0-25.6-17.067-42.667-42.667-42.667z","M934.4 110.933c-4.267-8.533-12.8-17.067-21.333-21.333-4.267-4.267-12.8-4.267-17.067-4.267h-256c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h153.6l-396.8 396.8c-17.067 17.067-17.067 42.667 0 59.733 8.533 8.533 17.067 12.8 29.867 12.8s21.333-4.267 29.867-12.8l396.8-396.8v153.6c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-256c0-4.267 0-12.8-4.267-17.067z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["external-link"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":2,"prevSize":24,"code":59757,"name":"external-link"},"setIdx":4,"setId":6,"iconIdx":2},{"icon":{"paths":["M810.667 85.333h-597.333c-72.533 0-128 55.467-128 128v597.333c0 72.533 55.467 128 128 128h597.333c72.533 0 128-55.467 128-128v-597.333c0-72.533-55.467-128-128-128zM853.333 810.667c0 25.6-17.067 42.667-42.667 42.667h-597.333c-25.6 0-42.667-17.067-42.667-42.667v-597.333c0-25.6 17.067-42.667 42.667-42.667h597.333c25.6 0 42.667 17.067 42.667 42.667v597.333z","M682.667 469.333h-341.333c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h341.333c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["minus-square"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":3,"prevSize":24,"code":59753,"name":"minus-square"},"setIdx":4,"setId":6,"iconIdx":3},{"icon":{"paths":["M810.667 85.333h-597.333c-72.533 0-128 55.467-128 128v597.333c0 72.533 55.467 128 128 128h597.333c72.533 0 128-55.467 128-128v-597.333c0-72.533-55.467-128-128-128zM853.333 810.667c0 25.6-17.067 42.667-42.667 42.667h-597.333c-25.6 0-42.667-17.067-42.667-42.667v-597.333c0-25.6 17.067-42.667 42.667-42.667h597.333c25.6 0 42.667 17.067 42.667 42.667v597.333z","M682.667 469.333h-128v-128c0-25.6-17.067-42.667-42.667-42.667s-42.667 17.067-42.667 42.667v128h-128c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667h128v128c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667v-128h128c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["plus-square"],"grid":24},"attrs":[{},{}],"properties":{"order":1,"id":4,"name":"plus-square","prevSize":24,"code":59752},"setIdx":4,"setId":6,"iconIdx":4},{"icon":{"paths":["M170 640v-86h684v86h-684zM854 384v86h-684v-86h684z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag_handle"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":5,"prevSize":24,"code":59745,"name":"drag2"},"setIdx":4,"setId":6,"iconIdx":5},{"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":6,"name":"comments","prevSize":24,"code":59743},"setIdx":4,"setId":6,"iconIdx":6},{"icon":{"paths":["M512 128c212 0 384 172 384 384s-172 384-384 384c-88 0-170-30-234-80l60-60c50 34 110 54 174 54 166 0 298-132 298-298s-132-298-298-298-298 132-298 298h128l-172 170-170-170h128c0-212 172-384 384-384zM598 512c0 46-40 86-86 86s-86-40-86-86 40-86 86-86 86 40 86 86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings_backup_restore"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":24,"code":59739,"name":"backup"},"setIdx":4,"setId":6,"iconIdx":7},{"icon":{"paths":["M726 512c0 24-20 42-44 42h-426l-170 172v-598c0-24 18-42 42-42h554c24 0 44 18 44 42v384zM896 256c24 0 42 18 42 42v640l-170-170h-470c-24 0-42-18-42-42v-86h554v-384h86z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["question_answer"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":8,"prevSize":24,"code":59738,"name":"support"},"setIdx":4,"setId":6,"iconIdx":8},{"icon":{"paths":["M918 384v128h-128v298h-128v-298h-128v-128h384zM106 170h556v128h-214v512h-128v-512h-214v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["text_fields"],"grid":24},"attrs":[{}],"properties":{"order":75,"id":9,"prevSize":24,"code":59705,"name":"control-RichText"},"setIdx":4,"setId":6,"iconIdx":9},{"icon":{"paths":["M640 85.333q78 0 149.167 30.5t122.5 81.833 81.833 122.5 30.5 149.167q0 85-35 160.667t-96.667 129.167-140 77.5l21-20.667q18-18.333 28-42.667 9.333-22.667 9.333-49.333 0-6.667-0.333-9.333 59.333-41.333 93.833-105.833t34.5-139.5q0-60.667-23.667-116t-63.667-95.333-95.333-63.667-116-23.667q-55.333 0-106.5 19.833t-90 53.833-65 81.333-33.833 101h-88.667q-70.667 0-120.667 50t-50 120.667q0 38.667 15.167 71.667t39.833 54.167 54.833 33 60.833 11.833h50q11.667 29.333 30 48l37.667 37.333h-117.667q-69.667 0-128.5-34.333t-93.167-93.167-34.333-128.5 34.333-128.5 93.167-93.167 128.5-34.333h22q26.333-74.333 79.333-132.167t126.833-90.833 155.833-33zM554.667 426.667q17.667 0 30.167 12.5t12.5 30.167v281l55-55.333q12.333-12.333 30.333-12.333 18.333 0 30.5 12.167t12.167 30.5q0 18-12.333 30.333l-128 128q-12.333 12.333-30.333 12.333t-30.333-12.333l-128-128q-12.333-13-12.333-30.333 0-17.667 12.5-30.167t30.167-12.5q18 0 30.333 12.333l55 55.333v-281q0-17.667 12.5-30.167t30.167-12.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cloud-download"],"grid":24},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":24,"code":59710,"name":"download"},"setIdx":4,"setId":6,"iconIdx":10},{"icon":{"paths":["M448 576h128v-256h192l-256-256-256 256h192zM640 432v98.712l293.066 109.288-421.066 157.018-421.066-157.018 293.066-109.288v-98.712l-384 144v256l512 192 512-192v-256z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload","load","arrow"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":32,"code":59760,"name":"upload"},"setIdx":1,"setId":9,"iconIdx":0},{"icon":{"paths":["M585.143 548.557c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z","M585.143 219.443c0 9.728-3.986 18.871-10.862 25.71l-256 256c-6.839 6.839-16.018 10.862-25.71 10.862s-18.871-3.986-25.71-10.862l-256-256c-6.839-6.839-10.862-16.018-10.862-25.71 0-20.005 16.567-36.571 36.571-36.571h512c20.005 0 36.571 16.567 36.571 36.571z"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-bottom"],"grid":16},"attrs":[{},{}],"properties":{"order":125,"id":0,"name":"caret-bottom","prevSize":32,"code":59755},"setIdx":6,"setId":4,"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"],"width":585,"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-top"],"grid":16},"attrs":[{},{}],"properties":{"order":124,"id":1,"name":"caret-top","prevSize":32,"code":59756},"setIdx":6,"setId":4,"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,"tags":["show"],"grid":16},"attrs":[{},{},{}],"properties":{"order":123,"id":2,"name":"show","prevSize":32,"code":59748},"setIdx":6,"setId":4,"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,"tags":["show-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":122,"id":3,"name":"show-all","prevSize":32,"code":59749},"setIdx":6,"setId":4,"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,"tags":["hide"],"grid":16},"attrs":[{},{},{}],"properties":{"order":121,"id":4,"name":"hide","prevSize":32,"code":59750},"setIdx":6,"setId":4,"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,"tags":["hide-all"],"grid":16},"attrs":[{},{},{},{}],"properties":{"order":120,"id":5,"name":"hide-all","prevSize":32,"code":59751},"setIdx":6,"setId":4,"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":6,"prevSize":32,"code":59737,"name":"spinner2"},"setIdx":6,"setId":4,"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.538z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-full","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":32,"code":59741,"name":"star-full"},"setIdx":6,"setId":4,"iconIdx":7},{"icon":{"paths":["M1024 397.050l-353.78-51.408-158.22-320.582-158.216 320.582-353.784 51.408 256 249.538-60.432 352.352 316.432-166.358 316.432 166.358-60.434-352.352 256.002-249.538zM512 753.498l-223.462 117.48 42.676-248.83-180.786-176.222 249.84-36.304 111.732-226.396 111.736 226.396 249.836 36.304-180.788 176.222 42.678 248.83-223.462-117.48z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star-empty","rate","star","favorite","bookmark"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":8,"prevSize":32,"code":59742,"name":"star-empty"},"setIdx":6,"setId":4,"iconIdx":8},{"icon":{"paths":["M1024 226.4c-37.6 16.8-78.2 28-120.6 33 43.4-26 76.6-67.2 92.4-116.2-40.6 24-85.6 41.6-133.4 51-38.4-40.8-93-66.2-153.4-66.2-116 0-210 94-210 210 0 16.4 1.8 32.4 5.4 47.8-174.6-8.8-329.4-92.4-433-219.6-18 31-28.4 67.2-28.4 105.6 0 72.8 37 137.2 93.4 174.8-34.4-1-66.8-10.6-95.2-26.2 0 0.8 0 1.8 0 2.6 0 101.8 72.4 186.8 168.6 206-17.6 4.8-36.2 7.4-55.4 7.4-13.6 0-26.6-1.4-39.6-3.8 26.8 83.4 104.4 144.2 196.2 146-72 56.4-162.4 90-261 90-17 0-33.6-1-50.2-3 93.2 59.8 203.6 94.4 322.2 94.4 386.4 0 597.8-320.2 597.8-597.8 0-9.2-0.2-18.2-0.6-27.2 41-29.4 76.6-66.4 104.8-108.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["twitter","brand","tweet","social"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":9,"prevSize":32,"code":59740,"name":"twitter"},"setIdx":6,"setId":4,"iconIdx":9},{"icon":{"paths":["M728.992 512c137.754-87.334 231.008-255.208 231.008-448 0-21.676-1.192-43.034-3.478-64h-889.042c-2.29 20.968-3.48 42.326-3.48 64 0 192.792 93.254 360.666 231.006 448-137.752 87.334-231.006 255.208-231.006 448 0 21.676 1.19 43.034 3.478 64h889.042c2.288-20.966 3.478-42.324 3.478-64 0.002-192.792-93.252-360.666-231.006-448zM160 960c0-186.912 80.162-345.414 224-397.708v-100.586c-143.838-52.29-224-210.792-224-397.706v0h704c0 186.914-80.162 345.416-224 397.706v100.586c143.838 52.294 224 210.796 224 397.708h-704zM619.626 669.594c-71.654-40.644-75.608-93.368-75.626-125.366v-64.228c0-31.994 3.804-84.914 75.744-125.664 38.504-22.364 71.808-56.348 97.048-98.336h-409.582c25.266 42.032 58.612 76.042 97.166 98.406 71.654 40.644 75.606 93.366 75.626 125.366v64.228c0 31.992-3.804 84.914-75.744 125.664-72.622 42.18-126.738 125.684-143.090 226.336h501.67c-16.364-100.708-70.53-184.248-143.212-226.406z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hour-glass","loading","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":10,"prevSize":32,"code":59732,"name":"hour-glass"},"setIdx":6,"setId":4,"iconIdx":10},{"icon":{"paths":["M192 512c0-12.18 0.704-24.196 2.030-36.022l-184.98-60.104c-5.916 31.14-9.050 63.264-9.050 96.126 0 147.23 62.166 279.922 161.654 373.324l114.284-157.296c-52.124-56.926-83.938-132.758-83.938-216.028zM832 512c0 83.268-31.812 159.102-83.938 216.028l114.284 157.296c99.488-93.402 161.654-226.094 161.654-373.324 0-32.862-3.132-64.986-9.048-96.126l-184.98 60.104c1.324 11.828 2.028 23.842 2.028 36.022zM576 198.408c91.934 18.662 169.544 76.742 214.45 155.826l184.978-60.102c-73.196-155.42-222.24-268.060-399.428-290.156v194.432zM233.55 354.232c44.906-79.084 122.516-137.164 214.45-155.826v-194.43c-177.188 22.096-326.23 134.736-399.426 290.154l184.976 60.102zM644.556 803.328c-40.39 18.408-85.272 28.672-132.556 28.672s-92.166-10.264-132.554-28.67l-114.292 157.31c73.206 40.366 157.336 63.36 246.846 63.36s173.64-22.994 246.848-63.36l-114.292-157.312z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["spinner","loading","loading-wheel","busy","wait"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":32,"code":59731,"name":"spinner"},"setIdx":6,"setId":4,"iconIdx":11},{"icon":{"paths":["M658.744 749.256l-210.744-210.746v-282.51h128v229.49l173.256 173.254zM512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384s-171.922 384-384 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["clock","time","schedule"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":12,"prevSize":32,"code":59728,"name":"clock"},"setIdx":6,"setId":4,"iconIdx":12},{"icon":{"paths":["M128 320v640c0 35.2 28.8 64 64 64h576c35.2 0 64-28.8 64-64v-640h-704zM320 896h-64v-448h64v448zM448 896h-64v-448h64v448zM576 896h-64v-448h64v448zM704 896h-64v-448h64v448z","M848 128h-208v-80c0-26.4-21.6-48-48-48h-224c-26.4 0-48 21.6-48 48v80h-208c-26.4 0-48 21.6-48 48v80h832v-80c0-26.4-21.6-48-48-48zM576 128h-192v-63.198h192v63.198z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bin","trashcan","remove","delete","recycle","dispose"],"grid":16},"attrs":[{},{}],"properties":{"order":1,"id":13,"name":"bin2","prevSize":32,"code":59650},"setIdx":6,"setId":4,"iconIdx":13},{"icon":{"paths":["M512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 960.002c-62.958 0-122.872-13.012-177.23-36.452l233.148-262.29c5.206-5.858 8.082-13.422 8.082-21.26v-96c0-17.674-14.326-32-32-32-112.99 0-232.204-117.462-233.374-118.626-6-6.002-14.14-9.374-22.626-9.374h-128c-17.672 0-32 14.328-32 32v192c0 12.122 6.848 23.202 17.69 28.622l110.31 55.156v187.886c-116.052-80.956-192-215.432-192-367.664 0-68.714 15.49-133.806 43.138-192h116.862c8.488 0 16.626-3.372 22.628-9.372l128-128c6-6.002 9.372-14.14 9.372-22.628v-77.412c40.562-12.074 83.518-18.588 128-18.588 70.406 0 137.004 16.26 196.282 45.2-4.144 3.502-8.176 7.164-12.046 11.036-36.266 36.264-56.236 84.478-56.236 135.764s19.97 99.5 56.236 135.764c36.434 36.432 85.218 56.264 135.634 56.26 3.166 0 6.342-0.080 9.518-0.236 13.814 51.802 38.752 186.656-8.404 372.334-0.444 1.744-0.696 3.488-0.842 5.224-81.324 83.080-194.7 134.656-320.142 134.656z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["earth","globe","language","web","internet","sphere","planet"],"defaultCode":59850,"grid":16},"attrs":[],"properties":{"ligatures":"earth, globe2","name":"earth","id":14,"order":91,"prevSize":32,"code":59850},"setIdx":6,"setId":4,"iconIdx":14},{"icon":{"paths":["M512.002 193.212v-65.212h128v-64c0-35.346-28.654-64-64.002-64h-191.998c-35.346 0-64 28.654-64 64v64h128v65.212c-214.798 16.338-384 195.802-384 414.788 0 229.75 186.25 416 416 416s416-186.25 416-416c0-218.984-169.202-398.448-384-414.788zM706.276 834.274c-60.442 60.44-140.798 93.726-226.274 93.726s-165.834-33.286-226.274-93.726c-60.44-60.44-93.726-140.8-93.726-226.274s33.286-165.834 93.726-226.274c58.040-58.038 134.448-91.018 216.114-93.548l-21.678 314.020c-1.86 26.29 12.464 37.802 31.836 37.802s33.698-11.512 31.836-37.802l-21.676-314.022c81.666 2.532 158.076 35.512 216.116 93.55 60.44 60.44 93.726 140.8 93.726 226.274s-33.286 165.834-93.726 226.274z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["stopwatch","time","speed","meter","chronometer"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":15,"prevSize":32,"code":59715,"name":"elapsed"},"setIdx":6,"setId":4,"iconIdx":15},{"icon":{"paths":["M522.2 438.8v175.6h290.4c-11.8 75.4-87.8 220.8-290.4 220.8-174.8 0-317.4-144.8-317.4-323.2s142.6-323.2 317.4-323.2c99.4 0 166 42.4 204 79l139-133.8c-89.2-83.6-204.8-134-343-134-283 0-512 229-512 512s229 512 512 512c295.4 0 491.6-207.8 491.6-500.2 0-33.6-3.6-59.2-8-84.8l-483.6-0.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["google","brand"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":16,"prevSize":32,"code":59707,"name":"google"},"setIdx":6,"setId":4,"iconIdx":16},{"icon":{"paths":["M592 448h-16v-192c0-105.87-86.13-192-192-192h-128c-105.87 0-192 86.13-192 192v192h-16c-26.4 0-48 21.6-48 48v480c0 26.4 21.6 48 48 48h544c26.4 0 48-21.6 48-48v-480c0-26.4-21.6-48-48-48zM192 256c0-35.29 28.71-64 64-64h128c35.29 0 64 28.71 64 64v192h-256v-192z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["lock","secure","private","encrypted"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":17,"prevSize":32,"code":59700,"name":"lock"},"setIdx":6,"setId":4,"iconIdx":17},{"icon":{"paths":["M0.35 512l-0.35-312.074 384-52.144v364.218zM448 138.482l511.872-74.482v448h-511.872zM959.998 576l-0.126 448-511.872-72.016v-375.984zM384 943.836l-383.688-52.594-0.020-315.242h383.708z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["windows8","brand","os"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":18,"prevSize":32,"code":59712,"name":"microsoft"},"setIdx":6,"setId":4,"iconIdx":18},{"icon":{"paths":["M128 128h320v768h-320zM576 128h320v768h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pause","player"],"grid":16},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":32,"code":59695,"name":"pause"},"setIdx":6,"setId":4,"iconIdx":19},{"icon":{"paths":["M192 128l640 384-640 384z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["play","player"],"grid":16},"attrs":[{}],"properties":{"order":3,"id":20,"prevSize":32,"code":59696,"name":"play"},"setIdx":6,"setId":4,"iconIdx":20},{"icon":{"paths":["M889.68 166.32c-93.608-102.216-228.154-166.32-377.68-166.32-282.77 0-512 229.23-512 512h96c0-229.75 186.25-416 416-416 123.020 0 233.542 53.418 309.696 138.306l-149.696 149.694h352v-352l-134.32 134.32z","M928 512c0 229.75-186.25 416-416 416-123.020 0-233.542-53.418-309.694-138.306l149.694-149.694h-352v352l134.32-134.32c93.608 102.216 228.154 166.32 377.68 166.32 282.77 0 512-229.23 512-512h-96z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["loop","repeat","player","reload","refresh","update","synchronize","arrows"],"grid":16},"attrs":[{},{}],"properties":{"order":49,"id":21,"prevSize":32,"code":59694,"name":"reset"},"setIdx":6,"setId":4,"iconIdx":21},{"icon":{"paths":["M933.79 610.25c-53.726-93.054-21.416-212.304 72.152-266.488l-100.626-174.292c-28.75 16.854-62.176 26.518-97.846 26.518-107.536 0-194.708-87.746-194.708-195.99h-201.258c0.266 33.41-8.074 67.282-25.958 98.252-53.724 93.056-173.156 124.702-266.862 70.758l-100.624 174.292c28.97 16.472 54.050 40.588 71.886 71.478 53.638 92.908 21.512 211.92-71.708 266.224l100.626 174.292c28.65-16.696 61.916-26.254 97.4-26.254 107.196 0 194.144 87.192 194.7 194.958h201.254c-0.086-33.074 8.272-66.57 25.966-97.218 53.636-92.906 172.776-124.594 266.414-71.012l100.626-174.29c-28.78-16.466-53.692-40.498-71.434-71.228zM512 719.332c-114.508 0-207.336-92.824-207.336-207.334 0-114.508 92.826-207.334 207.336-207.334 114.508 0 207.332 92.826 207.332 207.334-0.002 114.51-92.824 207.334-207.332 207.334z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["cog","gear","preferences","settings","generate","control","options"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":22,"prevSize":32,"code":59693,"name":"settings2"},"setIdx":6,"setId":4,"iconIdx":22},{"icon":{"paths":["M512 128c-247.424 0-448 200.576-448 448s200.576 448 448 448 448-200.576 448-448-200.576-448-448-448zM512 936c-198.824 0-360-161.178-360-360 0-198.824 161.176-360 360-360 198.822 0 360 161.176 360 360 0 198.822-161.178 360-360 360zM934.784 287.174c16.042-28.052 25.216-60.542 25.216-95.174 0-106.040-85.96-192-192-192-61.818 0-116.802 29.222-151.92 74.596 131.884 27.236 245.206 105.198 318.704 212.578v0zM407.92 74.596c-35.116-45.374-90.102-74.596-151.92-74.596-106.040 0-192 85.96-192 192 0 34.632 9.174 67.122 25.216 95.174 73.5-107.38 186.822-185.342 318.704-212.578z","M512 576v-256h-64v320h256v-64z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["alarm","time","clock"],"grid":16},"attrs":[{},{}],"properties":{"order":2,"id":23,"prevSize":32,"code":59716,"name":"timeout"},"setIdx":6,"setId":4,"iconIdx":23},{"icon":{"paths":["M768 64c105.87 0 192 86.13 192 192v192h-128v-192c0-35.29-28.71-64-64-64h-128c-35.29 0-64 28.71-64 64v192h16c26.4 0 48 21.6 48 48v480c0 26.4-21.6 48-48 48h-544c-26.4 0-48-21.6-48-48v-480c0-26.4 21.6-48 48-48h400v-192c0-105.87 86.13-192 192-192h128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["unlocked","lock-open"],"grid":16},"attrs":[{}],"properties":{"order":1,"id":24,"prevSize":32,"code":59699,"name":"unlocked"},"setIdx":6,"setId":4,"iconIdx":24},{"icon":{"paths":["M66.337 575.491l276.668-171.531v-57.177l-331.627 207.614v42.189l331.627 207.614-0-57.177z","M957.663 575.49l-276.668-171.531v-57.177l331.627 207.614v42.189l-331.627 207.614 0-57.177z","M583.295 214.183l-200.825 621.623 53.007 17.527 200.837-621.623z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["prerender"],"grid":0},"attrs":[{},{},{}],"properties":{"order":114,"id":0,"name":"prerender","prevSize":32,"code":59724},"setIdx":2,"setId":8,"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,"tags":["circle"],"grid":0},"attrs":[{}],"properties":{"order":106,"id":1,"name":"circle","prevSize":32,"code":59729},"setIdx":2,"setId":8,"iconIdx":1},{"icon":{"paths":["M512 0c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h128v870.4h-128c-15.36 0-25.6 10.24-25.6 25.6s10.24 25.6 25.6 25.6h307.2c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-128v-870.4h128c15.36 0 25.6-10.24 25.6-25.6s-10.24-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.16 0-51.2 23.040-51.2 51.2v460.8c0 28.16 23.040 51.2 51.2 51.2h537.6v-51.2h-512c-15.36 0-25.6-10.24-25.6-25.6v-409.6c0-15.36 10.24-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c15.36 0 25.6 10.24 25.6 25.6v409.6c0 15.36-10.24 25.6-25.6 25.6h-204.8v51.2h230.4c28.16 0 51.2-23.040 51.2-51.2v-460.8c0-28.16-23.040-51.2-51.2-51.2h-230.4z","M386.56 606.72c0 12.8-7.68 23.040-20.48 25.6-28.16 10.24-58.88 15.36-92.16 15.36-35.84 0-66.56-10.24-84.48-25.6s-25.6-38.4-25.6-66.56 10.24-51.2 25.6-66.56c17.92-17.92 46.080-23.040 84.48-23.040h69.12v-38.4c0-35.84-25.6-53.76-64-53.76-23.040 0-46.080 7.68-69.12 20.48-2.56 2.56-5.12 2.56-10.24 2.56-10.24 0-20.48-7.68-20.48-20.48 0-7.68 2.56-12.8 10.24-17.92 30.72-20.48 61.44-25.6 92.16-25.6 56.32 0 104.96 30.72 104.96 92.16v181.76zM345.6 501.76h-69.12c-61.44 0-69.12 28.16-69.12 53.76s7.68 56.32 69.12 56.32c23.040 0 46.080-2.56 69.12-10.24v-99.84z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Slug"],"grid":0},"attrs":[{},{}],"properties":{"order":103,"id":2,"name":"control-Slug","prevSize":32,"code":59727},"setIdx":2,"setId":8,"iconIdx":2},{"icon":{"paths":["M295.954 822.751h-94.705c-47.353 0-88.786-41.434-88.786-88.786v-491.283c0-47.353 41.434-88.786 88.786-88.786h94.705v-59.191h-94.705c-82.867 0-147.977 65.11-147.977 147.977v491.283c0 82.867 65.11 147.977 147.977 147.977h94.705v-59.191z","M970.728 473.526c-82.867-171.653-201.249-378.821-272.277-378.821h-112.462v59.191h112.462c35.514 11.838 136.139 177.572 213.087 337.387-76.948 153.896-177.572 325.549-213.087 337.387h-112.462v59.191h112.462c71.029 0 183.491-207.168 272.277-384.74l5.919-11.838-5.919-17.757z","M266.358 337.341v260.462h59.191v-260.462z","M479.422 337.341v260.462h59.191v-260.462z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["Tags"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":98,"id":3,"name":"type-Tags","prevSize":32,"code":59722},"setIdx":2,"setId":8,"iconIdx":3},{"icon":{"paths":["M512 102.4c-200.4 0-366.954 144.072-402.4 334.2-0.031 0.165-0.069 0.335-0.1 0.5-2.974 16.061-4.76 32.441-5.8 49.1-0.017 0.271-0.084 0.529-0.1 0.8 0.019 0.004 0.080-0.004 0.1 0-0.503 8.31-1.3 16.564-1.3 25 0 226.202 183.398 409.6 409.6 409.6 208.165 0 379.707-155.44 405.8-356.5 0.004-0.033-0.004-0.067 0-0.1 1.94-14.978 3.124-30.16 3.4-45.6 0.044-2.487 0.4-4.903 0.4-7.4 0-226.202-183.398-409.6-409.6-409.6zM512 153.6c185.461 0 337.902 140.924 356.4 321.5-35.181-21.812-84.232-39.9-151.6-39.9-85.35 0-140.891 41.606-194.6 81.9-49.152 36.864-95.55 71.7-163.8 71.7-86.067 0-135.862-54.67-175.9-98.6-9.001-9.901-17.11-17.483-25.4-25.3 23.131-175.603 172.981-311.3 354.9-311.3zM716.8 486.4c77.828 0 125.173 28.221 152.2 52.8-13.96 185.173-168.254 331.2-357 331.2-190.097 0-345.175-148.14-357.2-335.2 41.826 45.372 102.577 104.8 203.6 104.8 85.35 0 140.891-41.606 194.6-81.9 49.152-36.915 95.55-71.7 163.8-71.7z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["activity"],"grid":0},"attrs":[{}],"properties":{"order":12,"id":4,"name":"activity, history, time","prevSize":32,"code":59652},"setIdx":2,"setId":8,"iconIdx":4},{"icon":{"paths":["M512 0c-35.392 0-64 28.608-64 64v384h-384c-35.392 0-64 28.608-64 64s28.608 64 64 64h384v384c0 35.392 28.608 64 64 64s64-28.608 64-64v-384h384c35.392 0 64-28.608 64-64s-28.608-64-64-64h-384v-384c0-35.392-28.608-64-64-64z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["add"],"grid":0},"attrs":[{}],"properties":{"order":13,"id":5,"name":"add, plus","prevSize":32,"code":59653},"setIdx":2,"setId":8,"iconIdx":5},{"icon":{"paths":["M512 102.4c-226.202 0-409.6 183.398-409.6 409.6s183.398 409.6 409.6 409.6c226.202 0 409.6-183.398 409.6-409.6s-183.398-409.6-409.6-409.6zM512 153.6c197.632 0 358.4 160.819 358.4 358.4s-160.768 358.4-358.4 358.4c-197.632 0-358.4-160.819-358.4-358.4s160.768-358.4 358.4-358.4zM691.9 333c-12.893 0.002-25.782 4.882-35.5 14.6l-222.2 221.9-67.7-67.5c-19.19-19.294-51.085-19.215-70.3 0-19.15 19.15-19.15 51.050 0 70.2 0.198 0.2 26.198 26.681 52 53 12.95 13.209 25.761 26.372 35.2 36 4.719 4.814 8.607 8.755 11.2 11.4 1.296 1.322 2.293 2.281 2.9 2.9 0.279 0.282 0.488 0.486 0.6 0.6 0.001 0.001 7.591-7.429 14.6-14.3l-14.5 14.4 0.2 0.2v0.1c19.43 19.327 51.57 19.327 71 0v-0.1l258.1-257.6c19.546-19.447 19.521-51.885-0.1-71.3-9.731-9.679-22.607-14.502-35.5-14.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle"],"grid":0},"attrs":[{}],"properties":{"order":14,"id":6,"name":"check-circle","prevSize":32,"code":59654},"setIdx":2,"setId":8,"iconIdx":6},{"icon":{"paths":["M512 1024c-282.778 0-512-229.222-512-512s229.222-512 512-512 512 229.222 512 512-229.222 512-512 512zM855.808 270.592c-19.2-19.2-50.278-19.2-69.478 0l-376.73 376.73-171.878-171.93c-19.2-19.2-50.278-19.2-69.478 0s-19.2 50.278 0 69.478c0 0 201.523 205.261 204.8 208.486 9.984 10.138 23.347 14.643 36.557 14.080 13.21 0.563 26.573-3.942 36.608-14.029 3.277-3.226 409.6-413.286 409.6-413.286 19.2-19.2 19.2-50.33 0-69.53z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["check-circle-filled"],"grid":0},"attrs":[{}],"properties":{"order":27,"id":7,"name":"check-circle-filled","prevSize":32,"code":59655},"setIdx":2,"setId":8,"iconIdx":7},{"icon":{"paths":["M601.024 512l276.736 276.736c24.512 24.576 24.512 64.384 0 89.024-24.64 24.576-64.384 24.576-89.024 0l-276.736-276.736-276.736 276.736c-24.512 24.576-64.384 24.576-89.024 0-24.512-24.64-24.512-64.448 0-89.024l276.736-276.736-276.736-276.736c-24.512-24.576-24.512-64.384 0-89.024 24.64-24.576 64.512-24.576 89.024 0l276.736 276.736 276.736-276.736c24.64-24.576 64.384-24.576 89.024 0 24.512 24.64 24.512 64.448 0 89.024l-276.736 276.736z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["close"],"grid":0},"attrs":[{}],"properties":{"order":28,"id":8,"name":"close","prevSize":32,"code":59656},"setIdx":2,"setId":8,"iconIdx":8},{"icon":{"paths":["M409.6 435.2h-153.6v51.2h153.6v-51.2zM409.6 332.8h-153.6v51.2h153.6v-51.2zM256 691.2h409.6v-51.2h-409.6v51.2zM409.6 230.4h-153.6v51.2h153.6v-51.2zM870.4 179.2h-51.2v-51.2c0-28.262-22.938-51.2-51.2-51.2h-614.4c-28.262 0-51.2 22.938-51.2 51.2v665.6c0 28.262 22.938 51.2 51.2 51.2h51.2v51.2c0 28.262 22.938 51.2 51.2 51.2h614.4c28.262 0 51.2-22.938 51.2-51.2v-665.6c0-28.262-22.938-51.2-51.2-51.2zM179.2 793.6c-14.157 0-25.6-11.443-25.6-25.6v-614.4c0-14.131 11.443-25.6 25.6-25.6h563.2c14.157 0 25.6 11.469 25.6 25.6v614.4c0 14.157-11.443 25.6-25.6 25.6h-563.2zM870.4 870.4c0 14.157-11.443 25.6-25.6 25.6h-563.2c-14.157 0-25.6-11.443-25.6-25.6v-25.6h512c28.262 0 51.2-22.938 51.2-51.2v-563.2h25.6c14.157 0 25.6 11.469 25.6 25.6v614.4zM614.4 230.4h-102.4c-28.262 0-51.2 22.938-51.2 51.2v153.6c0 28.262 22.938 51.2 51.2 51.2h102.4c28.262 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.938-51.2-51.2-51.2zM614.4 435.2h-102.4v-153.6h102.4v153.6zM256 588.8h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":0},"attrs":[{}],"properties":{"order":37,"id":9,"name":"type-References","prevSize":32,"code":59657},"setIdx":2,"setId":8,"iconIdx":9},{"icon":{"paths":["M793.6 844.8c0 14.157-11.443 25.6-25.6 25.6h-665.6c-14.131 0-25.6-11.443-25.6-25.6v-665.6c0-14.157 11.469-25.6 25.6-25.6h665.6c14.157 0 25.6 11.443 25.6 25.6v102.4h51.2v-128c0-28.262-22.938-51.2-51.2-51.2h-716.8c-28.262 0-51.2 22.938-51.2 51.2v716.8c0 28.262 22.938 51.2 51.2 51.2h716.8c28.262 0 51.2-22.938 51.2-51.2v-281.6h-51.2v256zM991.078 237.747c-9.958-9.958-26.035-9.958-35.968 0l-391.91 391.91-238.31-238.31c-9.958-9.958-26.061-9.958-35.942 0-9.958 9.907-9.958 26.010 0 35.942l254.874 254.874c0.461 0.538 0.614 1.203 1.126 1.69 5.043 5.018 11.674 7.475 18.278 7.373 6.605 0.102 13.235-2.355 18.278-7.373 0.512-0.512 0.666-1.178 1.126-1.69l408.448-408.474c9.933-9.933 9.933-26.035 0-35.942z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-checkbox"],"grid":0},"attrs":[{}],"properties":{"order":38,"id":10,"name":"control-Checkbox","prevSize":32,"code":59658},"setIdx":2,"setId":8,"iconIdx":10},{"icon":{"paths":["M51.2 0c-28.262 0-51.2 22.938-51.2 51.2v281.6c0 28.262 22.938 51.2 51.2 51.2h921.6c28.262 0 51.2-22.938 51.2-51.2v-281.6c0-28.262-22.938-51.2-51.2-51.2h-921.6zM76.8 51.2h512v281.6h-512c-14.157 0-25.6-11.443-25.6-25.6v-230.4c0-14.157 11.443-25.6 25.6-25.6zM640 51.2h307.2c14.157 0 25.6 11.443 25.6 25.6v230.4c0 14.157-11.443 25.6-25.6 25.6h-307.2v-281.6zM716.8 153.6c-0.41 0.358 89.139 102.938 89.6 102.4 0.512 0 89.6-95.36 89.6-102.4 0 0.384-172.16 0-179.2 0zM128 435.2c-42.394 0-76.8 34.406-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.406 76.8-76.8s-34.406-76.8-76.8-76.8zM128 486.4c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 486.4c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 640c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 691.2c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 691.2c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640zM128 844.8c-42.394 0-76.8 34.381-76.8 76.8s34.406 76.8 76.8 76.8c42.394 0 76.8-34.381 76.8-76.8s-34.406-76.8-76.8-76.8zM128 896c14.157 0 25.6 11.443 25.6 25.6s-11.443 25.6-25.6 25.6c-14.157 0-25.6-11.443-25.6-25.6s11.443-25.6 25.6-25.6zM307.2 896c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h640c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-640z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-dropdown"],"grid":0},"attrs":[{}],"properties":{"order":39,"id":11,"name":"control-Dropdown","prevSize":32,"code":59659},"setIdx":2,"setId":8,"iconIdx":11},{"icon":{"paths":["M512 0c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h128v870.4h-128c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h307.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-128v-870.4h128c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-307.2zM51.2 204.8c-28.262 0-51.2 22.938-51.2 51.2v460.8c0 28.262 22.938 51.2 51.2 51.2h537.6v-51.2h-512c-14.131 0-25.6-11.443-25.6-25.6v-409.6c0-14.157 11.469-25.6 25.6-25.6h512v-51.2h-537.6zM742.4 204.8v51.2h204.8c14.157 0 25.6 11.443 25.6 25.6v409.6c0 14.157-11.443 25.6-25.6 25.6h-204.8v51.2h230.4c28.262 0 51.2-22.938 51.2-51.2v-460.8c0-28.262-22.938-51.2-51.2-51.2h-230.4zM285.9 307c-0.589 0.051-1.161 0.048-1.75 0.15-8.243 0.051-16.396 4.474-20.85 13.050l-132.55 306.25c-6.656 12.749-2.866 28.981 8.5 36.2 11.341 7.219 25.97 2.749 32.6-10l27.65-63.85h170.5c0.512 0 0.914-0.224 1.4-0.25l27.45 64.050c6.63 12.749 21.136 17.269 32.4 10.050s15.005-23.451 8.4-36.2l-131.3-306.25c-4.454-8.576-12.432-12.973-20.65-13.050-0.614-0.102-1.211-0.099-1.8-0.15zM285.9 389.15l63.65 148.45h-127.9l64.25-148.45z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-input"],"grid":0},"attrs":[{}],"properties":{"order":41,"id":12,"name":"control-Input","prevSize":32,"code":59660},"setIdx":2,"setId":8,"iconIdx":12},{"icon":{"paths":["M153.6 716.8c-84.787 0-153.6 68.813-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.813 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 972.8c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM153.6 0c-84.787 0-153.6 68.787-153.6 153.6s68.813 153.6 153.6 153.6c84.787 0 153.6-68.787 153.6-153.6s-68.813-153.6-153.6-153.6zM153.6 256c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 358.4c-84.787 0-153.6 68.787-153.6 153.6 0 84.787 68.813 153.6 153.6 153.6s153.6-68.813 153.6-153.6c0-84.813-68.813-153.6-153.6-153.6zM153.6 614.4c-56.55 0-102.4-45.85-102.4-102.4s45.85-102.4 102.4-102.4c56.55 0 102.4 45.85 102.4 102.4s-45.85 102.4-102.4 102.4zM153.6 102.4c-28.262 0-51.2 22.938-51.2 51.2s22.938 51.2 51.2 51.2c28.262 0 51.2-22.938 51.2-51.2s-22.938-51.2-51.2-51.2zM998.4 844.8h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-radio"],"grid":0},"attrs":[{}],"properties":{"order":42,"id":13,"name":"control-Radio","prevSize":32,"code":59661},"setIdx":2,"setId":8,"iconIdx":13},{"icon":{"paths":["M0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8h-204.8zM819.2 0v204.8h204.8v-204.8h-204.8zM51.2 51.2h102.4v102.4h-102.4v-102.4zM870.4 51.2h102.4v102.4h-102.4v-102.4zM281.6 76.8v51.2h102.4v-51.2h-102.4zM486.4 76.8v51.2h102.4v-51.2h-102.4zM691.2 76.8v51.2h102.4v-51.2h-102.4zM333.25 204.8c-7.091-0.307-14.348 2.097-19.75 7.55l-74.75 74.75c-10.317 10.291-10.317 27.083 0 37.4s27.059 10.317 37.35 0l68.45-68.5h141.85v486.4h-50.7c-7.117-0.307-14.348 2.097-19.75 7.55l-23.6 23.55c-10.317 10.317-10.317 27.083 0 37.4 10.291 10.317 27.109 10.317 37.4 0l17.25-17.3h129.75l18.050 18c10.394 10.368 27.181 10.368 37.6 0 10.368-10.394 10.368-27.181 0-37.6l-24-24c-5.478-5.478-12.682-7.907-19.85-7.6h-50.95v-486.4h141.55l69.25 69.2c10.394 10.368 27.155 10.368 37.6 0 10.368-10.368 10.368-27.181 0-37.6l-75.2-75.2c-5.478-5.478-12.706-7.907-19.9-7.6h-357.65zM896 281.6v102.4h51.2v-102.4h-51.2zM76.8 384v102.4h51.2v-102.4h-51.2zM896 486.4v102.4h51.2v-102.4h-51.2zM76.8 588.8v102.4h51.2v-102.4h-51.2zM896 691.2v102.4h51.2v-102.4h-51.2zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6h-51.2zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8h-204.8zM51.2 870.4h102.4v102.4h-102.4v-102.4zM870.4 870.4h102.4v102.4h-102.4v-102.4zM384 896v51.2h102.4v-51.2h-102.4zM588.8 896v51.2h102.4v-51.2h-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-textarea"],"grid":0},"attrs":[{}],"properties":{"order":17,"id":14,"name":"control-TextArea","prevSize":32,"code":59662},"setIdx":2,"setId":8,"iconIdx":14},{"icon":{"paths":["M332.8 25.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 76.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM332.8 128c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM332.8 179.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8zM332.8 537.6c-127.258 0-230.4 103.142-230.4 230.4s103.142 230.4 230.4 230.4h358.4c127.258 0 230.4-103.142 230.4-230.4s-103.142-230.4-230.4-230.4h-358.4zM332.8 588.8h358.4c98.97 0 179.2 80.23 179.2 179.2s-80.23 179.2-179.2 179.2h-358.4c-98.97 0-179.2-80.23-179.2-179.2s80.23-179.2 179.2-179.2zM691.2 640c-70.707 0-128 57.293-128 128s57.293 128 128 128c70.707 0 128-57.293 128-128s-57.293-128-128-128zM691.2 691.2c42.419 0 76.8 34.381 76.8 76.8s-34.381 76.8-76.8 76.8c-42.419 0-76.8-34.381-76.8-76.8s34.381-76.8 76.8-76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-toggle"],"grid":0},"attrs":[{}],"properties":{"order":16,"id":15,"name":"control-Toggle","prevSize":32,"code":59663},"setIdx":2,"setId":8,"iconIdx":15},{"icon":{"paths":["M204.8 51.2c-56.525 0-102.4 45.875-102.4 102.4v512c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4h-409.6zM204.8 102.4h409.6c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2v-512c0-28.314 22.938-51.2 51.2-51.2zM768 204.8v51.2c28.262 0 51.2 22.886 51.2 51.2v512c0 28.314-22.938 51.2-51.2 51.2h-409.6c-28.262 0-51.2-22.886-51.2-51.2h-51.2c0 56.525 45.875 102.4 102.4 102.4h409.6c56.525 0 102.4-45.875 102.4-102.4v-512c0-56.525-45.875-102.4-102.4-102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["copy"],"grid":0},"attrs":[{}],"properties":{"order":90,"id":16,"name":"copy","prevSize":32,"code":59664},"setIdx":2,"setId":8,"iconIdx":16},{"icon":{"paths":["M828.8 1024h-633.6c-105.6 0-195.2-89.6-195.2-195.2v-320c0-281.6 227.2-508.8 505.6-508.8 288 0 518.4 230.4 518.4 518.4v310.4c0 105.6-89.6 195.2-195.2 195.2zM505.6 64c-243.2 0-441.6 198.4-441.6 441.6v320c0 73.6 60.8 134.4 131.2 134.4h630.4c73.6 0 131.2-60.8 131.2-131.2v-310.4c3.2-249.6-201.6-454.4-451.2-454.4z","M512 668.8c-3.2 0-6.4 0-6.4 0-32-3.2-64-19.2-80-48l-192-278.4c-9.6-9.6-9.6-25.6-0-38.4 9.6-9.6 25.6-12.8 38.4-6.4l294.4 172.8c28.8 16 48 44.8 51.2 76.8s-6.4 64-28.8 89.6c-19.2 22.4-48 32-76.8 32zM364.8 428.8l108.8 160c6.4 9.6 19.2 19.2 32 19.2s25.6-3.2 35.2-12.8c9.6-9.6 12.8-22.4 9.6-35.2s-9.6-22.4-19.2-32l-166.4-99.2z","M678.4 364.8c-6.4 0-12.8-3.2-19.2-6.4-16-9.6-19.2-28.8-9.6-44.8l54.4-83.2c9.6-16 28.8-19.2 44.8-9.6 19.2 12.8 22.4 35.2 12.8 48l-54.4 83.2c-6.4 9.6-16 12.8-28.8 12.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["dashboard"],"grid":0},"attrs":[{},{},{}],"properties":{"order":26,"id":17,"name":"dashboard","prevSize":32,"code":59665},"setIdx":2,"setId":8,"iconIdx":17},{"icon":{"paths":["M597.35 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.418 25.6 25.6 25.6zM776.55 204.8h-153.6v-51.2c0-28.314-22.886-51.2-51.2-51.2h-102.4c-28.262 0-51.2 22.886-51.2 51.2v51.2h-153.6c-28.262 0-51.2 22.886-51.2 51.2v102.4c0 28.314 22.938 51.2 51.2 51.2v460.8c0 28.314 22.938 51.2 51.2 51.2h409.6c28.314 0 51.2-22.886 51.2-51.2v-460.8c28.314 0 51.2-22.886 51.2-51.2v-102.4c0-28.314-22.938-51.2-51.2-51.2zM469.35 153.6h102.4v51.2h-102.4v-51.2zM725.35 870.4h-409.6v-460.8h409.6v460.8zM776.55 358.4h-512v-102.4h512v102.4zM443.75 819.2c14.131 0 25.6-11.469 25.6-25.6v-307.2c0-14.080-11.469-25.6-25.6-25.6s-25.6 11.52-25.6 25.6v307.2c0 14.131 11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete"],"grid":0},"attrs":[{}],"properties":{"order":29,"id":18,"name":"delete, bin","prevSize":32,"code":59666},"setIdx":2,"setId":8,"iconIdx":18},{"icon":{"paths":["M832 128h-192v-64c0-35.392-28.608-64-64-64h-128c-35.328 0-64 28.608-64 64v64h-192c-35.328 0-64 28.608-64 64v128c0 35.392 28.672 64 64 64v512c0 35.392 28.672 64 64 64h512c35.392 0 64-28.608 64-64v-512c35.392 0 64-28.608 64-64v-128c0-35.392-28.608-64-64-64zM448 64h128v64h-128v-64zM448 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM640 800c0 17.664-14.336 32-32 32s-32-14.336-32-32v-320c0-17.6 14.336-32 32-32s32 14.4 32 32v320zM832 320h-640v-128h640v128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["delete-filled"],"grid":0},"attrs":[{}],"properties":{"order":36,"id":19,"name":"delete-filled","prevSize":32,"code":59667},"setIdx":2,"setId":8,"iconIdx":19},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c98.816 0 179.2 80.384 179.2 179.2s-80.384 179.2-179.2 179.2c-98.816 0-179.2-80.384-179.2-179.2s80.384-179.2 179.2-179.2zM227.2 665.6c-12.39 0-22.4 10.061-22.4 22.4v6.4c0 12.39 10.010 22.4 22.4 22.4h211.2c12.39 0 22.4-10.010 22.4-22.4v-6.4c0-12.39-10.061-22.4-22.4-22.4h-211.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-delete"],"grid":0},"attrs":[{}],"properties":{"order":35,"id":20,"name":"document-delete","prevSize":32,"code":59668},"setIdx":2,"setId":8,"iconIdx":20},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8c-127.232 0-230.4 103.168-230.4 230.4s103.168 230.4 230.4 230.4c127.232 0 230.4-103.168 230.4-230.4s-103.168-230.4-230.4-230.4zM332.8 512c39.934 0 76.475 13.533 106.3 35.7l-250.4 249c-21.807-29.683-35.1-65.924-35.1-105.5 0-98.816 80.384-179.2 179.2-179.2zM477 585.7c21.785 29.674 35 65.947 35 105.5 0 98.816-80.384 179.2-179.2 179.2-39.906 0-76.386-13.561-106.2-35.7l250.4-249z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-disable"],"grid":0},"attrs":[{}],"properties":{"order":40,"id":21,"name":"document-disable","prevSize":32,"code":59669},"setIdx":2,"setId":8,"iconIdx":21},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v256h51.2v-256h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-343.4zM716.8 189.8l117.4 117.4h-117.4v-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2l-230.4-256zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7l161.5-179.5z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-publish"],"grid":0},"attrs":[{}],"properties":{"order":44,"id":22,"name":"document-publish","prevSize":32,"code":59670},"setIdx":2,"setId":8,"iconIdx":22},{"icon":{"paths":["M665.6 51.2v102.4h102.4v-102.4h-102.4zM460.8 153.6h102.4v-102.4h-102.4v102.4zM460.8 358.4h102.4v-102.4h-102.4v102.4zM665.6 358.4h102.4v-102.4h-102.4v102.4zM665.6 563.2h102.4v-102.4h-102.4v102.4zM460.8 563.2h102.4v-102.4h-102.4v102.4zM460.8 768h102.4v-102.4h-102.4v102.4zM665.6 768h102.4v-102.4h-102.4v102.4zM665.6 972.8h102.4v-102.4h-102.4v102.4zM460.8 972.8h102.4v-102.4h-102.4v102.4zM256 153.6h102.4v-102.4h-102.4v102.4zM256 358.4h102.4v-102.4h-102.4v102.4zM256 563.2h102.4v-102.4h-102.4v102.4zM256 768h102.4v-102.4h-102.4v102.4zM256 972.8h102.4v-102.4h-102.4v102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["drag"],"grid":0},"attrs":[{}],"properties":{"order":43,"id":23,"name":"drag","prevSize":32,"code":59671},"setIdx":2,"setId":8,"iconIdx":23},{"icon":{"paths":["M921.6 281.958c0-70.707-171.878-128.154-384-128.154s-384 57.19-384 127.898c0 10.035 3.789 19.712 10.342 29.030 0-0.051 296.858 406.067 296.858 406.067v256l153.6-51.2v-204.8c0 0 298.752-408.166 299.725-409.702 0 0 7.475-16.64 7.475-25.139zM537.6 204.8c206.899 0 318.208 53.248 332.083 76.8-13.875 23.552-125.184 76.8-332.083 76.8s-318.208-53.248-332.083-76.8c13.875-23.552 125.184-76.8 332.083-76.8zM869.376 345.856v0 0zM573.030 686.592c-6.4 8.755-9.83 19.354-9.83 30.208v167.885l-51.2 17.050v-184.934c0-10.854-3.43-21.453-9.83-30.208l-228.147-312.115c68.762 21.709 161.382 35.123 263.578 35.123 102.298 0 195.021-13.414 263.834-35.174-0.102 0.051-0.205 0.051-0.307 0.102l-228.096 312.064z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["filter"],"grid":0},"attrs":[{}],"properties":{"order":18,"id":24,"name":"filter","prevSize":32,"code":59672},"setIdx":2,"setId":8,"iconIdx":24},{"icon":{"paths":["M512 0c-282.88 0-512 229.248-512 512 0 226.24 146.688 418.112 350.080 485.76 25.6 4.8 35.008-11.008 35.008-24.64 0-12.16-0.448-44.352-0.64-87.040-142.464 30.912-172.48-68.672-172.48-68.672-23.296-59.136-56.96-74.88-56.96-74.88-46.4-31.744 3.584-31.104 3.584-31.104 51.392 3.584 78.4 52.736 78.4 52.736 45.696 78.272 119.872 55.68 149.12 42.56 4.608-33.088 17.792-55.68 32.448-68.48-113.728-12.8-233.216-56.832-233.216-252.992 0-55.872 19.84-101.568 52.672-137.408-5.76-12.928-23.040-64.96 4.48-135.488 0 0 42.88-13.76 140.8 52.48 40.96-11.392 84.48-17.024 128-17.28 43.52 0.256 87.040 5.888 128 17.28 97.28-66.24 140.16-52.48 140.16-52.48 27.52 70.528 10.24 122.56 5.12 135.488 32.64 35.84 52.48 81.536 52.48 137.408 0 196.672-119.68 240-233.6 252.608 17.92 15.36 34.56 46.72 34.56 94.72 0 68.48-0.64 123.52-0.64 140.16 0 13.44 8.96 29.44 35.2 24.32 204.864-67.136 351.424-259.136 351.424-485.056 0-282.752-229.248-512-512-512z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["brand","github"],"grid":0},"attrs":[{}],"properties":{"order":77,"id":25,"name":"github","prevSize":32,"code":59713},"setIdx":2,"setId":8,"iconIdx":25},{"icon":{"paths":["M512 512h-204.8v51.2h204.8v-51.2zM768 153.6h-51.2c0-28.314-22.886-51.2-51.2-51.2h-307.2c-28.314 0-51.2 22.886-51.2 51.2h-51.2c-28.314 0-51.2 22.886-51.2 51.2v665.6c0 28.314 22.886 51.2 51.2 51.2h512c28.314 0 51.2-22.886 51.2-51.2v-665.6c0-28.314-22.886-51.2-51.2-51.2zM358.4 153.6h307.2v51.2h-307.2v-51.2zM768 819.2c0 28.314-22.886 51.2-51.2 51.2h-409.6c-28.314 0-51.2-22.886-51.2-51.2v-563.2c0-28.314 22.886-51.2 51.2-51.2 0 28.314 22.886 51.2 51.2 51.2h307.2c28.314 0 51.2-22.886 51.2-51.2 28.314 0 51.2 22.886 51.2 51.2v563.2zM307.2 460.8h409.6v-51.2h-409.6v51.2zM307.2 665.6h409.6v-51.2h-409.6v51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["help"],"grid":0},"attrs":[{}],"properties":{"order":19,"id":26,"name":"help","prevSize":32,"code":59673},"setIdx":2,"setId":8,"iconIdx":26},{"icon":{"paths":["M512 0c-169.421 0-307.2 137.779-307.2 307.2 0 78.643 15.258 164.915 45.261 256.41 23.859 72.55 56.986 148.582 98.56 226.099 70.707 131.635 140.339 220.774 143.309 224.512 4.813 6.195 12.288 9.779 20.070 9.779 7.834 0 15.258-3.584 20.122-9.779 2.97-3.686 72.602-92.826 143.309-224.512 41.574-77.517 74.701-153.549 98.56-226.099 29.952-91.494 45.21-177.766 45.21-256.41 0-169.421-137.83-307.2-307.2-307.2zM630.682 764.672c-46.234 86.374-92.979 154.982-118.682 190.822-25.6-35.635-72.038-103.885-118.221-189.952-62.874-117.146-137.779-291.738-137.779-458.342 0-141.158 114.842-256 256-256s256 114.842 256 256c0 166.298-74.65 340.582-137.318 457.472zM512 153.6c-84.685 0-153.6 68.915-153.6 153.6s68.915 153.6 153.6 153.6 153.6-68.915 153.6-153.6-68.915-153.6-153.6-153.6zM512 409.6c-56.525 0-102.4-45.875-102.4-102.4 0-56.474 45.875-102.4 102.4-102.4 56.474 0 102.4 45.926 102.4 102.4 0 56.525-45.926 102.4-102.4 102.4z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["location"],"grid":0},"attrs":[{}],"properties":{"order":25,"id":27,"name":"location, control-Map, type-Geolocation","prevSize":32,"code":59675},"setIdx":2,"setId":8,"iconIdx":27},{"icon":{"paths":["M512.273 83.782c-0.141 0.056-182.959 84.073-229.418 256.782-4.481 16.584 32.696 9.296 31.036 27.527-2.034 22.136-44.668 31.201-39.109 94.764 5.659 64.734 60.321 130.141 68.527 169.673v27.655c-0.497 8.54-4.566 31.715-18.018 43.036-7.378 6.19-17.322 8.421-30.436 6.782-18.205-2.275-25.449-14.468-28.345-24.309-4.753-16.218-0.322-35.123 10.345-44 10.724-8.924 12.17-24.842 3.236-35.564-8.934-10.712-24.858-12.161-35.582-3.218-25.995 21.64-36.887 61.52-26.491 97 9.815 33.392 36.197 55.884 70.6 60.182 4.903 0.609 9.566 0.909 14 0.909 26.623 0 44.661-10.175 55.582-19.455 32.866-27.97 35.449-74.593 35.636-79.818 0.009-0.309 0.018-0.618 0.018-0.927v-21.218h0.109v-1.418c0-12.351 10.008-22.364 22.382-22.364 11.944 0 21.609 9.346 22.273 21.109v202.491c-0.206 2.912-2.536 29.892-17.891 42.945-7.368 6.274-17.384 8.53-30.545 6.873-18.214-2.275-25.476-14.468-28.364-24.291-4.762-16.228-0.322-35.151 10.345-44.018 10.724-8.933 12.188-24.833 3.255-35.564-8.924-10.694-24.876-12.161-35.6-3.218-26.013 21.631-36.887 61.52-26.491 97 9.796 33.392 36.197 55.893 70.6 60.2 4.903 0.609 9.566 0.891 14 0.891 26.623 0 44.671-10.156 55.564-19.436 32.875-27.97 35.458-74.611 35.636-79.836 0.019-0.328 0.018-0.609 0.018-0.909v-225.636l0.127-0.055v-1c0-12.595 10.219-22.8 22.836-22.8 12.349 0 22.333 9.824 22.727 22.073v227.418c0 0.309-0 0.591 0.018 0.909 0.187 5.216 2.779 51.866 35.655 79.836 10.912 9.28 28.959 19.436 55.582 19.436 4.443 0 9.088-0.282 13.982-0.891 34.394-4.307 60.804-26.818 70.6-60.2 10.405-35.48-0.487-75.36-26.491-97-10.743-8.943-26.676-7.466-35.6 3.218-8.934 10.74-7.488 26.63 3.236 35.564 10.668 8.868 15.135 27.79 10.364 44.018-2.878 9.823-10.159 22.015-28.364 24.291-13.105 1.648-23.050-0.592-30.418-6.782-13.508-11.358-17.558-34.657-18.036-43v-201.818c0.297-12.093 10.14-21.818 22.327-21.818 12.374 0 22.4 10.003 22.4 22.364v1.418h0.073v21.218c0 0.318-0 0.628 0.018 0.927 0.178 5.216 2.779 51.848 35.655 79.818 10.912 9.28 28.941 19.455 55.564 19.455 4.434 0 9.107-0.292 14-0.891 34.394-4.298 60.786-26.818 70.582-60.2 10.405-35.48-0.487-75.351-26.491-97-10.743-8.933-26.667-7.476-35.582 3.236-8.943 10.722-7.488 26.622 3.236 35.545 10.668 8.877 15.117 27.8 10.345 44.018-2.878 9.842-10.159 22.025-28.364 24.291-13.086 1.648-23.050-0.583-30.418-6.764-13.508-11.368-17.549-34.675-18.018-43v-21.018c5.305-54.103 63.095-107.777 69.091-176.364 5.531-63.563-37.121-72.627-39.145-94.764-1.669-18.232 35.498-10.944 31.036-27.527-46.468-172.709-229.269-256.726-229.4-256.782z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["logo"],"grid":0},"attrs":[{}],"properties":{"order":31,"id":28,"name":"logo","prevSize":32,"code":59676},"setIdx":2,"setId":8,"iconIdx":28},{"icon":{"paths":["M947.2 0h-870.4c-42.342 0-76.8 34.458-76.8 76.8v870.4c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-870.4c0-42.342-34.458-76.8-76.8-76.8zM972.8 947.2c0 14.157-11.443 25.6-25.6 25.6h-870.4c-14.131 0-25.6-11.443-25.6-25.6v-870.4c0-14.131 11.469-25.6 25.6-25.6h870.4c14.157 0 25.6 11.469 25.6 25.6v870.4zM665.6 460.8c56.448 0 102.4-45.926 102.4-102.4s-45.952-102.4-102.4-102.4c-56.448 0-102.4 45.926-102.4 102.4s45.952 102.4 102.4 102.4zM665.6 307.2c28.211 0 51.2 22.989 51.2 51.2s-22.989 51.2-51.2 51.2c-28.211 0-51.2-22.989-51.2-51.2s22.989-51.2 51.2-51.2zM896 102.4h-768c-14.131 0-25.6 11.469-25.6 25.6v614.4c0 14.157 11.469 25.6 25.6 25.6h768c14.157 0 25.6-11.443 25.6-25.6v-614.4c0-14.131-11.443-25.6-25.6-25.6zM153.6 716.8v-118.246l164.301-184.858c4.198-4.787 9.728-7.373 15.462-7.475 5.734-0.051 11.29 2.458 15.642 7.040l283.238 303.539h-478.643zM870.4 716.8h-168.090l-315.853-338.432c-14.285-15.334-33.331-23.603-53.709-23.347-20.326 0.256-39.219 9.011-53.094 24.627l-126.054 141.798v-367.846h716.8v563.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["media"],"grid":0},"attrs":[{}],"properties":{"order":30,"id":29,"name":"media, type-Assets, trigger-AssetChanged","prevSize":32,"code":59677},"setIdx":2,"setId":8,"iconIdx":29},{"icon":{"paths":["M128 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM512 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128zM896 384c-70.656 0-128 57.344-128 128s57.344 128 128 128c70.656 0 128-57.344 128-128s-57.344-128-128-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["more"],"grid":0},"attrs":[{}],"properties":{"order":34,"id":30,"name":"more, dots","prevSize":32,"code":59678},"setIdx":2,"setId":8,"iconIdx":30},{"icon":{"paths":["M877.12 311.104l-66.304 66.368-228.224-228.224 66.368-66.368c25.216-25.152 66.048-25.152 91.264 0l136.896 137.024c25.216 25.216 25.216 65.984 0 91.2zM760.896 427.392l-386.176 386.112c-25.216 25.28-66.048 25.28-91.264 0l-136.96-136.896c-25.216-25.28-25.216-66.112 0-91.264l386.24-386.24 228.16 228.288zM64 896v-191.872l191.936 191.872h-191.936z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["pencil"],"grid":0},"attrs":[{}],"properties":{"order":47,"id":31,"name":"pencil","prevSize":32,"code":59679},"setIdx":2,"setId":8,"iconIdx":31},{"icon":{"paths":["M892.083 131.917c-73.523-73.498-193.152-73.498-266.65 0l-157.184 157.107c-9.958 10.035-9.958 26.214 0 36.275 10.061 9.984 26.24 9.984 36.25 0l157.133-157.107c53.504-53.555 140.672-53.555 194.176 0 53.581 53.504 53.581 140.672 0 194.176l-186.138 186.163c-53.53 53.581-140.672 53.581-194.176 0-10.086-10.010-26.24-10.010-36.275 0-10.035 10.086-10.035 26.189 0 36.25 36.787 36.736 84.992 55.117 133.325 55.117s96.589-18.432 133.376-55.117l186.163-186.214c73.498-73.472 73.498-193.152 0-266.65zM519.45 698.726l-157.082 157.082c-53.504 53.555-140.672 53.555-194.176 0-53.581-53.504-53.581-140.672 0-194.176l186.138-186.163c53.53-53.581 140.672-53.581 194.176 0 10.086 9.984 26.189 9.984 36.275 0 10.035-10.086 10.035-26.214 0-36.25-73.549-73.498-193.203-73.498-266.701 0l-186.163 186.163c-73.498 73.574-73.498 193.203 0 266.701 36.787 36.71 85.043 55.117 133.325 55.117 48.333 0 96.538-18.406 133.325-55.117l157.133-157.133c10.010-10.010 10.010-26.189 0-36.224-10.010-9.984-26.189-9.984-36.25 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["reference"],"grid":0},"attrs":[{}],"properties":{"order":45,"id":32,"name":"reference","prevSize":32,"code":59680},"setIdx":2,"setId":8,"iconIdx":32},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-300.8c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v300.8c0 124.8-99.2 224-224 224zM224 339.2c-89.6 0-160 70.4-160 160v300.8c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-300.8c0-89.6-70.4-160-160-160h-576z","M828.8 201.6h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M716.8 64h-409.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h412.8c19.2 0 32 12.8 32 32s-16 32-35.2 32z","M800 416v64c0 48-38.4 83.2-83.2 83.2h-409.6c-44.8 3.2-83.2-35.2-83.2-83.2v-64h-54.4v64c0 76.8 64 140.8 140.8 140.8h406.4c76.8 0 140.8-64 140.8-140.8v-64h-57.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["schemas"],"grid":0},"attrs":[{},{},{},{}],"properties":{"order":46,"id":33,"name":"schemas","prevSize":32,"code":59681},"setIdx":2,"setId":8,"iconIdx":33},{"icon":{"paths":["M939.776 1003.776c-27.2 27.008-71.232 27.008-98.368 0l-168.96-168.96c-66.176 38.464-142.016 62.080-224 62.080-247.744 0-448.448-200.832-448.448-448.448 0-247.744 200.704-448.448 448.448-448.448 247.68 0 448.512 200.704 448.512 448.448 0 115.136-44.672 218.944-115.904 298.304l158.656 158.656c27.008 27.136 27.008 71.168 0.064 98.368zM448.448 128.128c-176.896 0-320.32 143.36-320.32 320.32s143.424 320.32 320.32 320.32c176.96 0 320.384-143.36 320.384-320.32s-143.488-320.32-320.384-320.32z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["search"],"grid":0},"attrs":[{}],"properties":{"order":23,"id":34,"name":"search","prevSize":32,"code":59682},"setIdx":2,"setId":8,"iconIdx":34},{"icon":{"paths":["M1019.11 440.755c-1.946-13.747-14.438-23.398-28.16-21.888-16.947 1.843-34.253-0.589-50.048-7.091-52.25-21.504-77.261-81.459-55.757-133.709 6.605-15.846 16.947-29.85 30.208-40.602 10.803-8.653 12.698-24.294 4.352-35.354-28.902-37.99-62.797-71.706-100.838-100.045-10.701-8.090-25.805-6.451-34.662 3.661-28.8 33.254-75.546 44.262-116.198 27.546-40.704-16.742-66.099-57.498-63.206-101.453 0.845-13.338-8.755-25.19-21.99-27.008-47.002-6.605-94.797-6.605-142.054 0.077-13.722 1.946-23.398 14.387-21.862 28.211 1.843 16.896-0.614 34.202-7.168 49.997-21.504 52.25-81.408 77.21-133.632 55.706-15.821-6.502-29.85-16.947-40.602-30.157-8.653-10.752-24.32-12.698-35.379-4.301-37.99 28.851-71.68 62.694-100.045 100.762-8.090 10.701-6.451 25.83 3.635 34.637 33.28 28.902 44.288 75.597 27.546 116.301-16.742 40.653-57.498 66.048-101.427 63.155-13.363-0.845-25.19 8.755-26.982 21.99-6.63 47.002-6.63 94.822 0.102 142.080 1.946 13.696 14.387 23.322 28.16 21.811 16.896-1.818 34.202 0.691 50.022 7.168 52.224 21.53 77.21 81.459 55.706 133.734-6.502 15.795-16.947 29.773-30.157 40.525-10.803 8.73-12.698 24.346-4.352 35.354 28.877 38.042 62.822 71.731 100.813 100.122 1.741 1.357 3.661 2.355 5.606 3.2 9.933 4.045 21.709 1.536 29.082-6.938 28.826-33.178 75.571-44.262 116.275-27.52 40.653 16.742 66.048 57.498 63.13 101.453-0.819 13.338 8.755 25.165 22.067 27.059 47.002 6.579 94.72 6.554 142.029-0.102 13.645-1.971 23.347-14.464 21.811-28.237-1.843-16.947 0.691-34.253 7.194-50.048 21.504-52.25 81.459-77.21 133.658-55.68 15.795 6.528 29.85 16.947 40.55 30.157 8.704 10.803 24.346 12.698 35.405 4.326 37.99-28.902 71.654-62.746 100.096-100.813 7.987-10.675 6.4-25.805-3.712-34.662-33.254-28.826-44.288-75.571-27.546-116.224 16.742-40.73 57.498-66.099 101.453-63.232 13.338 0.922 25.139-8.678 27.008-21.965 6.554-47.002 6.502-94.771-0.128-142.003zM971.059 554.010c-56.141 5.274-105.702 41.114-127.642 94.464s-12.058 113.613 24.090 156.902c-17.69 21.478-37.453 41.318-58.854 59.315-12.749-11.213-27.392-20.352-43.238-26.854-78.259-32.282-168.243 5.197-200.499 83.584-6.502 15.718-10.291 32.563-11.29 49.536-27.853 2.56-55.859 2.637-83.61 0.077-5.274-56.090-41.114-105.677-94.464-127.616-53.35-21.99-113.613-11.981-156.928 24.064-21.504-17.69-41.318-37.453-59.29-58.88 11.213-12.723 20.352-27.392 26.906-43.136 32.205-78.387-5.274-168.294-83.584-200.55-15.821-6.502-32.589-10.342-49.613-11.366-2.534-27.853-2.586-55.859 0-83.558 56.090-5.299 105.626-41.088 127.565-94.438 21.965-53.402 12.058-113.638-24.090-156.902 17.69-21.555 37.478-41.395 58.88-59.341 12.749 11.213 27.392 20.352 43.213 26.854 78.285 32.256 168.218-5.248 200.474-83.558 6.528-15.795 10.342-32.589 11.366-49.613 27.853-2.509 55.808-2.56 83.558 0 5.299 56.090 41.139 105.6 94.49 127.59 53.35 21.939 113.638 12.006 156.902-24.090 21.504 17.741 41.293 37.453 59.29 58.854-11.213 12.8-20.352 27.392-26.854 43.213-32.256 78.31 5.248 168.294 83.507 200.499 15.846 6.502 32.691 10.342 49.638 11.392 2.56 27.853 2.611 55.808 0.077 83.558zM512 307.2c-113.101 0-204.8 91.699-204.8 204.8 0 113.126 91.699 204.826 204.8 204.826s204.8-91.699 204.8-204.826c0-113.101-91.699-204.8-204.8-204.8zM512 665.626c-84.813 0-153.6-68.813-153.6-153.626 0-84.838 68.787-153.6 153.6-153.6 84.838 0 153.6 68.762 153.6 153.6 0 84.813-68.762 153.626-153.6 153.626z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["settings"],"grid":0},"attrs":[{}],"properties":{"order":22,"id":35,"name":"settings","prevSize":32,"code":59683},"setIdx":2,"setId":8,"iconIdx":35},{"icon":{"paths":["M77.005 102.605h128v332.8c0 14.131 11.418 25.6 25.6 25.6 14.106 0 25.6-11.469 25.6-25.6v-332.8h128c14.106 0 25.6-11.469 25.6-25.6 0-14.157-11.494-25.6-25.6-25.6h-307.2c-14.182 0-25.6 11.443-25.6 25.6 0 14.106 11.418 25.6 25.6 25.6zM947.405 716.979h-179.2v-102.4h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-204.8c-14.182 0-25.6 11.443-25.6 25.6v358.4c0 14.157 11.418 25.6 25.6 25.6 14.157 0 25.6-11.443 25.6-25.6v-179.2h179.2c14.157 0 25.6-11.443 25.6-25.6s-11.494-25.6-25.6-25.6zM965.094 58.47c-9.958-9.933-26.112-9.933-36.045 0l-870.605 870.579c-9.958 9.984-9.958 26.086 0 36.045 10.010 9.984 26.112 9.984 36.045 0l870.605-870.579c9.958-9.933 9.958-26.086 0-36.045z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-boolean"],"grid":0},"attrs":[{}],"properties":{"order":21,"id":36,"name":"type-Boolean","prevSize":32,"code":59684},"setIdx":2,"setId":8,"iconIdx":36},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-datetime"],"grid":0},"attrs":[{}],"properties":{"order":24,"id":37,"name":"type-DateTime","prevSize":32,"code":59685},"setIdx":2,"setId":8,"iconIdx":37},{"icon":{"paths":["M179.2 256c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6h-25.6c-56.55 0-102.4 45.85-102.4 102.4v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 56.55 45.85 102.4 102.4 102.4h25.6c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-30.746-13.85-58.061-35.328-76.8 21.478-18.765 35.328-46.029 35.328-76.8v-179.2zM972.8 486.4h-25.6c-28.262 0-51.2-22.938-51.2-51.2v-179.2c0-56.55-45.85-102.4-102.4-102.4h-25.6c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6h25.6c28.262 0 51.2 22.938 51.2 51.2v179.2c0 30.771 13.85 58.035 35.328 76.8-21.478 18.739-35.328 46.054-35.328 76.8v179.2c0 28.262-22.938 51.2-51.2 51.2h-25.6c-14.157 0-25.6 11.443-25.6 25.6s11.443 25.6 25.6 25.6h25.6c56.55 0 102.4-45.85 102.4-102.4v-179.2c0-28.262 22.938-51.2 51.2-51.2h25.6c14.157 0 25.6-11.443 25.6-25.6 0-14.131-11.443-25.6-25.6-25.6zM512 332.8c-14.157 0-25.6 11.469-25.6 25.6 0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6c0-14.131-11.443-25.6-25.6-25.6zM512 435.2c-14.157 0-25.6 11.469-25.6 25.6v204.8c0 14.157 11.443 25.6 25.6 25.6s25.6-11.443 25.6-25.6v-204.8c0-14.131-11.443-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["json"],"grid":0},"attrs":[{}],"properties":{"order":20,"id":38,"name":"type-Json, json","prevSize":32,"code":59674},"setIdx":2,"setId":8,"iconIdx":38},{"icon":{"paths":["M256 665.6h-76.8v-332.8c0-14.131-11.469-25.6-25.6-25.6h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h51.2v307.2h-76.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6zM614.4 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6v179.2c0 14.131 11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-179.2v-128h179.2c14.131 0 25.6-11.469 25.6-25.6v-179.2c0-14.131-11.469-25.6-25.6-25.6zM972.8 307.2h-204.8c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h179.2v128h-179.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6h204.8c14.131 0 25.6-11.469 25.6-25.6v-358.4c0-14.131-11.469-25.6-25.6-25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-number"],"grid":0},"attrs":[{}],"properties":{"order":32,"id":39,"name":"type-Number","prevSize":32,"code":59686},"setIdx":2,"setId":8,"iconIdx":39},{"icon":{"paths":["M870.4 921.6h-716.8c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h716.8c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM194.688 817.152c13.030 5.555 28.083-0.461 33.613-13.44l125.030-291.712h317.338l125.005 291.712c4.173 9.677 13.568 15.488 23.526 15.488 3.405 0 6.81-0.64 10.112-2.048 13.005-5.606 18.995-20.659 13.44-33.638l-131.61-306.944c-0.051-0.051-0.051-0.154-0.102-0.205l-175.488-409.6c-4.045-9.472-13.312-15.565-23.552-15.565s-19.507 6.093-23.552 15.514l-175.488 409.6c-0.051 0.051-0.051 0.154-0.102 0.205l-131.61 306.97c-5.53 13.005 0.461 28.058 13.44 33.664zM512 141.773l136.704 319.027h-273.408l136.704-319.027z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-string"],"grid":0},"attrs":[{}],"properties":{"order":48,"id":40,"name":"type-String","prevSize":32,"code":59687},"setIdx":2,"setId":8,"iconIdx":40},{"icon":{"paths":["M955.221 848c0-0.109 10.752 0 0 0-52.751-161.392-240.461-224-443.178-224-202.269 0-389.979 63.392-443.066 224-11.2-0.109 0-1.232 0 0 0 61.936 49.615 112 110.654 112h664.823c61.151 0 110.766-50.064 110.766-112zM290.399 288c0 123.648 99.231 336 221.645 336s221.645-212.352 221.645-336c0-123.648-99.231-224-221.645-224s-221.645 100.352-221.645 224z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user"],"grid":0},"attrs":[{}],"properties":{"order":33,"id":41,"name":"user","prevSize":32,"code":59688},"setIdx":2,"setId":8,"iconIdx":41},{"icon":{"paths":["M469.333 614.997v281.003c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-281.003l97.835 97.835c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331l-170.667-170.667c-0.085-0.085-0.171-0.171-0.256-0.256-4.053-3.968-8.661-6.955-13.568-9.003-5.12-2.133-10.624-3.2-16.085-3.243-0.171 0-0.341 0-0.469 0-5.461 0.043-10.965 1.109-16.085 3.243-4.949 2.048-9.557 5.035-13.568 9.003-0.085 0.085-0.171 0.171-0.256 0.256l-170.667 170.667c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0zM890.411 822.101c30.379-16.555 56.149-38.443 76.672-63.915 21.333-26.411 36.949-56.619 46.379-88.576s12.629-65.835 9.003-99.584c-3.456-32.512-13.269-64.896-29.824-95.232-14.208-26.069-32.384-48.768-53.376-67.669-21.717-19.541-46.421-34.944-72.875-45.952-30.891-12.8-64.171-19.584-98.048-19.84h-22.528c-13.312-37.717-32.085-72.235-55.168-102.912-30.635-40.661-68.821-74.453-111.915-99.84s-91.179-42.411-141.568-49.536c-48.597-6.784-99.243-4.395-149.504 8.619s-95.744 35.413-134.912 64.939c-40.661 30.635-74.453 68.821-99.84 111.915s-42.411 91.179-49.493 141.568c-6.827 48.555-4.395 99.2 8.576 149.461 15.872 61.312 45.781 115.627 84.267 158.421 15.744 17.536 42.752 18.944 60.245 3.2s18.944-42.752 3.2-60.245c-29.355-32.64-52.693-74.667-65.109-122.752-10.155-39.253-11.989-78.592-6.699-116.224 5.504-39.125 18.773-76.501 38.571-110.123s46.080-63.317 77.653-87.083c30.379-22.869 65.664-40.32 104.917-50.475s78.592-11.989 116.224-6.699c39.125 5.504 76.544 18.731 110.123 38.528s63.317 46.080 87.083 77.653c22.869 30.379 40.32 65.664 50.475 104.917 4.907 18.56 21.547 32 41.301 32h53.461c22.869 0.171 45.269 4.736 65.92 13.312 17.707 7.339 34.133 17.621 48.512 30.592 13.909 12.501 25.984 27.605 35.541 45.099 11.093 20.352 17.579 41.899 19.883 63.488 2.389 22.443 0.256 45.013-6.016 66.432s-16.725 41.515-30.933 59.093c-13.611 16.896-30.763 31.445-51.115 42.581-20.693 11.264-28.331 37.205-17.024 57.899s37.205 28.331 57.899 17.024z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload-cloud"],"grid":0},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":32,"code":59763,"name":"upload-3"},"setIdx":8,"setId":2,"iconIdx":0},{"icon":{"paths":["M853.333 640v170.667c0 5.845-1.152 11.349-3.2 16.299-2.133 5.205-5.333 9.899-9.301 13.867s-8.661 7.125-13.867 9.301c-4.949 2.048-10.453 3.2-16.299 3.2h-597.333c-5.845 0-11.349-1.152-16.299-3.2-5.205-2.133-9.899-5.333-13.867-9.301s-7.125-8.661-9.301-13.867c-2.048-4.949-3.2-10.453-3.2-16.299v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v170.667c0 17.28 3.456 33.835 9.728 48.981 6.485 15.701 16 29.781 27.776 41.557s25.856 21.291 41.557 27.776c15.104 6.229 31.659 9.685 48.939 9.685h597.333c17.28 0 33.835-3.456 48.981-9.728 15.701-6.485 29.781-16 41.557-27.776s21.291-25.856 27.776-41.557c6.229-15.104 9.685-31.659 9.685-48.939v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667zM469.333 230.997v409.003c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-409.003l140.501 140.501c16.683 16.683 43.691 16.683 60.331 0s16.683-43.691 0-60.331l-213.333-213.333c-0.043-0.043-0.128-0.085-0.171-0.171-4.053-4.011-8.704-7.040-13.653-9.088-10.453-4.309-22.229-4.309-32.683 0-4.949 2.048-9.6 5.077-13.653 9.088-0.043 0.043-0.128 0.085-0.171 0.171l-213.333 213.333c-16.683 16.683-16.683 43.691 0 60.331s43.691 16.683 60.331 0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["upload"],"grid":0},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59761,"name":"upload-4"},"setIdx":8,"setId":2,"iconIdx":1},{"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":7,"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"],"width":1344,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["browser","window","software","program"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":1,"prevSize":32,"code":59701,"name":"browser"},"setIdx":3,"setId":7,"iconIdx":1},{"icon":{"paths":["M927.936 272.992l-68.288-68.288c-12.608-12.576-32.96-12.576-45.536 0l-409.44 409.44-194.752-196.16c-12.576-12.576-32.928-12.576-45.536 0l-68.288 68.288c-12.576 12.608-12.576 32.96 0 45.536l285.568 287.488c12.576 12.576 32.96 12.576 45.536 0l500.736-500.768c12.576-12.544 12.576-32.96 0-45.536z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["checkmark","tick","approve","submit"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":2,"prevSize":32,"code":59714,"name":"checkmark"},"setIdx":3,"setId":7,"iconIdx":2},{"icon":{"paths":["M1020.192 401.824c-8.864-25.568-31.616-44.288-59.008-48.352l-266.432-39.616-115.808-240.448c-12.192-25.248-38.272-41.408-66.944-41.408s-54.752 16.16-66.944 41.408l-115.808 240.448-266.464 39.616c-27.36 4.064-50.112 22.784-58.944 48.352-8.8 25.632-2.144 53.856 17.184 73.12l195.264 194.944-45.28 270.432c-4.608 27.232 7.2 54.56 30.336 70.496 12.704 8.736 27.648 13.184 42.592 13.184 12.288 0 24.608-3.008 35.776-8.992l232.288-125.056 232.32 125.056c11.168 5.984 23.488 8.992 35.744 8.992 14.944 0 29.888-4.448 42.624-13.184 23.136-15.936 34.88-43.264 30.304-70.496l-45.312-270.432 195.328-194.944c19.296-19.296 25.92-47.52 17.184-73.12zM754.816 619.616c-16.384 16.32-23.808 39.328-20.064 61.888l45.312 270.432-232.32-124.992c-11.136-6.016-23.424-8.992-35.776-8.992-12.288 0-24.608 3.008-35.744 8.992l-232.32 124.992 45.312-270.432c3.776-22.56-3.648-45.568-20.032-61.888l-195.264-194.944 266.432-39.68c24.352-3.616 45.312-18.848 55.776-40.576l115.872-240.384 115.84 240.416c10.496 21.728 31.424 36.928 55.744 40.576l266.496 39.68-195.264 194.912z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["star","favorite"],"grid":32},"attrs":[{}],"properties":{"order":1,"id":3,"prevSize":32,"code":59706,"name":"control-Stars"},"setIdx":3,"setId":7,"iconIdx":3},{"icon":{"paths":["M409.6 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 204.8h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM409.6 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2zM768 563.2h-153.6c-28.314 0-51.2 22.886-51.2 51.2v153.6c0 28.262 22.886 51.2 51.2 51.2h153.6c28.314 0 51.2-22.938 51.2-51.2v-153.6c0-28.262-22.886-51.2-51.2-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["grid"],"grid":20},"attrs":[{}],"properties":{"order":1,"id":0,"prevSize":20,"code":59730,"name":"grid1"},"setIdx":5,"setId":5,"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":1,"name":"list","prevSize":20,"code":59726},"setIdx":5,"setId":5,"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":2,"prevSize":20,"code":59708,"name":"info"},"setIdx":5,"setId":5,"iconIdx":2},{"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":7,"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"],"width":1140,"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Tags"],"grid":14},"attrs":[{},{},{}],"properties":{"order":119,"id":1,"name":"control-Tags","prevSize":28,"code":59747},"setIdx":7,"setId":3,"iconIdx":1},{"icon":{"paths":["M384 179.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6zM998.4 486.4h-614.4c-14.131 0-25.6 11.443-25.6 25.6s11.469 25.6 25.6 25.6h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6zM998.4 844.8h-614.4c-38.406 15.539-22.811 37.543 0 51.2h614.4c14.157 0 25.6-11.443 25.6-25.6s-11.443-25.6-25.6-25.6z","M0 0v307.2h307.2v-307.2zM47.4 47.4h212.4v212.4h-212.4z","M0 716.8v307.2h307.2v-307.2zM47.4 764.2h212.4v212.4h-212.4z","M0 358.4v307.2h307.2v-307.2zM47.4 405.8h212.4v212.4h-212.4z","M89.6 89.6h128v128h-128v-128z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Checkboxes"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":118,"id":2,"name":"control-Checkboxes","prevSize":28,"code":59746},"setIdx":7,"setId":3,"iconIdx":2},{"icon":{"paths":["M159.073 665.6l-159.073-134.055 159.073-133.819 36.818 37.29-117.062 96.057 117.062 97.237z","M493.247 536.029q0 33.042-9.441 57.115-9.205 24.073-25.961 40.122-16.521 15.813-39.178 23.601-22.657 7.552-49.327 7.552-26.197 0-48.855-4.012-22.421-3.776-42.954-10.385v-323.338h57.587v78.356l-2.36 47.203q12.981-16.757 30.21-26.905 17.465-10.149 41.774-10.149 21.241 0 37.762 8.496t27.614 24.309q11.329 15.577 17.229 37.998 5.9 22.185 5.9 50.035zM432.828 538.389q0-19.825-2.832-33.75t-8.26-22.893q-5.192-8.969-12.981-12.981-7.552-4.248-17.465-4.248-14.633 0-28.086 11.801-13.217 11.801-28.086 32.098v104.79q6.844 2.596 16.757 4.248 10.149 1.652 20.533 1.652 13.689 0 24.781-5.664 11.329-5.664 19.117-16.049 8.024-10.385 12.273-25.253 4.248-15.105 4.248-33.75z","M700.682 513.608q0.472-13.453-1.416-22.893-1.652-9.441-5.664-15.577-3.776-6.136-9.441-8.968t-12.981-2.832q-12.745 0-26.433 10.621-13.453 10.385-29.738 34.458v151.756h-59.003v-239.789h52.159l2.124 34.93q5.9-9.205 13.217-16.521 7.552-7.316 16.521-12.509 9.205-5.428 20.297-8.26t24.309-2.832q18.173 0 32.098 6.372 14.161 6.136 23.601 18.409 9.677 12.273 14.161 30.918 4.72 18.409 4.012 42.718z","M864.927 397.725l159.073 133.819-159.073 134.055-36.582-37.29 116.826-96.293-116.826-97.001z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Html"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":116,"id":3,"name":"control-Html","prevSize":28,"code":59744},"setIdx":7,"setId":3,"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"],"width":1029,"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["single-content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":112,"id":4,"name":"single-content","prevSize":28,"code":59736},"setIdx":7,"setId":3,"iconIdx":4},{"icon":{"paths":["M777.143 946.286h-525.714c-89.143 0-160-70.857-160-160v-297.143c0-89.143 70.857-160 160-160h525.714c89.143 0 160 70.857 160 160v297.143c0 89.143-70.857 160-160 160zM251.429 374.857c-64 0-114.286 50.286-114.286 114.286v297.143c0 64 50.286 114.286 114.286 114.286h525.714c64 0 114.286-50.286 114.286-114.286v-297.143c0-64-50.286-114.286-114.286-114.286h-525.714z","M731.429 580.571h-457.143c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h457.143c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M502.857 740.571h-228.571c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h228.571c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M777.143 260.571h-525.714c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h525.714c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z","M685.714 146.286h-342.857c-13.714 0-22.857-9.143-22.857-22.857s9.143-22.857 22.857-22.857h342.857c13.714 0 22.857 9.143 22.857 22.857s-9.143 22.857-22.857 22.857z"],"width":1029,"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["multiple-content"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":113,"id":5,"name":"multiple-content","prevSize":28,"code":59735},"setIdx":7,"setId":3,"iconIdx":5},{"icon":{"paths":["M832 268.8h-657.92c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h657.92c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 453.12h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 642.56h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z","M832 832h-409.6c-15.36 0-25.6-10.24-25.6-25.6s10.24-25.6 25.6-25.6h409.6c15.36 0 25.6 10.24 25.6 25.6s-10.24 25.6-25.6 25.6z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["type-Array"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":108,"id":6,"name":"type-Array","prevSize":28,"code":59734},"setIdx":7,"setId":3,"iconIdx":6},{"icon":{"paths":["M292.571 713.143v128c0 20-16.571 36.571-36.571 36.571h-146.286c-20 0-36.571-16.571-36.571-36.571v-128c0-20 16.571-36.571 36.571-36.571h146.286c20 0 36.571 16.571 36.571 36.571zM309.714 109.714l-16 438.857c-0.571 20-17.714 36.571-37.714 36.571h-146.286c-20 0-37.143-16.571-37.714-36.571l-16-438.857c-0.571-20 15.429-36.571 35.429-36.571h182.857c20 0 36 16.571 35.429 36.571z"],"width":366,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["exclamation"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":7,"prevSize":28,"code":59733,"name":"exclamation"},"setIdx":7,"setId":3,"iconIdx":7},{"icon":{"paths":["M512 26.38l-424.96 242.8v485.64l424.96 242.8 424.96-242.8v-485.64l-424.96-242.8zM512 235.52l245.76 138.24v276.48l-245.76 138.24-245.76-138.24v-276.48l245.76-138.24z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["orleans"],"grid":14},"attrs":[{}],"properties":{"order":99,"id":8,"name":"orleans","prevSize":28,"code":59723},"setIdx":7,"setId":3,"iconIdx":8},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v204.8h51.2v-204.8h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-307.2v51.2h307.2c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4z","M153.6 640v281.6h358.4v-281.6zM179.2 640v-76.8c0-84.48 69.12-153.6 153.6-153.6s153.6 69.12 153.6 153.6v76.8h-51.2v-76.8c0-56.32-46.080-102.4-102.4-102.4s-102.4 46.080-102.4 102.4v76.8z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-lock"],"grid":14},"attrs":[{},{}],"properties":{"order":97,"id":9,"name":"document-lock","prevSize":28,"code":59721},"setIdx":7,"setId":3,"iconIdx":9},{"icon":{"paths":["M358.4 102.4c-28.314 0-51.2 22.886-51.2 51.2v153.6h51.2v-153.6h307.2v153.6c0 28.314 22.886 51.2 51.2 51.2h153.6v512h-358.4v51.2h358.4c28.314 0 51.2-22.886 51.2-51.2v-548.2l-219.8-219.8h-292.2zM716.8 189.8l117.4 117.4h-117.4zM332.8 460.8l-230.4 256v51.2h102.4v153.6h256v-153.6h102.4v-51.2zM332.8 537.3l161.5 179.5h-84.7v153.6h-153.6v-153.6h-84.7z","M102.4 357.532h460.8v52.068h-460.8v-52.068z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["document-unpublish"],"grid":14},"attrs":[{},{}],"properties":{"order":96,"id":10,"name":"document-unpublish","prevSize":28,"code":59711},"setIdx":7,"setId":3,"iconIdx":10},{"icon":{"paths":["M614.286 420.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8-5.714 13.143-5.714 4.571 0 9.714 2.286 13.143 5.714l224.571 224.571 224.571-224.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-down"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":11,"prevSize":28,"code":59648,"name":"angle-down"},"setIdx":7,"setId":3,"iconIdx":11},{"icon":{"paths":["M358.286 310.857c0 4.571-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8 5.714 13.143z"],"width":384,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":12,"prevSize":28,"code":59649,"name":"angle-left"},"setIdx":7,"setId":3,"iconIdx":12},{"icon":{"paths":["M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8-5.714-13.143 0-4.571 2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":347,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-right"],"grid":14},"attrs":[{}],"properties":{"order":67,"id":13,"prevSize":28,"code":59697,"name":"angle-right"},"setIdx":7,"setId":3,"iconIdx":13},{"icon":{"paths":["M614.286 676.571c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8 5.714-13.143 5.714-4.571 0-9.714-2.286-13.143-5.714l-224.571-224.571-224.571 224.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z"],"width":658,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["angle-up"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":14,"prevSize":28,"code":59651,"name":"angle-up"},"setIdx":7,"setId":3,"iconIdx":14},{"icon":{"paths":["M592 393.6h-156.8c-57.6 0-105.6-48-105.6-105.6v-182.4c0-57.6 48-105.6 105.6-105.6h156.8c57.6 0 105.6 48 105.6 105.6v182.4c-3.2 57.6-48 105.6-105.6 105.6zM432 64c-22.4 0-41.6 19.2-41.6 41.6v182.4c0 22.4 19.2 41.6 41.6 41.6h156.8c22.4 0 41.6-19.2 41.6-41.6v-182.4c0-22.4-19.2-41.6-41.6-41.6h-156.8z","M195.2 1024c-105.6 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c3.2 105.6-86.4 195.2-195.2 195.2zM195.2 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 134.4 131.2 134.4 73.6 0 131.2-60.8 131.2-131.2 3.2-73.6-57.6-134.4-131.2-134.4z","M828.8 1024c-108.8 0-195.2-89.6-195.2-195.2 0-108.8 89.6-195.2 195.2-195.2s195.2 89.6 195.2 195.2c0 105.6-89.6 195.2-195.2 195.2zM828.8 694.4c-73.6 0-131.2 60.8-131.2 131.2 0 73.6 60.8 131.2 131.2 131.2 73.6 0 131.2-60.8 131.2-131.2s-60.8-131.2-131.2-131.2z","M332.8 640c-6.4 0-12.8 0-16-3.2-16-9.6-19.2-28.8-9.6-44.8l83.2-137.6c9.6-16 28.8-19.2 44.8-9.6s19.2 28.8 9.6 44.8l-83.2 137.6c-6.4 6.4-16 12.8-28.8 12.8z","M691.2 640c-9.6 0-22.4-6.4-28.8-16l-83.2-137.6c-9.6-16-3.2-35.2 9.6-44.8s35.2-3.2 44.8 9.6l83.2 137.6c9.6 16 3.2 35.2-9.6 44.8-6.4 6.4-12.8 6.4-16 6.4z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["api"],"grid":14},"attrs":[{},{},{},{},{}],"properties":{"order":94,"id":15,"name":"api","prevSize":28,"code":59717},"setIdx":7,"setId":3,"iconIdx":15},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M771.2 860.8h-438.4c-12.8 0-22.4-6.4-28.8-19.2s-3.2-25.6 3.2-35.2l300.8-355.2c6.4-6.4 16-12.8 25.6-12.8s19.2 6.4 25.6 12.8l192 275.2c3.2 3.2 3.2 6.4 3.2 9.6 16 44.8 3.2 73.6-6.4 89.6-22.4 32-70.4 35.2-76.8 35.2zM403.2 796.8h371.2c6.4 0 22.4-3.2 25.6-9.6 3.2-3.2 3.2-12.8 0-25.6l-166.4-236.8-230.4 272z","M332.8 502.4c-76.8 0-140.8-64-140.8-140.8s64-140.8 140.8-140.8 140.8 64 140.8 140.8-60.8 140.8-140.8 140.8zM332.8 284.8c-41.6 0-76.8 32-76.8 76.8s35.2 76.8 76.8 76.8 76.8-35.2 76.8-76.8-32-76.8-76.8-76.8z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["assets"],"grid":14},"attrs":[{},{},{}],"properties":{"order":95,"id":16,"name":"assets","prevSize":28,"code":59720},"setIdx":7,"setId":3,"iconIdx":16},{"icon":{"paths":["M932.571 548.571c0 20-16.571 36.571-36.571 36.571h-128c0 71.429-15.429 125.143-38.286 165.714l118.857 119.429c14.286 14.286 14.286 37.143 0 51.429-6.857 7.429-16.571 10.857-25.714 10.857s-18.857-3.429-25.714-10.857l-113.143-112.571s-74.857 68.571-172 68.571v-512h-73.143v512c-103.429 0-178.857-75.429-178.857-75.429l-104.571 118.286c-7.429 8-17.143 12-27.429 12-8.571 0-17.143-2.857-24.571-9.143-14.857-13.714-16-36.571-2.857-52l115.429-129.714c-20-39.429-33.143-90.286-33.143-156.571h-128c-20 0-36.571-16.571-36.571-36.571s16.571-36.571 36.571-36.571h128v-168l-98.857-98.857c-14.286-14.286-14.286-37.143 0-51.429s37.143-14.286 51.429 0l98.857 98.857h482.286l98.857-98.857c14.286-14.286 37.143-14.286 51.429 0s14.286 37.143 0 51.429l-98.857 98.857v168h128c20 0 36.571 16.571 36.571 36.571zM658.286 219.429h-365.714c0-101.143 81.714-182.857 182.857-182.857s182.857 81.714 182.857 182.857z"],"width":951,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["bug"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":17,"prevSize":28,"code":59709,"name":"bug"},"setIdx":7,"setId":3,"iconIdx":17},{"icon":{"paths":["M585.143 402.286c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857s-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714 0-20 16.571-36.571 36.571-36.571h512c20 0 36.571 16.571 36.571 36.571z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-down"],"grid":14},"attrs":[{}],"properties":{"order":4,"id":18,"prevSize":28,"code":59692,"name":"caret-down"},"setIdx":7,"setId":3,"iconIdx":18},{"icon":{"paths":["M365.714 256v512c0 20-16.571 36.571-36.571 36.571-9.714 0-18.857-4-25.714-10.857l-256-256c-6.857-6.857-10.857-16-10.857-25.714s4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857 20 0 36.571 16.571 36.571 36.571z"],"width":402,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-left"],"grid":14},"attrs":[{}],"properties":{"order":2,"id":19,"prevSize":28,"code":59690,"name":"caret-left"},"setIdx":7,"setId":3,"iconIdx":19},{"icon":{"paths":["M329.143 512c0 9.714-4 18.857-10.857 25.714l-256 256c-6.857 6.857-16 10.857-25.714 10.857-20 0-36.571-16.571-36.571-36.571v-512c0-20 16.571-36.571 36.571-36.571 9.714 0 18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":329,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-right"],"grid":14},"attrs":[{}],"properties":{"order":1,"id":20,"prevSize":28,"code":59689,"name":"caret-right"},"setIdx":7,"setId":3,"iconIdx":20},{"icon":{"paths":["M585.143 694.857c0 20-16.571 36.571-36.571 36.571h-512c-20 0-36.571-16.571-36.571-36.571 0-9.714 4-18.857 10.857-25.714l256-256c6.857-6.857 16-10.857 25.714-10.857s18.857 4 25.714 10.857l256 256c6.857 6.857 10.857 16 10.857 25.714z"],"width":585,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["caret-up"],"grid":14},"attrs":[{}],"properties":{"order":3,"id":21,"prevSize":28,"code":59691,"name":"caret-up"},"setIdx":7,"setId":3,"iconIdx":21},{"icon":{"paths":["M800 1024h-576c-124.8 0-224-99.2-224-224v-576c0-124.8 99.2-224 224-224h576c124.8 0 224 99.2 224 224v576c0 124.8-99.2 224-224 224zM224 64c-89.6 0-160 70.4-160 160v576c0 89.6 70.4 160 160 160h576c89.6 0 160-70.4 160-160v-576c0-89.6-70.4-160-160-160h-576z","M480 448h-211.2c-57.6 0-105.6-48-105.6-105.6v-73.6c0-57.6 48-105.6 105.6-105.6h211.2c57.6 0 105.6 48 105.6 105.6v73.6c0 57.6-48 105.6-105.6 105.6zM268.8 227.2c-22.4 0-41.6 19.2-41.6 41.6v73.6c0 22.4 19.2 41.6 41.6 41.6h211.2c22.4 0 41.6-19.2 41.6-41.6v-73.6c0-22.4-19.2-41.6-41.6-41.6h-211.2z","M828.8 611.2h-633.6c-19.2 0-32-12.8-32-32s12.8-32 32-32h630.4c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z","M553.6 777.6h-358.4c-19.2 0-32-12.8-32-32s12.8-32 32-32h355.2c19.2 0 32 12.8 32 32s-12.8 32-28.8 32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["content"],"grid":14},"attrs":[{},{},{},{}],"properties":{"order":93,"id":22,"name":"contents, trigger-ContentChanged","prevSize":28,"code":59718},"setIdx":7,"setId":3,"iconIdx":22},{"icon":{"paths":["M947.2 102.4h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-512v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v716.8c0 42.342 34.458 76.8 76.8 76.8h870.4c42.342 0 76.8-34.458 76.8-76.8v-716.8c0-42.342-34.458-76.8-76.8-76.8zM972.8 896c0 14.131-11.469 25.6-25.6 25.6h-870.4c-14.080 0-25.6-11.469-25.6-25.6v-537.6h921.6v537.6zM972.8 307.2h-921.6v-128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h512v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128zM332.8 512h51.2c14.080 0 25.6-11.52 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.52-25.6 25.6s11.52 25.6 25.6 25.6zM640 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 512h51.2c14.131 0 25.6-11.52 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.52-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 614.4h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 614.4h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 716.8h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 716.8h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM179.2 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM332.8 819.2h51.2c14.080 0 25.6-11.469 25.6-25.6s-11.52-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM486.4 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.080 0-25.6 11.469-25.6 25.6s11.52 25.6 25.6 25.6zM640 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6zM793.6 819.2h51.2c14.131 0 25.6-11.469 25.6-25.6s-11.469-25.6-25.6-25.6h-51.2c-14.131 0-25.6 11.469-25.6 25.6s11.469 25.6 25.6 25.6z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date"],"grid":14},"attrs":[{}],"properties":{"order":71,"id":23,"name":"control-Date","prevSize":28,"code":59702},"setIdx":7,"setId":3,"iconIdx":23},{"icon":{"paths":["M486.4 409.6h51.2c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6zM230.4 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM230.4 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM51.2 742.4v-435.2h665.6v102.4h51.2v-281.6c0-42.342-34.458-76.8-76.8-76.8h-128v-25.6c0-14.131-11.469-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-256v-25.6c0-14.131-11.52-25.6-25.6-25.6s-25.6 11.469-25.6 25.6v25.6h-128c-42.342 0-76.8 34.458-76.8 76.8v614.4c0 42.342 34.458 76.8 76.8 76.8h332.8v-51.2h-332.8c-14.080 0-25.6-11.469-25.6-25.6zM51.2 128c0-14.080 11.52-25.6 25.6-25.6h128v76.8c0 14.080 11.52 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h256v76.8c0 14.080 11.469 25.6 25.6 25.6s25.6-11.52 25.6-25.6v-76.8h128c14.131 0 25.6 11.52 25.6 25.6v128h-665.6v-128zM384 409.6c14.080 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.52-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM742.4 460.8c-155.546 0-281.6 126.054-281.6 281.6s126.054 281.6 281.6 281.6 281.6-126.054 281.6-281.6-126.054-281.6-281.6-281.6zM742.4 972.8c-127.232 0-230.4-103.168-230.4-230.4s103.168-230.4 230.4-230.4 230.4 103.168 230.4 230.4-103.168 230.4-230.4 230.4zM384 512c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM384 614.4c14.080 0 25.6 11.469 25.6 25.6s-11.52 25.6-25.6 25.6h-51.2c-14.080 0-25.6-11.469-25.6-25.6s11.52-25.6 25.6-25.6h51.2zM844.8 716.8c14.131 0 25.6 11.469 25.6 25.6s-11.469 25.6-25.6 25.6h-102.4c-14.131 0-25.6-11.469-25.6-25.6v-102.4c0-14.131 11.469-25.6 25.6-25.6s25.6 11.469 25.6 25.6v76.8h76.8z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-date-time"],"grid":14},"attrs":[{}],"properties":{"order":70,"id":24,"name":"control-DateTime","prevSize":28,"code":59703},"setIdx":7,"setId":3,"iconIdx":24},{"icon":{"paths":["M793.6 609.416h-61.838v-28.108h-0.783q-21.135 33.092-62.034 33.092-37.573 0-60.469-26.912-22.896-27.112-22.896-75.554 0-50.635 25.244-81.136t66.144-30.501q38.747 0 54.011 28.308h0.783v-121.405h61.838v302.216zM732.936 510.139v-15.35q0-19.935-11.35-33.092t-29.549-13.157q-20.548 0-32.093 16.546-11.546 16.347-11.546 45.053 0 26.912 11.154 41.465t30.919 14.553q18.786 0 30.528-15.35 11.937-15.35 11.937-40.668zM548.594 609.416h-61.643v-116.421q0-44.455-32.093-44.455-15.264 0-24.853 13.357t-9.589 33.292v114.228h-61.839v-117.617q0-43.259-31.506-43.259-15.851 0-25.44 12.758-9.393 12.758-9.393 34.687v113.431h-61.838v-204.135h61.838v31.896h0.783q9.589-16.347 26.81-26.514 17.417-10.366 37.964-10.366 42.465 0 58.12 38.076 22.896-38.076 67.318-38.076 65.361 0 65.361 82.133v126.987zM0 0v204.8h76.8v76.8h51.2v-76.8h76.8v-204.8zM819.2 0v204.8h204.8v-204.8zM51.2 51.2h102.4v102.4h-102.4zM870.4 51.2h102.4v102.4h-102.4zM281.6 76.8v51.2h102.4v-51.2zM486.4 76.8v51.2h102.4v-51.2zM691.2 76.8v51.2h102.4v-51.2zM896 281.6v102.4h51.2v-102.4zM76.8 384v102.4h51.2v-102.4zM896 486.4v102.4h51.2v-102.4zM76.8 588.8v102.4h51.2v-102.4zM896 691.2v102.4h51.2v-102.4zM76.8 793.6v25.6h-76.8v204.8h204.8v-76.8h76.8v-51.2h-76.8v-76.8h-76.8v-25.6zM819.2 819.2v76.8h-25.6v51.2h25.6v76.8h204.8v-204.8zM51.2 870.4h102.4v102.4h-102.4zM870.4 870.4h102.4v102.4h-102.4zM384 896v51.2h102.4v-51.2zM588.8 896v51.2h102.4v-51.2z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["control-Markdown"],"grid":14},"attrs":[{}],"properties":{"order":72,"id":25,"name":"control-Markdown","prevSize":28,"code":59704},"setIdx":7,"setId":3,"iconIdx":25},{"icon":{"paths":["M292.571 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM292.571 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 713.143v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM658.286 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 420.571v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857zM1024 128v109.714c0 30.286-24.571 54.857-54.857 54.857h-182.857c-30.286 0-54.857-24.571-54.857-54.857v-109.714c0-30.286 24.571-54.857 54.857-54.857h182.857c30.286 0 54.857 24.571 54.857 54.857z"],"width":1024,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["th"],"defaultCode":61450,"grid":14},"attrs":[],"properties":{"name":"grid","id":26,"order":83,"prevSize":28,"code":61450},"setIdx":7,"setId":3,"iconIdx":26},{"icon":{"paths":["M877.714 768v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 475.429v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571zM877.714 182.857v73.143c0 20-16.571 36.571-36.571 36.571h-804.571c-20 0-36.571-16.571-36.571-36.571v-73.143c0-20 16.571-36.571 36.571-36.571h804.571c20 0 36.571 16.571 36.571 36.571z"],"width":877.7142857142857,"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["bars","navicon","reorder"],"defaultCode":61641,"grid":14},"attrs":[],"properties":{"name":"list1","id":27,"order":89,"prevSize":28,"code":61641},"setIdx":7,"setId":3,"iconIdx":27},{"icon":{"paths":["M512 64c-131.696 0-239.125 107.4-239.125 239 0 65.8 24.831 146.717 65.375 215.25 19.653 33.221 43.902 63.853 71.75 87.125-59.423 7.524-122.009 9.415-172.125 32-79.809 35.967-144.343 94.74-172.375 178.625-1.5 9.499 0 0-1.5 9v0.499c0 73.995 60.563 134.501 134.375 134.501h627.125c73.888 0 134.5-60.506 134.5-134.5l-1.5-9.375c-27.845-84.263-92.273-143.119-172.125-179-50.17-22.544-112.844-24.421-172.375-31.875 27.792-23.26 52.002-53.831 71.625-87 40.544-68.533 65.375-149.45 65.375-215.25 0-131.6-107.304-239-239-239zM512 124c99.241 0 179 79.875 179 179 0 49.562-21.877 125.381-57 184.75s-81.435 98.75-122 98.75c-40.565 0-86.877-39.381-122-98.75s-57.125-135.188-57.125-184.75c0-99.125 79.884-179 179.125-179zM512 646.5c92.551 0 180.829 14.406 249.75 45.375 66.784 30.009 113.649 74.724 136.5 137.75-2.447 39.259-32.9 70.375-72.75 70.375h-627.125c-39.678 0-70.116-31.051-72.625-70.25 22.978-62.705 69.953-107.523 136.75-137.625 68.937-31.067 157.205-45.625 249.5-45.625z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"tags":["user-o"],"grid":14},"attrs":[{}],"properties":{"order":64,"id":28,"name":"user-o","prevSize":28,"code":59698},"setIdx":7,"setId":3,"iconIdx":28},{"icon":{"paths":["M217.6 992c-3.2 0-3.2 0-6.4 0h-3.2c-144-25.6-208-144-208-249.6 0-99.2 57.6-208 185.6-240v-147.2c0-19.2 12.8-32 32-32s32 12.8 32 32v172.8c0 16-12.8 28.8-25.6 32-108.8 16-160 102.4-160 182.4s48 166.4 153.6 185.6h6.4c16 3.2 28.8 19.2 25.6 38.4-3.2 16-16 25.6-32 25.6z","M774.4 1001.6c0 0 0 0 0 0-102.4 0-211.2-60.8-243.2-185.6h-176c-19.2 0-32-12.8-32-32s12.8-32 32-32h201.6c16 0 28.8 12.8 32 25.6 16 108.8 102.4 156.8 182.4 160 80 0 166.4-48 185.6-153.6v-3.2c3.2-16 19.2-28.8 38.4-25.6 16 3.2 28.8 19.2 25.6 38.4v3.2c-22.4 140.8-140.8 204.8-246.4 204.8z","M787.2 678.4c-19.2 0-32-12.8-32-32v-176c0-16 12.8-28.8 25.6-32 108.8-16 156.8-102.4 160-182.4 0-80-48-166.4-153.6-185.6h-3.2c-19.2-6.4-32-22.4-28.8-38.4s19.2-28.8 38.4-25.6h3.2c144 25.6 208 144 208 249.6 0 99.2-60.8 208-185.6 240v150.4c0 16-16 32-32 32z","M41.6 246.4c-3.2 0-3.2 0-6.4 0-16-3.2-28.8-19.2-25.6-35.2v-3.2c25.6-144 140.8-208 246.4-208 0 0 3.2 0 3.2 0 99.2 0 208 60.8 240 185.6h147.2c19.2 0 32 12.8 32 32s-12.8 32-32 32h-172.8c-16 0-28.8-12.8-32-25.6-16-108.8-102.4-156.8-182.4-160-80 0-166.4 48-185.6 153.6v3.2c-3.2 16-16 25.6-32 25.6z","M256 387.2c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-25.6 22.4-57.6 35.2-92.8 35.2zM256 192c-16 0-32 6.4-44.8 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-32-19.2-44.8-28.8-19.2-48-19.2z","M771.2 873.6c-32 0-67.2-12.8-92.8-38.4-51.2-51.2-51.2-134.4 0-185.6 25.6-25.6 57.6-38.4 92.8-38.4s67.2 12.8 92.8 38.4c25.6 25.6 38.4 57.6 38.4 92.8s-12.8 67.2-38.4 92.8c-28.8 25.6-60.8 38.4-92.8 38.4zM771.2 678.4c-19.2 0-35.2 6.4-48 19.2-25.6 25.6-25.6 67.2 0 92.8s67.2 25.6 92.8 0c12.8-12.8 19.2-28.8 19.2-48s-6.4-35.2-19.2-48-28.8-16-44.8-16z","M745.6 387.2c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 60.8-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM745.6 192c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z","M259.2 873.6c-32 0-67.2-12.8-92.8-38.4s-38.4-57.6-38.4-92.8 12.8-67.2 38.4-92.8c25.6-22.4 57.6-35.2 92.8-35.2s67.2 12.8 92.8 38.4c51.2 51.2 51.2 134.4 0 185.6v0c-25.6 22.4-57.6 35.2-92.8 35.2zM259.2 678.4c-19.2 0-35.2 6.4-48 19.2s-19.2 28.8-19.2 48 6.4 35.2 19.2 48c25.6 25.6 67.2 25.6 92.8 0s25.6-67.2 0-92.8c-9.6-16-25.6-22.4-44.8-22.4z"],"attrs":[{},{},{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["webhooks"],"grid":14},"attrs":[{},{},{},{},{},{},{},{}],"properties":{"order":92,"id":29,"name":"rules","prevSize":28,"code":59719},"setIdx":7,"setId":3,"iconIdx":29}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showCodes":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"name":"icomoon","classSelector":".icon"},"historySize":50}} \ 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 b97bacc51..33e95defc 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?dvmkhg'); - src: url('fonts/icomoon.eot?dvmkhg#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?dvmkhg') format('truetype'), - url('fonts/icomoon.woff?dvmkhg') format('woff'), - url('fonts/icomoon.svg?dvmkhg#icomoon') format('svg'); + src: url('fonts/icomoon.eot?6bqpt3'); + src: url('fonts/icomoon.eot?6bqpt3#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?6bqpt3') format('truetype'), + url('fonts/icomoon.woff?6bqpt3') format('woff'), + url('fonts/icomoon.svg?6bqpt3#icomoon') format('svg'); font-weight: normal; font-style: normal; } @@ -24,6 +24,9 @@ -moz-osx-font-smoothing: grayscale; } +.icon-upload-2:before { + content: "\e972"; +} .icon-translate:before { content: "\e96f"; } @@ -57,6 +60,84 @@ .icon-download:before { content: "\e93e"; } +.icon-upload:before { + content: "\e970"; +} +.icon-caret-bottom:before { + content: "\e96b"; +} +.icon-caret-top:before { + content: "\e96c"; +} +.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"; +} +.icon-star-full:before { + content: "\e95d"; +} +.icon-star-empty:before { + content: "\e95e"; +} +.icon-twitter:before { + content: "\e95c"; +} +.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-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-prerender:before { content: "\e94c"; } @@ -213,6 +294,12 @@ .icon-user:before { content: "\e928"; } +.icon-upload-3:before { + content: "\e973"; +} +.icon-upload-4:before { + content: "\e971"; +} .icon-control-Color:before { content: "\e94d"; } @@ -234,81 +321,6 @@ .icon-info:before { content: "\e93c"; } -.icon-caret-bottom:before { - content: "\e96b"; -} -.icon-caret-top:before { - content: "\e96c"; -} -.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"; -} -.icon-star-full:before { - content: "\e95d"; -} -.icon-star-empty:before { - content: "\e95e"; -} -.icon-twitter:before { - content: "\e95c"; -} -.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-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-clone:before { content: "\e96a"; } From 173391026d3f0d3f3dad6d9301f655407a1e529e Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 27 Apr 2019 17:06:02 +0200 Subject: [PATCH 06/20] Simplified users and event consumers state. --- .../guards/user-must-exist.guard.spec.ts | 5 +- .../pages/users/users-page.component.ts | 15 +- .../state/event-consumers.state.spec.ts | 13 +- .../state/event-consumers.state.ts | 53 +++--- .../administration/state/users.state.spec.ts | 44 ++--- .../administration/state/users.state.ts | 168 +++++++++++------- .../app/framework/utils/immutable-array.ts | 5 + 7 files changed, 173 insertions(+), 130 deletions(-) diff --git a/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts b/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts index 8fb04cde5..8070a5f30 100644 --- a/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts +++ b/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts @@ -9,8 +9,7 @@ import { Router } from '@angular/router'; import { of } from 'rxjs'; import { IMock, Mock, Times } from 'typemoq'; -import { UserDto } from './../services/users.service'; -import { UsersState } from './../state/users.state'; +import { SnapshotUser, UsersState } from './../state/users.state'; import { UserMustExistGuard } from './user-must-exist.guard'; describe('UserMustExistGuard', () => { @@ -32,7 +31,7 @@ describe('UserMustExistGuard', () => { it('should load user and return true when found', () => { usersState.setup(x => x.select('123')) - .returns(() => of({})); + .returns(() => of({})); let result: boolean; diff --git a/src/Squidex/app/features/administration/pages/users/users-page.component.ts b/src/Squidex/app/features/administration/pages/users/users-page.component.ts index a7b6ab87d..b0137f171 100644 --- a/src/Squidex/app/features/administration/pages/users/users-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/users-page.component.ts @@ -7,7 +7,6 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { UserDto, UsersState } from '../../declarations'; @@ -25,31 +24,31 @@ export class UsersPageComponent implements OnInit { } public ngOnInit() { - this.usersState.load().pipe(onErrorResumeNext()).subscribe(); + this.usersState.load(); } public reload() { - this.usersState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.usersState.load(true); } public search() { - this.usersState.search(this.usersFilter.value).pipe(onErrorResumeNext()).subscribe(); + this.usersState.search(this.usersFilter.value); } public goPrev() { - this.usersState.goPrev().pipe(onErrorResumeNext()).subscribe(); + this.usersState.goPrev(); } public goNext() { - this.usersState.goNext().pipe(onErrorResumeNext()).subscribe(); + this.usersState.goNext(); } public lock(user: UserDto) { - this.usersState.lock(user).pipe(onErrorResumeNext()).subscribe(); + this.usersState.lock(user); } public unlock(user: UserDto) { - this.usersState.unlock(user).pipe(onErrorResumeNext()).subscribe(); + this.usersState.unlock(user); } public trackByUser(index: number, userInfo: { user: UserDto }) { diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts index c288609e7..2fc2ae90e 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts @@ -6,7 +6,6 @@ */ import { of, throwError } from 'rxjs'; -import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, It, Mock, Times } from 'typemoq'; import { DialogService } from '@app/shared'; @@ -46,7 +45,7 @@ describe('EventConsumersState', () => { }); it('should show notification on load when reload is true', () => { - eventConsumersState.load(true).subscribe(); + eventConsumersState.load(true); expect().nothing(); @@ -57,7 +56,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.getEventConsumers()) .returns(() => throwError({})); - eventConsumersState.load(true, false).pipe(onErrorResumeNext()).subscribe(); + eventConsumersState.load(true, false); expect().nothing(); @@ -68,7 +67,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.getEventConsumers()) .returns(() => throwError({})); - eventConsumersState.load(true, true).pipe(onErrorResumeNext()).subscribe(); + eventConsumersState.load(true, true); expect().nothing(); @@ -79,7 +78,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.putStart(oldConsumers[1].name)) .returns(() => of({})); - eventConsumersState.start(oldConsumers[1]).subscribe(); + eventConsumersState.start(oldConsumers[1]); const es_1 = eventConsumersState.snapshot.eventConsumers.at(1); @@ -90,7 +89,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.putStop(oldConsumers[0].name)) .returns(() => of({})); - eventConsumersState.stop(oldConsumers[0]).subscribe(); + eventConsumersState.stop(oldConsumers[0]); const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); @@ -101,7 +100,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.putReset(oldConsumers[0].name)) .returns(() => of({})); - eventConsumersState.reset(oldConsumers[0]).subscribe(); + eventConsumersState.reset(oldConsumers[0]); const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.ts b/src/Squidex/app/features/administration/state/event-consumers.state.ts index 80a89eac8..3a4cfa880 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.ts @@ -10,6 +10,7 @@ import { Observable } from 'rxjs'; import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { + array, DialogService, ImmutableArray, State @@ -19,12 +20,14 @@ import { EventConsumerDto, EventConsumersService } from './../services/event-con interface Snapshot { // The list of event consumers. - eventConsumers: ImmutableArray; + eventConsumers: EventConsumersList; // Indicates if event consumers are loaded. isLoaded?: boolean; } +type EventConsumersList = ImmutableArray; + @Injectable() export class EventConsumersState extends State { public eventConsumers = @@ -42,21 +45,21 @@ export class EventConsumersState extends State { super({ eventConsumers: ImmutableArray.empty() }); } - public load(isReload = false, silent = false): Observable { + public load(isReload = false, silent = false): Observable { if (!isReload) { this.resetState(); } - const stream = this.eventConsumersService.getEventConsumers().pipe(share()); + const stream = + this.eventConsumersService.getEventConsumers().pipe( + map(dtos => array(dtos)), share()); - stream.subscribe(dtos => { + stream.subscribe(eventConsumers => { if (isReload && !silent) { this.dialogs.notifyInfo('Event Consumers reloaded.'); } this.next(s => { - const eventConsumers = ImmutableArray.of(dtos); - return { ...s, eventConsumers, isLoaded: true }; }); @@ -70,39 +73,41 @@ export class EventConsumersState extends State { } public start(eventConsumer: EventConsumerDto): Observable { - const stream = this.eventConsumersService.putStart(eventConsumer.name).pipe(share()); + const stream = + this.eventConsumersService.putStart(eventConsumer.name).pipe( + map(_ => setStopped(eventConsumer, false), share())); - stream.subscribe(() => { - this.replaceEventConsumer(setStopped(eventConsumer, false)); - }, error => { - this.dialogs.notifyError(error); - }); + this.updateState(stream); return stream; } - public stop(eventConsumer: EventConsumerDto): Observable { - const stream = this.eventConsumersService.putStop(eventConsumer.name).pipe(share()); + public stop(eventConsumer: EventConsumerDto): Observable { + const stream = + this.eventConsumersService.putStop(eventConsumer.name).pipe( + map(_ => setStopped(eventConsumer, true), share())); - stream.subscribe(() => { - this.replaceEventConsumer(setStopped(eventConsumer, true)); - }, error => { - this.dialogs.notifyError(error); - }); + this.updateState(stream); return stream; } public reset(eventConsumer: EventConsumerDto): Observable { - const stream = this.eventConsumersService.putReset(eventConsumer.name).pipe(share()); + const stream = + this.eventConsumersService.putReset(eventConsumer.name).pipe( + map(_ => reset(eventConsumer), share())); + + this.updateState(stream); - stream.subscribe(() => { - this.replaceEventConsumer(reset(eventConsumer)); + return stream; + } + + private updateState(stream: Observable) { + stream.subscribe(updated => { + this.replaceEventConsumer(updated); }, error => { this.dialogs.notifyError(error); }); - - return stream; } private replaceEventConsumer(eventConsumer: EventConsumerDto) { diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts index cc7939542..195cf3175 100644 --- a/src/Squidex/app/features/administration/state/users.state.spec.ts +++ b/src/Squidex/app/features/administration/state/users.state.spec.ts @@ -10,7 +10,7 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { AuthService, DialogService } from '@app/shared'; -import { UsersState } from './users.state'; +import { SnapshotUser, UsersState } from './users.state'; import { UserDto, @@ -45,7 +45,7 @@ describe('UsersState', () => { .returns(() => of(new UsersDto(200, oldUsers))); usersState = new UsersState(authService.object, dialogs.object, usersService.object); - usersState.load().subscribe(); + usersState.load(); }); it('should load users', () => { @@ -60,7 +60,7 @@ describe('UsersState', () => { }); it('should show notification on load when reload is true', () => { - usersState.load(true).subscribe(); + usersState.load(true); expect().nothing(); @@ -68,7 +68,7 @@ describe('UsersState', () => { }); it('should replace selected user when reloading', () => { - usersState.select('id1').subscribe(); + usersState.select('id1'); const newUsers = [ new UserDto('id1', 'mail1@mail.de_new', 'name1_new', ['Permission1_New'], false), @@ -78,19 +78,19 @@ describe('UsersState', () => { usersService.setup(x => x.getUsers(10, 0, undefined)) .returns(() => of(new UsersDto(200, newUsers))); - usersState.load().subscribe(); + usersState.load(); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUsers[0] }); }); it('should return user on select and not load when already loaded', () => { - let selectedUser: UserDto; + let selectedUser: SnapshotUser; usersState.select('id1').subscribe(x => { selectedUser = x!; }); - expect(selectedUser!).toEqual(oldUsers[0]); + expect(selectedUser!.user).toEqual(oldUsers[0]); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: oldUsers[0] }); usersService.verify(x => x.getUser(It.isAnyString()), Times.never()); @@ -100,20 +100,20 @@ describe('UsersState', () => { usersService.setup(x => x.getUser('id3')) .returns(() => of(newUser)); - let selectedUser: UserDto; + let selectedUser: SnapshotUser; usersState.select('id3').subscribe(x => { selectedUser = x!; }); - expect(selectedUser!).toEqual(newUser); + expect(selectedUser!.user).toEqual(newUser); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUser }); usersService.verify(x => x.getUser('id3'), Times.once()); }); it('should return null on select when unselecting user', () => { - let selectedUser: UserDto; + let selectedUser: SnapshotUser; usersState.select(null).subscribe(x => { selectedUser = x!; @@ -129,11 +129,11 @@ describe('UsersState', () => { usersService.setup(x => x.getUser('unknown')) .returns(() => throwError({})); - let selectedUser: UserDto; + let selectedUser: SnapshotUser; usersState.select('unknown').subscribe(x => { selectedUser = x!; - }).unsubscribe(); + }); expect(selectedUser!).toBeNull(); expect(usersState.snapshot.selectedUser).toBeNull(); @@ -143,8 +143,8 @@ describe('UsersState', () => { usersService.setup(x => x.lockUser('id1')) .returns(() => of({})); - usersState.select('id1').subscribe(); - usersState.lock(oldUsers[0]).subscribe(); + usersState.select('id1'); + usersState.lock(oldUsers[0]); const user_1 = usersState.snapshot.users.at(0); @@ -156,8 +156,8 @@ describe('UsersState', () => { usersService.setup(x => x.unlockUser('id2')) .returns(() => of({})); - usersState.select('id2').subscribe(); - usersState.unlock(oldUsers[1]).subscribe(); + usersState.select('id2'); + usersState.unlock(oldUsers[1]); const user_1 = usersState.snapshot.users.at(1); @@ -171,8 +171,8 @@ describe('UsersState', () => { usersService.setup(x => x.putUser('id1', request)) .returns(() => of({})); - usersState.select('id1').subscribe(); - usersState.update(oldUsers[0], request).subscribe(); + usersState.select('id1'); + usersState.update(oldUsers[0], request); const user_1 = usersState.snapshot.users.at(0); @@ -188,7 +188,7 @@ describe('UsersState', () => { usersService.setup(x => x.postUser(request)) .returns(() => of(newUser)); - usersState.create(request).subscribe(); + usersState.create(request); expect(usersState.snapshot.users.values).toEqual([ { isCurrentUser: false, user: newUser }, @@ -202,8 +202,8 @@ describe('UsersState', () => { usersService.setup(x => x.getUsers(10, 10, undefined)) .returns(() => of(new UsersDto(200, []))); - usersState.goNext().subscribe(); - usersState.goPrev().subscribe(); + usersState.goNext(); + usersState.goPrev(); expect().nothing(); @@ -215,7 +215,7 @@ describe('UsersState', () => { usersService.setup(x => x.getUsers(10, 0, 'my-query')) .returns(() => of(new UsersDto(0, []))); - usersState.search('my-query').subscribe(); + usersState.search('my-query'); expect(usersState.snapshot.usersQuery).toEqual('my-query'); diff --git a/src/Squidex/app/features/administration/state/users.state.ts b/src/Squidex/app/features/administration/state/users.state.ts index c5d82e70e..fa566a27e 100644 --- a/src/Squidex/app/features/administration/state/users.state.ts +++ b/src/Squidex/app/features/administration/state/users.state.ts @@ -7,15 +7,15 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; -import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, map, share, switchMap } from 'rxjs/operators'; import '@app/framework/utils/rxjs-extensions'; import { + array, AuthService, DialogService, ImmutableArray, - notify, Pager, State } from '@app/shared'; @@ -27,7 +27,7 @@ import { UsersService } from './../services/users.service'; -interface SnapshotUser { +export interface SnapshotUser { // The user. user: UserDto; @@ -37,7 +37,7 @@ interface SnapshotUser { interface Snapshot { // The current users. - users: ImmutableArray; + users: UsersList; // The pagination information. usersPager: Pager; @@ -52,6 +52,9 @@ interface Snapshot { selectedUser?: SnapshotUser | null; } +export type UsersList = ImmutableArray; +export type UsersResult = { total: number, users: UsersList }; + @Injectable() export class UsersState extends State { public users = @@ -78,25 +81,28 @@ export class UsersState extends State { super({ users: ImmutableArray.empty(), usersPager: new Pager(0) }); } - public select(id: string | null): Observable { - return this.loadUser(id).pipe( - tap(selectedUser => { - this.next(s => ({ ...s, selectedUser })); - }), - map(x => x && x.user)); + public select(id: string | null): Observable { + const stream = this.loadUser(id).pipe(share()); + + stream.subscribe(selectedUser => { + this.next(s => ({ ...s, selectedUser })); + }); + + return stream; } private loadUser(id: string | null) { - return !id ? - of(null) : - of(this.snapshot.users.find(x => x.user.id === id)).pipe( - switchMap(user => { - if (!user) { - return this.usersService.getUser(id).pipe(map(x => this.createUser(x)), catchError(() => of(null))); - } else { - return of(user); - } - })); + if (!id) { + return of(null); + } + + const found = this.snapshot.users.find(x => x.user.id === id); + + if (found) { + return of(found); + } + + return this.usersService.getUser(id).pipe(map(x => this.createUser(x)), catchError(() => of(null))); } public load(isReload = false): Observable { @@ -107,80 +113,96 @@ export class UsersState extends State { return this.loadInternal(isReload); } - private loadInternal(isReload = false): Observable { - return this.usersService.getUsers( + private loadInternal(isReload = false): Observable { + const stream = + this.usersService.getUsers( this.snapshot.usersPager.pageSize, this.snapshot.usersPager.skip, this.snapshot.usersQuery).pipe( - tap(dtos => { - if (isReload) { - this.dialogs.notifyInfo('Users reloaded.'); - } + map(({ total, items }) => ({ total, users: array(items.map(x => this.createUser(x))) })), share()); - this.next(s => { - const users = ImmutableArray.of(dtos.items.map(x => this.createUser(x))); - const usersPager = s.usersPager.setCount(dtos.total); + stream.subscribe(({ total, users }) => { + if (isReload) { + this.dialogs.notifyInfo('Users reloaded.'); + } - let selectedUser = s.selectedUser; + this.next(s => { + const usersPager = s.usersPager.setCount(total); - if (selectedUser) { - selectedUser = users.find(x => x.user.id === selectedUser!.user.id) || selectedUser; - } + let selectedUser = s.selectedUser; - return { ...s, users, usersPager, selectedUser, isLoaded: true }; - }); - }), - notify(this.dialogs)); + if (selectedUser) { + selectedUser = users.find(x => x.user.id === selectedUser!.user.id) || selectedUser; + } + + return { ...s, users, usersPager, selectedUser, isLoaded: true }; + }); + + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } public create(request: CreateUserDto): Observable { - return this.usersService.postUser(request).pipe( - tap(dto => { - this.next(s => { - const users = s.users.pushFront(this.createUser(dto)); - const usersPager = s.usersPager.incrementCount(); + const stream = this.usersService.postUser(request).pipe(share()); + + stream.subscribe(dto => { + this.next(s => { + const users = s.users.pushFront(this.createUser(dto)); + const usersPager = s.usersPager.incrementCount(); + + return { ...s, users, usersPager }; + }); + }); - return { ...s, users, usersPager }; - }); - })); + return stream; } - public update(user: UserDto, request: UpdateUserDto): Observable { - return this.usersService.putUser(user.id, request).pipe( - tap(() => { - this.replaceUser(update(user, request)); - })); + public update(user: UserDto, request: UpdateUserDto): Observable { + const stream = + this.usersService.putUser(user.id, request).pipe( + map(_ => update(user, request)), share()); + + this.updateState(stream, false); + + return stream; } - public lock(user: UserDto): Observable { - return this.usersService.lockUser(user.id).pipe( - tap(() => { - this.replaceUser(setLocked(user, true)); - }), - notify(this.dialogs)); + public lock(user: UserDto): Observable { + const stream = + this.usersService.lockUser(user.id).pipe( + map(_ => setLocked(user, true)), share()); + + this.updateState(stream, true); + + return stream; } - public unlock(user: UserDto): Observable { - return this.usersService.unlockUser(user.id).pipe( - tap(() => { - this.replaceUser(setLocked(user, false)); - }), - notify(this.dialogs)); + public unlock(user: UserDto): Observable { + const stream = + this.usersService.unlockUser(user.id).pipe( + map(_ => setLocked(user, false)), share()); + + this.updateState(stream, true); + + return stream; } - public search(query: string): Observable { + public search(query: string): Observable { this.next(s => ({ ...s, usersPager: new Pager(0), usersQuery: query })); return this.loadInternal(); } - public goNext(): Observable { + public goNext(): Observable { this.next(s => ({ ...s, usersPager: s.usersPager.goNext() })); return this.loadInternal(); } - public goPrev(): Observable { + public goPrev(): Observable { this.next(s => ({ ...s, usersPager: s.usersPager.goPrev() })); return this.loadInternal(); @@ -190,7 +212,11 @@ export class UsersState extends State { return this.next(s => { const users = s.users.map(u => u.user.id === user.id ? this.createUser(user, u) : u); - const selectedUser = s.selectedUser && s.selectedUser.user.id === user.id ? users.find(x => x.user.id === user.id) : s.selectedUser; + const selectedUser = + s.selectedUser && + s.selectedUser.user.id !== user.id ? + s.selectedUser : + users.find(x => x.user.id === user.id); return { ...s, users, selectedUser }; }); @@ -200,6 +226,16 @@ export class UsersState extends State { return this.authState.user!.id; } + private updateState(stream: Observable, notify: boolean) { + stream.subscribe(dto => { + this.replaceUser(dto); + }, error => { + if (notify) { + this.dialogs.notifyError(error); + } + }); + } + private createUser(user: UserDto, current?: SnapshotUser): SnapshotUser { if (!user) { return null!; diff --git a/src/Squidex/app/framework/utils/immutable-array.ts b/src/Squidex/app/framework/utils/immutable-array.ts index 0779e947d..ecb1a9d3f 100644 --- a/src/Squidex/app/framework/utils/immutable-array.ts +++ b/src/Squidex/app/framework/utils/immutable-array.ts @@ -17,6 +17,11 @@ function freeze(items: T[]): T[] { return items; } + +export function array(items?: V[]): ImmutableArray { + return ImmutableArray.of(items); +} + export class ImmutableArray implements Iterable { private static readonly EMPTY = new ImmutableArray([]); private readonly items: T[]; From 57eaab592a8f9b98c2dadb2807114285b1682ff5 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 27 Apr 2019 18:53:12 +0200 Subject: [PATCH 07/20] More refactorings. --- .../state/event-consumers.state.spec.ts | 32 +++-- .../state/event-consumers.state.ts | 8 +- .../administration/state/users.state.spec.ts | 58 ++++---- .../administration/state/users.state.ts | 10 +- .../pages/clients/client.component.ts | 64 +++++---- .../pages/clients/clients-page.component.ts | 7 +- .../contributors-page.component.ts | 12 +- .../framework/angular/forms/forms-helper.ts | 2 +- src/Squidex/app/framework/state.ts | 8 +- .../app/framework/utils/version.spec.ts | 2 +- .../shared/interceptors/auth.interceptor.ts | 2 +- .../app/shared/services/help.service.ts | 2 +- src/Squidex/app/shared/services/ui.service.ts | 4 +- .../app/shared/state/assets.state.spec.ts | 2 +- .../app/shared/state/clients.state.spec.ts | 12 +- src/Squidex/app/shared/state/clients.state.ts | 100 ++++++++------ .../app/shared/state/comments.state.spec.ts | 22 ++-- .../app/shared/state/comments.state.ts | 124 +++++++++++------- .../shared/state/contributors.state.spec.ts | 14 +- .../app/shared/state/contributors.state.ts | 85 +++++++----- .../app/shared/state/languages.state.spec.ts | 6 +- .../app/shared/state/patterns.state.spec.ts | 6 +- .../app/shared/state/plans.state.spec.ts | 5 +- .../app/shared/state/roles.state.spec.ts | 6 +- .../app/shared/state/rules.state.spec.ts | 10 +- .../app/shared/state/schemas.state.spec.ts | 54 ++++---- 26 files changed, 362 insertions(+), 295 deletions(-) diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts index 2fc2ae90e..a5b6120b4 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts @@ -6,6 +6,7 @@ */ import { of, throwError } from 'rxjs'; +import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, It, Mock, Times } from 'typemoq'; import { DialogService } from '@app/shared'; @@ -15,8 +16,8 @@ import { EventConsumersState } from './event-consumers.state'; describe('EventConsumersState', () => { const oldConsumers = [ - new EventConsumerDto('name1', false), - new EventConsumerDto('name2', true) + new EventConsumerDto('name1', false, false, 'error', '1'), + new EventConsumerDto('name2', true, true, 'error', '2') ]; let dialogs: IMock; @@ -29,12 +30,16 @@ describe('EventConsumersState', () => { eventConsumersService = Mock.ofType(); eventConsumersService.setup(x => x.getEventConsumers()) - .returns(() => of(oldConsumers)); + .returns(() => of(oldConsumers)).verifiable(Times.atLeastOnce()); eventConsumersState = new EventConsumersState(dialogs.object, eventConsumersService.object); eventConsumersState.load().subscribe(); }); + afterEach(() => { + eventConsumersService.verifyAll(); + }); + it('should load event consumers', () => { expect(eventConsumersState.snapshot.eventConsumers.values).toEqual(oldConsumers); expect(eventConsumersState.snapshot.isLoaded).toBeTruthy(); @@ -45,7 +50,10 @@ describe('EventConsumersState', () => { }); it('should show notification on load when reload is true', () => { - eventConsumersState.load(true); + eventConsumersService.setup(x => x.getEventConsumers()) + .returns(() => of(oldConsumers)); + + eventConsumersState.load(true).subscribe(); expect().nothing(); @@ -56,7 +64,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.getEventConsumers()) .returns(() => throwError({})); - eventConsumersState.load(true, false); + eventConsumersState.load(true, false).pipe(onErrorResumeNext()).subscribe(); expect().nothing(); @@ -67,7 +75,7 @@ describe('EventConsumersState', () => { eventConsumersService.setup(x => x.getEventConsumers()) .returns(() => throwError({})); - eventConsumersState.load(true, true); + eventConsumersState.load(true, true).pipe(onErrorResumeNext()).subscribe(); expect().nothing(); @@ -76,9 +84,9 @@ describe('EventConsumersState', () => { it('should unmark as stopped when started', () => { eventConsumersService.setup(x => x.putStart(oldConsumers[1].name)) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - eventConsumersState.start(oldConsumers[1]); + eventConsumersState.start(oldConsumers[1]).subscribe(); const es_1 = eventConsumersState.snapshot.eventConsumers.at(1); @@ -87,9 +95,9 @@ describe('EventConsumersState', () => { it('should mark as stopped when stopped', () => { eventConsumersService.setup(x => x.putStop(oldConsumers[0].name)) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - eventConsumersState.stop(oldConsumers[0]); + eventConsumersState.stop(oldConsumers[0]).subscribe(); const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); @@ -98,9 +106,9 @@ describe('EventConsumersState', () => { it('should mark as resetting when reset', () => { eventConsumersService.setup(x => x.putReset(oldConsumers[0].name)) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - eventConsumersState.reset(oldConsumers[0]); + eventConsumersState.reset(oldConsumers[0]).subscribe(); const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.ts b/src/Squidex/app/features/administration/state/event-consumers.state.ts index 3a4cfa880..5cd3e9d1d 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.ts @@ -45,7 +45,7 @@ export class EventConsumersState extends State { super({ eventConsumers: ImmutableArray.empty() }); } - public load(isReload = false, silent = false): Observable { + public load(isReload = false, silent = false): Observable { if (!isReload) { this.resetState(); } @@ -75,7 +75,7 @@ export class EventConsumersState extends State { public start(eventConsumer: EventConsumerDto): Observable { const stream = this.eventConsumersService.putStart(eventConsumer.name).pipe( - map(_ => setStopped(eventConsumer, false), share())); + map(() => setStopped(eventConsumer, false), share())); this.updateState(stream); @@ -85,7 +85,7 @@ export class EventConsumersState extends State { public stop(eventConsumer: EventConsumerDto): Observable { const stream = this.eventConsumersService.putStop(eventConsumer.name).pipe( - map(_ => setStopped(eventConsumer, true), share())); + map(() => setStopped(eventConsumer, true), share())); this.updateState(stream); @@ -95,7 +95,7 @@ export class EventConsumersState extends State { public reset(eventConsumer: EventConsumerDto): Observable { const stream = this.eventConsumersService.putReset(eventConsumer.name).pipe( - map(_ => reset(eventConsumer), share())); + map(() => reset(eventConsumer), share())); this.updateState(stream); diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts index 195cf3175..3d799ff27 100644 --- a/src/Squidex/app/features/administration/state/users.state.spec.ts +++ b/src/Squidex/app/features/administration/state/users.state.spec.ts @@ -42,10 +42,14 @@ describe('UsersState', () => { usersService = Mock.ofType(); usersService.setup(x => x.getUsers(10, 0, undefined)) - .returns(() => of(new UsersDto(200, oldUsers))); + .returns(() => of(new UsersDto(200, oldUsers))).verifiable(Times.atLeastOnce()); usersState = new UsersState(authService.object, dialogs.object, usersService.object); - usersState.load(); + usersState.load().subscribe(); + }); + + afterEach(() => { + usersService.verifyAll(); }); it('should load users', () => { @@ -60,7 +64,7 @@ describe('UsersState', () => { }); it('should show notification on load when reload is true', () => { - usersState.load(true); + usersState.load(true).subscribe(); expect().nothing(); @@ -68,7 +72,7 @@ describe('UsersState', () => { }); it('should replace selected user when reloading', () => { - usersState.select('id1'); + usersState.select('id1').subscribe(); const newUsers = [ new UserDto('id1', 'mail1@mail.de_new', 'name1_new', ['Permission1_New'], false), @@ -78,7 +82,7 @@ describe('UsersState', () => { usersService.setup(x => x.getUsers(10, 0, undefined)) .returns(() => of(new UsersDto(200, newUsers))); - usersState.load(); + usersState.load().subscribe(); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUsers[0] }); }); @@ -92,8 +96,6 @@ describe('UsersState', () => { expect(selectedUser!.user).toEqual(oldUsers[0]); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: oldUsers[0] }); - - usersService.verify(x => x.getUser(It.isAnyString()), Times.never()); }); it('should return user on select and load when not loaded', () => { @@ -108,8 +110,6 @@ describe('UsersState', () => { expect(selectedUser!.user).toEqual(newUser); expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUser }); - - usersService.verify(x => x.getUser('id3'), Times.once()); }); it('should return null on select when unselecting user', () => { @@ -121,19 +121,17 @@ describe('UsersState', () => { expect(selectedUser!).toBeNull(); expect(usersState.snapshot.selectedUser).toBeNull(); - - usersService.verify(x => x.getUser(It.isAnyString()), Times.never()); }); it('should return null on select when user is not found', () => { usersService.setup(x => x.getUser('unknown')) - .returns(() => throwError({})); + .returns(() => throwError({})).verifiable(); let selectedUser: SnapshotUser; usersState.select('unknown').subscribe(x => { selectedUser = x!; - }); + }).unsubscribe(); expect(selectedUser!).toBeNull(); expect(usersState.snapshot.selectedUser).toBeNull(); @@ -141,10 +139,10 @@ describe('UsersState', () => { it('should mark as locked when locked', () => { usersService.setup(x => x.lockUser('id1')) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - usersState.select('id1'); - usersState.lock(oldUsers[0]); + usersState.select('id1').subscribe(); + usersState.lock(oldUsers[0]).subscribe(); const user_1 = usersState.snapshot.users.at(0); @@ -154,10 +152,10 @@ describe('UsersState', () => { it('should unmark as locked when unlocked', () => { usersService.setup(x => x.unlockUser('id2')) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - usersState.select('id2'); - usersState.unlock(oldUsers[1]); + usersState.select('id2').subscribe(); + usersState.unlock(oldUsers[1]).subscribe(); const user_1 = usersState.snapshot.users.at(1); @@ -169,10 +167,10 @@ describe('UsersState', () => { const request = { email: 'new@mail.com', displayName: 'New', permissions: ['Permission1'] }; usersService.setup(x => x.putUser('id1', request)) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - usersState.select('id1'); - usersState.update(oldUsers[0], request); + usersState.select('id1').subscribe(); + usersState.update(oldUsers[0], request).subscribe(); const user_1 = usersState.snapshot.users.at(0); @@ -186,9 +184,9 @@ describe('UsersState', () => { const request = { ...newUser, password: 'password' }; usersService.setup(x => x.postUser(request)) - .returns(() => of(newUser)); + .returns(() => of(newUser)).verifiable(); - usersState.create(request); + usersState.create(request).subscribe(); expect(usersState.snapshot.users.values).toEqual([ { isCurrentUser: false, user: newUser }, @@ -200,10 +198,10 @@ describe('UsersState', () => { it('should load next page and prev page when paging', () => { usersService.setup(x => x.getUsers(10, 10, undefined)) - .returns(() => of(new UsersDto(200, []))); + .returns(() => of(new UsersDto(200, []))).verifiable(); - usersState.goNext(); - usersState.goPrev(); + usersState.goNext().subscribe(); + usersState.goPrev().subscribe(); expect().nothing(); @@ -213,12 +211,10 @@ describe('UsersState', () => { it('should load with query when searching', () => { usersService.setup(x => x.getUsers(10, 0, 'my-query')) - .returns(() => of(new UsersDto(0, []))); + .returns(() => of(new UsersDto(0, []))).verifiable(); - usersState.search('my-query'); + usersState.search('my-query').subscribe(); expect(usersState.snapshot.usersQuery).toEqual('my-query'); - - usersService.verify(x => x.getUsers(10, 0, 'my-query'), Times.once()); }); }); \ No newline at end of file diff --git a/src/Squidex/app/features/administration/state/users.state.ts b/src/Squidex/app/features/administration/state/users.state.ts index fa566a27e..2e0e7599b 100644 --- a/src/Squidex/app/features/administration/state/users.state.ts +++ b/src/Squidex/app/features/administration/state/users.state.ts @@ -7,7 +7,7 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; -import { catchError, distinctUntilChanged, map, share, switchMap } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators'; import '@app/framework/utils/rxjs-extensions'; @@ -113,7 +113,7 @@ export class UsersState extends State { return this.loadInternal(isReload); } - private loadInternal(isReload = false): Observable { + private loadInternal(isReload = false): Observable { const stream = this.usersService.getUsers( this.snapshot.usersPager.pageSize, @@ -163,7 +163,7 @@ export class UsersState extends State { public update(user: UserDto, request: UpdateUserDto): Observable { const stream = this.usersService.putUser(user.id, request).pipe( - map(_ => update(user, request)), share()); + map(() => update(user, request)), share()); this.updateState(stream, false); @@ -173,7 +173,7 @@ export class UsersState extends State { public lock(user: UserDto): Observable { const stream = this.usersService.lockUser(user.id).pipe( - map(_ => setLocked(user, true)), share()); + map(() => setLocked(user, true)), share()); this.updateState(stream, true); @@ -183,7 +183,7 @@ export class UsersState extends State { public unlock(user: UserDto): Observable { const stream = this.usersService.unlockUser(user.id).pipe( - map(_ => setLocked(user, false)), share()); + map(() => setLocked(user, false)), share()); this.updateState(stream, true); diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.ts b/src/Squidex/app/features/settings/pages/clients/client.component.ts index e45c48ac9..35437867a 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/client.component.ts @@ -7,7 +7,6 @@ import { Component, Input, OnChanges } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AccessTokenDto, @@ -24,36 +23,6 @@ import { const ESCAPE_KEY = 27; -function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { - const url = apiUrl.buildUrl('identity-server/connect/token'); - - return `$ curl - -X POST '${url}' - -H 'Content-Type: application/x-www-form-urlencoded' - -d 'grant_type=client_credentials& - client_id=${app}:${client.id}& - client_secret=${client.secret}& - scope=squidex-api`; -} - -function connectCLIWinText(app: string, client: { id: string, secret: string }) { - return `.\\sq.exe config add ${app} ${app}:${client.id} ${client.secret};.\\sq.exe config use ${app}`; -} - -function connectCLINixText(app: string, client: { id: string, secret: string }) { - return `sq config add ${app} ${app}:${client.id} ${client.secret} && sq config use ${app}`; -} - -function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { - const url = apiUrl.value; - - return `var clientManager = new SquidexClientManager( - "${url}", - "${app}", - "${app}:${client.id}", - "${client.secret}")`; -} - @Component({ selector: 'sqx-client', styleUrls: ['./client.component.scss'], @@ -100,11 +69,11 @@ export class ClientComponent implements OnChanges { } public revoke() { - this.clientsState.revoke(this.client).pipe(onErrorResumeNext()).subscribe(); + this.clientsState.revoke(this.client); } public update(role: string) { - this.clientsState.update(this.client, { role }).pipe(onErrorResumeNext()).subscribe(); + this.clientsState.update(this.client, { role }); } public toggleRename() { @@ -144,3 +113,32 @@ export class ClientComponent implements OnChanges { } } +function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { + const url = apiUrl.buildUrl('identity-server/connect/token'); + + return `$ curl + -X POST '${url}' + -H 'Content-Type: application/x-www-form-urlencoded' + -d 'grant_type=client_credentials& + client_id=${app}:${client.id}& + client_secret=${client.secret}& + scope=squidex-api`; +} + +function connectCLIWinText(app: string, client: { id: string, secret: string }) { + return `.\\sq.exe config add ${app} ${app}:${client.id} ${client.secret};.\\sq.exe config use ${app}`; +} + +function connectCLINixText(app: string, client: { id: string, secret: string }) { + return `sq config add ${app} ${app}:${client.id} ${client.secret} && sq config use ${app}`; +} + +function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { + const url = apiUrl.value; + + return `var clientManager = new SquidexClientManager( + "${url}", + "${app}", + "${app}:${client.id}", + "${client.secret}")`; +} \ No newline at end of file diff --git a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts index ab81b8776..885085116 100644 --- a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts @@ -7,7 +7,6 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppsState, @@ -34,13 +33,13 @@ export class ClientsPageComponent implements OnInit { } public ngOnInit() { - this.rolesState.load().pipe(onErrorResumeNext()).subscribe(); + this.rolesState.load(); - this.clientsState.load().pipe(onErrorResumeNext()).subscribe(); + this.clientsState.load(); } public reload() { - this.clientsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.clientsState.load(true); } public attachClient() { diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts index 498cd0b5f..79105759c 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts @@ -8,7 +8,7 @@ import { Component, Injectable, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { Observable } from 'rxjs'; -import { onErrorResumeNext, withLatestFrom } from 'rxjs/operators'; +import { withLatestFrom } from 'rxjs/operators'; import { AppsState, @@ -68,21 +68,21 @@ export class ContributorsPageComponent implements OnInit { } public ngOnInit() { - this.rolesState.load().pipe(onErrorResumeNext()).subscribe(); + this.rolesState.load(); - this.contributorsState.load().pipe(onErrorResumeNext()).subscribe(); + this.contributorsState.load(); } public reload() { - this.contributorsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.contributorsState.load(true); } public remove(contributor: ContributorDto) { - this.contributorsState.revoke(contributor).pipe(onErrorResumeNext()).subscribe(); + this.contributorsState.revoke(contributor); } public changeRole(contributor: ContributorDto, role: string) { - this.contributorsState.assign({ contributorId: contributor.contributorId, role }).pipe(onErrorResumeNext()).subscribe(); + this.contributorsState.assign({ contributorId: contributor.contributorId, role }); } public assignContributor() { diff --git a/src/Squidex/app/framework/angular/forms/forms-helper.ts b/src/Squidex/app/framework/angular/forms/forms-helper.ts index 8597769a2..91b4100b3 100644 --- a/src/Squidex/app/framework/angular/forms/forms-helper.ts +++ b/src/Squidex/app/framework/angular/forms/forms-helper.ts @@ -22,7 +22,7 @@ export function formControls(form: AbstractControl): AbstractControl[] { } export function invalid$(form: AbstractControl): Observable { - return form.statusChanges.pipe(map(_ => form.invalid), startWith(form.invalid)); + return form.statusChanges.pipe(map(() => form.invalid), startWith(form.invalid)); } export function value$(form: AbstractControl): Observable { diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index 5a9faa7cc..c788a7700 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -59,13 +59,13 @@ export class Form { } public load(value: V | undefined) { - this.state.next(_ => ({ submitted: false, error: null })); + this.state.next(() => ({ submitted: false, error: null })); this.setValue(value); } public submit(): V | null { - this.state.next(_ => ({ submitted: true })); + this.state.next(() => ({ submitted: true })); if (this.form.valid) { const value = this.transformSubmit(fullValue(this.form)); @@ -79,14 +79,14 @@ export class Form { } public submitCompleted(newValue?: V) { - this.state.next(_ => ({ submitted: false, error: null })); + this.state.next(() => ({ submitted: false, error: null })); this.enable(); this.setValue(newValue); } public submitFailed(error?: string | ErrorDto) { - this.state.next(_ => ({ submitted: false, error: this.getError(error) })); + this.state.next(() => ({ submitted: false, error: this.getError(error) })); this.enable(); } diff --git a/src/Squidex/app/framework/utils/version.spec.ts b/src/Squidex/app/framework/utils/version.spec.ts index 20603d4d3..6cf3e24fe 100644 --- a/src/Squidex/app/framework/utils/version.spec.ts +++ b/src/Squidex/app/framework/utils/version.spec.ts @@ -24,7 +24,7 @@ describe('Version', () => { describe('Versioned', () => { it('should initialize with version and payload', () => { - const versioned = new Versioned(new Version('1.0'), 123); + const versioned = new Versioned(new Version('1.0'), 123); expect(versioned.version.value).toBe('1.0'); expect(versioned.payload).toBe(123); diff --git a/src/Squidex/app/shared/interceptors/auth.interceptor.ts b/src/Squidex/app/shared/interceptors/auth.interceptor.ts index d6e4d5623..c9f92ff09 100644 --- a/src/Squidex/app/shared/interceptors/auth.interceptor.ts +++ b/src/Squidex/app/shared/interceptors/auth.interceptor.ts @@ -50,7 +50,7 @@ export class AuthInterceptor implements HttpInterceptor { catchError((error: HttpErrorResponse) => { if (error.status === 401 && renew) { return this.authService.loginSilent().pipe( - catchError(_ => { + catchError(() => { this.authService.logoutRedirect(); return empty(); diff --git a/src/Squidex/app/shared/services/help.service.ts b/src/Squidex/app/shared/services/help.service.ts index c141dae7b..b37528fd7 100644 --- a/src/Squidex/app/shared/services/help.service.ts +++ b/src/Squidex/app/shared/services/help.service.ts @@ -21,6 +21,6 @@ export class HelpService { const url = `https://raw.githubusercontent.com/Squidex/squidex-docs/master/${helpPage}.md`; return this.http.get(url, { responseType: 'text' }).pipe( - catchError(_ => of(''))); + catchError(() => of(''))); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/services/ui.service.ts b/src/Squidex/app/shared/services/ui.service.ts index 97115ccff..13b23b28d 100644 --- a/src/Squidex/app/shared/services/ui.service.ts +++ b/src/Squidex/app/shared/services/ui.service.ts @@ -31,7 +31,7 @@ export class UIService { const url = this.apiUrl.buildUrl(`api/ui/settings`); return this.http.get(url).pipe( - catchError(_ => { + catchError(() => { return of({ mapType: 'OSM', mapKey: '', canCreateApps: true }); })); } @@ -40,7 +40,7 @@ export class UIService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/ui/settings`); return this.http.get(url).pipe( - catchError(_ => { + catchError(() => { return of({ }); })); } diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index ebd4a8edc..b69927318 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -90,7 +90,7 @@ describe('AssetsState', () => { it('should remove asset from snapshot when deleted', () => { assetsService.setup(x => x.deleteAsset(app, oldAssets[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); assetsState.delete(oldAssets[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index 82971fc19..ad086db0d 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -42,12 +42,16 @@ describe('ClientsState', () => { clientsService = Mock.ofType(); clientsService.setup(x => x.getClients(app)) - .returns(() => of(new ClientsDto(oldClients, version))); + .returns(() => of(new ClientsDto(oldClients, version))).verifiable(Times.atLeastOnce()); clientsState = new ClientsState(clientsService.object, appsState.object, dialogs.object); clientsState.load().subscribe(); }); + afterEach(() => { + clientsService.verifyAll(); + }); + it('should load clients', () => { expect(clientsState.snapshot.clients.values).toEqual(oldClients); expect(clientsState.snapshot.version).toEqual(version); @@ -70,7 +74,7 @@ describe('ClientsState', () => { const request = { id: 'id3' }; clientsService.setup(x => x.postClient(app, request, version)) - .returns(() => of(new Versioned(newVersion, newClient))); + .returns(() => of(new Versioned(newVersion, newClient))).verifiable(); clientsState.attach(request).subscribe(); @@ -82,7 +86,7 @@ describe('ClientsState', () => { const request = { name: 'NewName', role: 'NewRole' }; clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); clientsState.update(oldClients[0], request).subscribe(); @@ -95,7 +99,7 @@ describe('ClientsState', () => { it('should remove client from snapshot when revoked', () => { clientsService.setup(x => x.deleteClient(app, oldClients[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); clientsState.revoke(oldClients[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/clients.state.ts b/src/Squidex/app/shared/state/clients.state.ts index 5f3098169..2f43ec210 100644 --- a/src/Squidex/app/shared/state/clients.state.ts +++ b/src/Squidex/app/shared/state/clients.state.ts @@ -5,14 +5,16 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ +// tslint:disable: no-shadowed-variable + import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { + array, DialogService, ImmutableArray, - notify, State, Version } from '@app/framework'; @@ -28,7 +30,7 @@ import { interface Snapshot { // The current clients. - clients: ImmutableArray; + clients: ClientsList; // The app version. version: Version; @@ -37,6 +39,8 @@ interface Snapshot { isLoaded?: boolean; } +type ClientsList = ImmutableArray; + @Injectable() export class ClientsState extends State { public clients = @@ -60,55 +64,69 @@ export class ClientsState extends State { this.resetState(); } - return this.clientsService.getClients(this.appName).pipe( - tap(dtos => { - if (isReload) { - this.dialogs.notifyInfo('Clients reloaded.'); - } + const stream = + this.clientsService.getClients(this.appName).pipe( + map(({ version, clients }) => ({ version, clients: array(clients) })), share()); + + stream.subscribe(({ version, clients }) => { + if (isReload) { + this.dialogs.notifyInfo('Clients reloaded.'); + } - this.next(s => { - const clients = ImmutableArray.of(dtos.clients); + this.next(s => { + return { ...s, clients, isLoaded: true, version }; + }); + }); - return { ...s, clients, isLoaded: true, version: dtos.version }; - }); - }), - notify(this.dialogs)); + return stream; } - public attach(request: CreateClientDto): Observable { - return this.clientsService.postClient(this.appName, request, this.version).pipe( - tap(dto => { - this.next(s => { - const clients = s.clients.push(dto.payload); + public attach(request: CreateClientDto): Observable { + const stream = + this.clientsService.postClient(this.appName, request, this.version).pipe( + share()); + + stream.subscribe(dto => { + this.next(s => { + const clients = s.clients.push(dto.payload); + + return { ...s, clients, version: dto.version }; + }); + }); - return { ...s, clients, version: dto.version }; - }); - }), - notify(this.dialogs)); + return stream.pipe(map(x => x.payload)); } public revoke(client: ClientDto): Observable { - return this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( - tap(dto => { - this.next(s => { - const clients = s.clients.filter(c => c.id !== client.id); - - return { ...s, clients, version: dto.version }; - }); - }), - notify(this.dialogs)); + const stream = + this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( + share()); + + stream.subscribe(({ version }) => { + this.next(s => { + const clients = s.clients.filter(c => c.id !== client.id); + + return { ...s, clients, version }; + }); + }); + + return stream; } - public update(client: ClientDto, request: UpdateClientDto): Observable { - return this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( - tap(dto => { - this.next(s => { - const clients = s.clients.replaceBy('id', update(client, request)); + public update(client: ClientDto, request: UpdateClientDto): Observable { + const stream = + this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( + map(({ version }) => ({ version, client: update(client, request) })), share()); + + stream.subscribe(({ version, client }) => { + this.next(s => { + const clients = s.clients.replaceBy('id', client); + + return { ...s, clients, version }; + }); + }); - return { ...s, clients, version: dto.version }; - }); - }), - notify(this.dialogs)); + return stream.pipe(map(x => x.client)); } private get appName() { diff --git a/src/Squidex/app/shared/state/comments.state.spec.ts b/src/Squidex/app/shared/state/comments.state.spec.ts index ad1d1347d..d917b340c 100644 --- a/src/Squidex/app/shared/state/comments.state.spec.ts +++ b/src/Squidex/app/shared/state/comments.state.spec.ts @@ -45,12 +45,16 @@ describe('CommentsState', () => { commentsService = Mock.ofType(); commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) - .returns(() => of(oldComments)); + .returns(() => of(oldComments)).verifiable(Times.atLeastOnce()); commentsState = new CommentsState(appsState.object, commentsId, commentsService.object, dialogs.object); commentsState.load().subscribe(); }); + beforeEach(() => { + commentsService.verifyAll(); + }); + it('should load and merge comments', () => { const newComments = new CommentsDto([ new CommentDto('3', now, 'text3', creator) @@ -59,7 +63,7 @@ describe('CommentsState', () => { ], ['1'], new Version('2')); commentsService.setup(x => x.getComments(app, commentsId, new Version('1'))) - .returns(() => of(newComments)); + .returns(() => of(newComments)).verifiable(); commentsState.load().subscribe(); @@ -78,7 +82,7 @@ describe('CommentsState', () => { const request = { text: 'text3' }; commentsService.setup(x => x.postComment(app, commentsId, request)) - .returns(() => of(newComment)); + .returns(() => of(newComment)).verifiable(); commentsState.create('text3').subscribe(); @@ -93,28 +97,24 @@ describe('CommentsState', () => { const request = { text: 'text2_2' }; commentsService.setup(x => x.putComment(app, commentsId, '2', request)) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - commentsState.update('2', 'text2_2', now).subscribe(); + commentsState.update(oldComments.createdComments[1], 'text2_2', now).subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ new CommentDto('1', now, 'text1', creator), new CommentDto('2', now, 'text2_2', creator) ])); - - commentsService.verify(x => x.putComment(app, commentsId, '2', request), Times.once()); }); it('should remove comment from snapshot when deleted', () => { commentsService.setup(x => x.deleteComment(app, commentsId, '2')) - .returns(() => of({})); + .returns(() => of({})).verifiable(); - commentsState.delete('2').subscribe(); + commentsState.delete(oldComments.createdComments[1]).subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ new CommentDto('1', now, 'text1', creator) ])); - - commentsService.verify(x => x.deleteComment(app, commentsId, '2'), Times.once()); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/comments.state.ts b/src/Squidex/app/shared/state/comments.state.ts index fb653ad3e..6dd85841c 100644 --- a/src/Squidex/app/shared/state/comments.state.ts +++ b/src/Squidex/app/shared/state/comments.state.ts @@ -6,7 +6,7 @@ */ import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { DateTime, @@ -17,12 +17,12 @@ import { Version } from '@app/framework'; -import { CommentDto, CommentsService } from './../services/comments.service'; +import { CommentDto, CommentsDto, CommentsService } from './../services/comments.service'; import { AppsState } from './apps.state'; interface Snapshot { // The current comments. - comments: ImmutableArray; + comments: CommentsList; // The version of the comments state. version: Version; @@ -31,6 +31,8 @@ interface Snapshot { isLoaded?: boolean; } +type CommentsList = ImmutableArray; + export class CommentsState extends State { public comments = this.changes.pipe(map(x => x.comments), @@ -49,66 +51,90 @@ export class CommentsState extends State { super({ comments: ImmutableArray.empty(), version: new Version('-1') }); } - public load(): Observable { - return this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe( - tap(dtos => { - this.next(s => { - let comments = s.comments; + public load(): Observable { + const stream = + this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe( + share()); - for (let created of dtos.createdComments) { - if (!comments.find(x => x.id === created.id)) { - comments = comments.push(created); - } - } + stream.subscribe(response => { + this.next(s => { + let comments = s.comments; - for (let updated of dtos.updatedComments) { - comments = comments.replaceBy('id', updated); + for (let created of response.createdComments) { + if (!comments.find(x => x.id === created.id)) { + comments = comments.push(created); } + } - for (let deleted of dtos.deletedComments) { - comments = comments.filter(x => x.id !== deleted); - } + for (let updated of response.updatedComments) { + comments = comments.replaceBy('id', updated); + } - return { ...s, comments, isLoaded: true, version: dtos.version }; - }); - }), - notify(this.dialogs)); + for (let deleted of response.deletedComments) { + comments = comments.filter(x => x.id !== deleted); + } + + return { ...s, comments, isLoaded: true, version: response.version }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } - public create(text: string): Observable { - return this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( - tap(dto => { - this.next(s => { - const comments = s.comments.push(dto); + public create(text: string): Observable { + const stream = + this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( + share()); + + stream.subscribe(comment => { + this.next(s => { + const comments = s.comments.push(comment); - return { ...s, comments }; - }); - }), - notify(this.dialogs)); + return { ...s, comments }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } - public update(commentId: string, text: string, now?: DateTime): Observable { - return this.commentsService.putComment(this.appName, this.commentsId, commentId, { text }).pipe( - tap(() => { - this.next(s => { - const comments = s.comments.map(c => c.id === commentId ? update(c, text, now || DateTime.now()) : c); + public update(comment: CommentDto, text: string, now?: DateTime): Observable { + const stream = + this.commentsService.putComment(this.appName, this.commentsId, comment.id, { text }).pipe( + map(() => update(comment, text, now || DateTime.now())), share()); + + stream.subscribe(updated => { + this.next(s => { + const comments = s.comments.replaceBy('id', updated); + + return { ...s, comments }; + }); + }, error => { + this.dialogs.notifyError(error); + }); - return { ...s, comments }; - }); - }), - notify(this.dialogs)); + return stream; } - public delete(commentId: string): Observable { - return this.commentsService.deleteComment(this.appName, this.commentsId, commentId).pipe( - tap(() => { - this.next(s => { - const comments = s.comments.filter(c => c.id !== commentId); + public delete(comment: CommentDto): Observable { + const stream = + this.commentsService.deleteComment(this.appName, this.commentsId, comment.id).pipe( + share()); + + stream.subscribe(() => { + this.next(s => { + const comments = s.comments.removeBy('id', comment); + + return { ...s, comments }; + }); + }, error => { + this.dialogs.notifyError(error); + }); - return { ...s, comments }; - }); - }), - notify(this.dialogs)); + return stream; } private get version() { diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index 8d217321a..ab605fc01 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -9,7 +9,6 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; import { - ContributorAssignedDto, ContributorDto, ContributorsDto, ContributorsService, @@ -43,13 +42,18 @@ describe('ContributorsState', () => { dialogs = Mock.ofType(); contributorsService = Mock.ofType(); + contributorsService.setup(x => x.getContributors(app)) - .returns(() => of(new ContributorsDto(oldContributors, 3, version))); + .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(Times.atLeastOnce()); contributorsState = new ContributorsState(contributorsService.object, appsState.object, authService.object, dialogs.object); contributorsState.load().subscribe(); }); + afterEach(() => { + contributorsService.verifyAll(); + }); + it('should load contributors', () => { expect(contributorsState.snapshot.contributors.values).toEqual([ { isCurrentUser: false, contributor: oldContributors[0] }, @@ -78,7 +82,7 @@ describe('ContributorsState', () => { const response = { contributorId: newContributor.contributorId, isCreated: true }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, response))); + .returns(() => of(new Versioned(newVersion, response))).verifiable(); contributorsState.assign(request).subscribe(); @@ -99,7 +103,7 @@ describe('ContributorsState', () => { const response = { contributorId: newContributor.contributorId, isCreated: true }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, response))); + .returns(() => of(new Versioned(newVersion, response))).verifiable(); contributorsState.assign(request).subscribe(); @@ -114,7 +118,7 @@ describe('ContributorsState', () => { it('should remove contributor from snapshot when revoked', () => { contributorsService.setup(x => x.deleteContributor(app, oldContributors[0].contributorId, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); contributorsState.revoke(oldContributors[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/contributors.state.ts b/src/Squidex/app/shared/state/contributors.state.ts index 4f8dbfff9..a8b4a7873 100644 --- a/src/Squidex/app/shared/state/contributors.state.ts +++ b/src/Squidex/app/shared/state/contributors.state.ts @@ -7,13 +7,13 @@ import { Injectable } from '@angular/core'; import { Observable, throwError } from 'rxjs'; -import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators'; import { + array, DialogService, ErrorDto, ImmutableArray, - notify, State, Types, Version @@ -38,7 +38,7 @@ interface SnapshotContributor { interface Snapshot { // All loaded contributors. - contributors: ImmutableArray; + contributors: ContributorsList; // Indicates if the maximum number of contributors are reached. isMaxReached?: boolean; @@ -53,6 +53,8 @@ interface Snapshot { version: Version; } +type ContributorsList = ImmutableArray; + @Injectable() export class ContributorsState extends State { public contributors = @@ -85,49 +87,62 @@ export class ContributorsState extends State { this.resetState(); } - return this.contributorsService.getContributors(this.appName).pipe( - tap(dtos => { - if (isReload) { - this.dialogs.notifyInfo('Contributors reloaded.'); - } + const stream = + this.contributorsService.getContributors(this.appName).pipe( + map(({ contributors, ...other }) => ({ ...other, contributors: array(contributors.map(x => this.createContributor(x))) })), share()); + + stream.subscribe(({ version, contributors, maxContributors }) => { + if (isReload) { + this.dialogs.notifyInfo('Contributors reloaded.'); + } - const contributors = ImmutableArray.of(dtos.contributors.map(x => this.createContributor(x))); + this.replaceContributors(contributors, version, maxContributors); + }, error => { + this.dialogs.notifyError(error); + }); - this.replaceContributors(contributors, dtos.version, dtos.maxContributors); - }), - notify(this.dialogs)); + return stream; } public revoke(contributor: ContributorDto): Observable { - return this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( - tap(dto => { - const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId); + const stream = + this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe(share()); + + stream.subscribe(({ version }) => { + const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId); - this.replaceContributors(contributors, dto.version); - }), - notify(this.dialogs)); + this.replaceContributors(contributors, version); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream; } public assign(request: AssignContributorDto): Observable { - return this.contributorsService.postContributor(this.appName, request, this.version).pipe( - map(dto => { - const contributors = this.updateContributors(dto.payload.contributorId, request.role, dto.version); - - this.replaceContributors(contributors, dto.version); - - return dto.payload.isCreated; - }), - catchError(error => { - if (Types.is(error, ErrorDto) && error.statusCode === 404) { - return throwError(new ErrorDto(404, 'The user does not exist.')); - } else { - return throwError(error); - } - }), - notify(this.dialogs)); + const stream = + this.contributorsService.postContributor(this.appName, request, this.version).pipe( + catchError(error => { + if (Types.is(error, ErrorDto) && error.statusCode === 404) { + return throwError(new ErrorDto(404, 'The user does not exist.')); + } else { + return throwError(error); + } + }), + share()); + + stream.subscribe(({ payload, version }) => { + const contributors = this.updateContributors(payload.contributorId, request.role); + + this.replaceContributors(contributors, version); + }, error => { + this.dialogs.notifyError(error); + }); + + return stream.pipe(map(x => x.payload.isCreated)); } - private updateContributors(id: string, role: string, version: Version) { + private updateContributors(id: string, role: string) { const contributor = new ContributorDto(id, role); const contributors = this.snapshot.contributors; diff --git a/src/Squidex/app/shared/state/languages.state.spec.ts b/src/Squidex/app/shared/state/languages.state.spec.ts index 56f98080b..74b810c8c 100644 --- a/src/Squidex/app/shared/state/languages.state.spec.ts +++ b/src/Squidex/app/shared/state/languages.state.spec.ts @@ -93,7 +93,7 @@ describe('LanguagesState', () => { const newLanguage = new AppLanguageDto(languageIT.iso2Code, languageIT.englishName, false, false, []); languagesService.setup(x => x.postLanguage(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, newLanguage))); + .returns(() => of(new Versioned(newVersion, newLanguage))); languagesState.add(languageIT).subscribe(); @@ -120,7 +120,7 @@ describe('LanguagesState', () => { const request = { isMaster: true, isOptional: false, fallback: [] }; languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); languagesState.update(oldLanguages[1], request).subscribe(); @@ -144,7 +144,7 @@ describe('LanguagesState', () => { it('should remove language from snapshot when deleted', () => { languagesService.setup(x => x.deleteLanguage(app, oldLanguages[1].iso2Code, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); languagesState.remove(oldLanguages[1]).subscribe(); diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index 94863afd3..3a1a3c56b 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -69,7 +69,7 @@ describe('PatternsState', () => { const request = { ...newPattern }; patternsService.setup(x => x.postPattern(app, request, version)) - .returns(() => of(new Versioned(newVersion, newPattern))); + .returns(() => of(new Versioned(newVersion, newPattern))); patternsState.create(request).subscribe(); @@ -81,7 +81,7 @@ describe('PatternsState', () => { const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' }; patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); patternsState.update(oldPatterns[1], request).subscribe(); @@ -95,7 +95,7 @@ describe('PatternsState', () => { it('should remove pattern from snapshot when deleted', () => { patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); patternsState.delete(oldPatterns[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/plans.state.spec.ts b/src/Squidex/app/shared/state/plans.state.spec.ts index e1555e27e..485b32e24 100644 --- a/src/Squidex/app/shared/state/plans.state.spec.ts +++ b/src/Squidex/app/shared/state/plans.state.spec.ts @@ -11,7 +11,6 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { DialogService, - PlanChangedDto, PlanDto, PlansDto, PlansService, @@ -96,7 +95,7 @@ describe('PlansState', () => { const result = { redirectUri: 'http://url' }; plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, result))); + .returns(() => of(new Versioned(newVersion, result))); plansState.load().subscribe(); plansState.change('free').pipe(onErrorResumeNext()).subscribe(); @@ -113,7 +112,7 @@ describe('PlansState', () => { plansState.window = { location: {} }; plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, { redirectUri: '' }))); + .returns(() => of(new Versioned(newVersion, { redirectUri: '' }))); plansState.load().subscribe(); plansState.change('id2_yearly').pipe(onErrorResumeNext()).subscribe(); diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index ce0786c92..297eedb5e 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -70,7 +70,7 @@ describe('RolesState', () => { const request = { name: newRole.name }; rolesService.setup(x => x.postRole(app, request, version)) - .returns(() => of(new Versioned(newVersion, newRole))); + .returns(() => of(new Versioned(newVersion, newRole))); rolesState.add(request).subscribe(); @@ -82,7 +82,7 @@ describe('RolesState', () => { const request = { permissions: ['P4', 'P5'] }; rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rolesState.update(oldRoles[1], request).subscribe(); @@ -94,7 +94,7 @@ describe('RolesState', () => { it('should remove role from snapshot when deleted', () => { rolesService.setup(x => x.deleteRole(app, oldRoles[0].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rolesState.delete(oldRoles[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index 6fd8c7cbe..6292a1610 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -86,7 +86,7 @@ describe('RulesState', () => { const newAction = {}; rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(() => true), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rulesState.updateAction(oldRules[0], newAction, modified).subscribe(); @@ -100,7 +100,7 @@ describe('RulesState', () => { const newTrigger = {}; rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(() => true), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe(); @@ -112,7 +112,7 @@ describe('RulesState', () => { it('should mark as enabled and update and user info when enabled', () => { rulesService.setup(x => x.enableRule(app, oldRules[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rulesState.enable(oldRules[0], modified).subscribe(); @@ -124,7 +124,7 @@ describe('RulesState', () => { it('should mark as disabled and update and user info when disabled', () => { rulesService.setup(x => x.disableRule(app, oldRules[1].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rulesState.disable(oldRules[1], modified).subscribe(); @@ -136,7 +136,7 @@ describe('RulesState', () => { it('should remove rule from snapshot when deleted', () => { rulesService.setup(x => x.deleteRule(app, oldRules[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); rulesState.delete(oldRules[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 067b022a5..d6054d2fa 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -168,7 +168,7 @@ describe('SchemasState', () => { it('should mark published and update user info when published', () => { schemasService.setup(x => x.publishSchema(app, oldSchemas[0].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.publish(oldSchemas[0], modified).subscribe(); @@ -180,7 +180,7 @@ describe('SchemasState', () => { it('should unmark published and update user info when unpublished', () => { schemasService.setup(x => x.unpublishSchema(app, oldSchemas[1].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.unpublish(oldSchemas[1], modified).subscribe(); @@ -194,7 +194,7 @@ describe('SchemasState', () => { const category = 'my-new-category'; schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.name === category), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); @@ -211,7 +211,7 @@ describe('SchemasState', () => { it('should nmark published and update user info when published selected schema', () => { schemasService.setup(x => x.publishSchema(app, schema.name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.publish(schema, modified).subscribe(); @@ -225,7 +225,7 @@ describe('SchemasState', () => { const category = 'my-new-category'; schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.name === category), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); @@ -239,7 +239,7 @@ describe('SchemasState', () => { const request = { label: 'name2_label', hints: 'name2_hints' }; schemasService.setup(x => x.putSchema(app, schema.name, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.update(schema, request, modified).subscribe(); @@ -254,7 +254,7 @@ describe('SchemasState', () => { const request = { query: '' }; schemasService.setup(x => x.putScripts(app, schema.name, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.configureScripts(schema, request, modified).subscribe(); @@ -268,7 +268,7 @@ describe('SchemasState', () => { const request = { web: 'url' }; schemasService.setup(x => x.putPreviewUrls(app, schema.name, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.configurePreviewUrls(schema, request, modified).subscribe(); @@ -294,7 +294,7 @@ describe('SchemasState', () => { it('should remove schema from snapshot when deleted', () => { schemasService.setup(x => x.deleteSchema(app, schema.name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.delete(schema).subscribe(); @@ -308,7 +308,7 @@ describe('SchemasState', () => { const newField = new RootFieldDto(3, '3', createProperties('String'), 'invariant'); schemasService.setup(x => x.postField(app, schema.name, It.isAny(), undefined, version)) - .returns(() => of(new Versioned(newVersion, newField))); + .returns(() => of(new Versioned(newVersion, newField))); schemasState.addField(schema, request, undefined, modified).subscribe(); @@ -324,7 +324,7 @@ describe('SchemasState', () => { const newField = new NestedFieldDto(3, '3', createProperties('String'), 2); schemasService.setup(x => x.postField(app, schema.name, It.isAny(), 2, version)) - .returns(() => of(new Versioned(newVersion, newField))); + .returns(() => of(new Versioned(newVersion, newField))); schemasState.addField(schema, request, field2, modified).subscribe(); @@ -336,7 +336,7 @@ describe('SchemasState', () => { it('should remove field and update user info when field removed', () => { schemasService.setup(x => x.deleteField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.deleteField(schema, field1, modified).subscribe(); @@ -348,7 +348,7 @@ describe('SchemasState', () => { it('should remove field and update user info when nested field removed', () => { schemasService.setup(x => x.deleteField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.deleteField(schema, nested1, modified).subscribe(); @@ -360,7 +360,7 @@ describe('SchemasState', () => { it('should sort fields and update user info when fields sorted', () => { schemasService.setup(x => x.putFieldOrdering(app, schema.name, [field2.fieldId, field1.fieldId], undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.sortFields(schema, [field2, field1], undefined, modified).subscribe(); @@ -372,7 +372,7 @@ describe('SchemasState', () => { it('should sort fields and update user info when nested fields sorted', () => { schemasService.setup(x => x.putFieldOrdering(app, schema.name, [nested2.fieldId, nested1.fieldId], 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.sortFields(schema, [nested2, nested1], field2, modified).subscribe(); @@ -386,7 +386,7 @@ describe('SchemasState', () => { const request = { properties: createProperties('String') }; schemasService.setup(x => x.putField(app, schema.name, field1.fieldId, request, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.updateField(schema, field1, request, modified).subscribe(); @@ -400,7 +400,7 @@ describe('SchemasState', () => { const request = { properties: createProperties('String') }; schemasService.setup(x => x.putField(app, schema.name, nested1.fieldId, request, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.updateField(schema, nested1, request, modified).subscribe(); @@ -412,7 +412,7 @@ describe('SchemasState', () => { it('should mark field hidden and update user info when field hidden', () => { schemasService.setup(x => x.hideField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.hideField(schema, field1, modified).subscribe(); @@ -424,7 +424,7 @@ describe('SchemasState', () => { it('should mark field hidden and update user info when nested field hidden', () => { schemasService.setup(x => x.hideField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.hideField(schema, nested1, modified).subscribe(); @@ -436,7 +436,7 @@ describe('SchemasState', () => { it('should mark field disabled and update user info when field disabled', () => { schemasService.setup(x => x.disableField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.disableField(schema, field1, modified).subscribe(); @@ -448,7 +448,7 @@ describe('SchemasState', () => { it('should mark field disabled and update user info when nested disabled', () => { schemasService.setup(x => x.disableField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.disableField(schema, nested1, modified).subscribe(); @@ -460,7 +460,7 @@ describe('SchemasState', () => { it('should mark field locked and update user info when field locked', () => { schemasService.setup(x => x.lockField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.lockField(schema, field1, modified).subscribe(); @@ -472,7 +472,7 @@ describe('SchemasState', () => { it('should mark field locked and update user info when nested field locked', () => { schemasService.setup(x => x.lockField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.lockField(schema, nested1, modified).subscribe(); @@ -484,7 +484,7 @@ describe('SchemasState', () => { it('should unmark field hidden and update user info when field shown', () => { schemasService.setup(x => x.showField(app, schema.name, field2.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.showField(schema, field2, modified).subscribe(); @@ -496,7 +496,7 @@ describe('SchemasState', () => { it('should unmark field hidden and update user info when nested field shown', () => { schemasService.setup(x => x.showField(app, schema.name, nested2.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.showField(schema, nested2, modified).subscribe(); @@ -508,7 +508,7 @@ describe('SchemasState', () => { it('should unmark field disabled and update user info when field enabled', () => { schemasService.setup(x => x.enableField(app, schema.name, field2.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.enableField(schema, field2, modified).subscribe(); @@ -520,7 +520,7 @@ describe('SchemasState', () => { it('should unmark field disabled and update user info when nested field enabled', () => { schemasService.setup(x => x.enableField(app, schema.name, nested2.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); schemasState.enableField(schema, nested2, modified).subscribe(); From b9104c091023bc3c702ec8becb94a62b51584acd Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sat, 27 Apr 2019 20:18:45 +0200 Subject: [PATCH 08/20] More progress --- .../state/event-consumers.state.spec.ts | 104 ++++--- .../state/event-consumers.state.ts | 33 +-- .../administration/state/users.state.spec.ts | 254 ++++++++++-------- .../administration/state/users.state.ts | 46 ++-- .../rules/pages/rules/rules-page.component.ts | 13 +- .../pages/backups/backups-page.component.ts | 8 +- .../app/framework/utils/immutable-array.ts | 5 - .../shared/components/comments.component.ts | 6 +- .../app/shared/state/apps.state.spec.ts | 19 +- src/Squidex/app/shared/state/apps.state.ts | 107 +++++--- .../app/shared/state/backups.state.spec.ts | 100 ++++--- src/Squidex/app/shared/state/backups.state.ts | 81 +++--- .../app/shared/state/clients.state.spec.ts | 94 ++++--- src/Squidex/app/shared/state/clients.state.ts | 35 +-- .../app/shared/state/comments.state.spec.ts | 108 ++++---- .../app/shared/state/comments.state.ts | 29 +- .../shared/state/contributors.state.spec.ts | 134 ++++----- .../app/shared/state/contributors.state.ts | 28 +- .../app/shared/state/languages.state.spec.ts | 203 +++++++------- .../app/shared/state/languages.state.ts | 53 ++-- .../app/shared/state/patterns.state.spec.ts | 98 ++++--- .../app/shared/state/patterns.state.ts | 107 +++++--- .../app/shared/state/roles.state.spec.ts | 92 ++++--- src/Squidex/app/shared/state/roles.state.ts | 6 +- .../app/shared/state/rules.state.spec.ts | 154 ++++++----- src/Squidex/app/shared/state/rules.state.ts | 143 ++++++---- 26 files changed, 1156 insertions(+), 904 deletions(-) diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts index a5b6120b4..9020ad510 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts @@ -28,90 +28,88 @@ describe('EventConsumersState', () => { dialogs = Mock.ofType(); eventConsumersService = Mock.ofType(); - - eventConsumersService.setup(x => x.getEventConsumers()) - .returns(() => of(oldConsumers)).verifiable(Times.atLeastOnce()); - eventConsumersState = new EventConsumersState(dialogs.object, eventConsumersService.object); - eventConsumersState.load().subscribe(); }); afterEach(() => { eventConsumersService.verifyAll(); }); - it('should load event consumers', () => { - expect(eventConsumersState.snapshot.eventConsumers.values).toEqual(oldConsumers); - expect(eventConsumersState.snapshot.isLoaded).toBeTruthy(); + describe('Loading', () => { + it('should load event consumers', () => { + eventConsumersService.setup(x => x.getEventConsumers()) + .returns(() => of(oldConsumers)).verifiable(); - expect().nothing(); + eventConsumersState.load().subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + expect(eventConsumersState.snapshot.eventConsumers.values).toEqual(oldConsumers); + expect(eventConsumersState.snapshot.isLoaded).toBeTruthy(); - it('should show notification on load when reload is true', () => { - eventConsumersService.setup(x => x.getEventConsumers()) - .returns(() => of(oldConsumers)); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - eventConsumersState.load(true).subscribe(); + it('should show notification on load when reload is true', () => { + eventConsumersService.setup(x => x.getEventConsumers()) + .returns(() => of(oldConsumers)).verifiable(); - expect().nothing(); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + eventConsumersState.load(true).subscribe(); - it('should show notification on load error when silent is false', () => { - eventConsumersService.setup(x => x.getEventConsumers()) - .returns(() => throwError({})); + expect().nothing(); - eventConsumersState.load(true, false).pipe(onErrorResumeNext()).subscribe(); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); - expect().nothing(); + it('should show notification on load error when silent is false', () => { + eventConsumersService.setup(x => x.getEventConsumers()) + .returns(() => throwError({})).verifiable(); - dialogs.verify(x => x.notifyError(It.isAny()), Times.once()); - }); + eventConsumersState.load(true, false).pipe(onErrorResumeNext()).subscribe(); - it('should not show notification on load error when silent is true', () => { - eventConsumersService.setup(x => x.getEventConsumers()) - .returns(() => throwError({})); + expect().nothing(); - eventConsumersState.load(true, true).pipe(onErrorResumeNext()).subscribe(); + dialogs.verify(x => x.notifyError(It.isAny()), Times.once()); + }); + }); - expect().nothing(); + describe('Updates', () => { + beforeEach(() => { + eventConsumersService.setup(x => x.getEventConsumers()) + .returns(() => of(oldConsumers)).verifiable(); - dialogs.verify(x => x.notifyError(It.isAny()), Times.never()); - }); + eventConsumersState.load().subscribe(); + }); - it('should unmark as stopped when started', () => { - eventConsumersService.setup(x => x.putStart(oldConsumers[1].name)) - .returns(() => of({})).verifiable(); + it('should unmark as stopped when started', () => { + eventConsumersService.setup(x => x.putStart(oldConsumers[1].name)) + .returns(() => of({})).verifiable(); - eventConsumersState.start(oldConsumers[1]).subscribe(); + eventConsumersState.start(oldConsumers[1]).subscribe(); - const es_1 = eventConsumersState.snapshot.eventConsumers.at(1); + const es_1 = eventConsumersState.snapshot.eventConsumers.at(1); - expect(es_1.isStopped).toBeFalsy(); - }); + expect(es_1.isStopped).toBeFalsy(); + }); - it('should mark as stopped when stopped', () => { - eventConsumersService.setup(x => x.putStop(oldConsumers[0].name)) - .returns(() => of({})).verifiable(); + it('should mark as stopped when stopped', () => { + eventConsumersService.setup(x => x.putStop(oldConsumers[0].name)) + .returns(() => of({})).verifiable(); - eventConsumersState.stop(oldConsumers[0]).subscribe(); + eventConsumersState.stop(oldConsumers[0]).subscribe(); - const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); + const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); - expect(es_1.isStopped).toBeTruthy(); - }); + expect(es_1.isStopped).toBeTruthy(); + }); - it('should mark as resetting when reset', () => { - eventConsumersService.setup(x => x.putReset(oldConsumers[0].name)) - .returns(() => of({})).verifiable(); + it('should mark as resetting when reset', () => { + eventConsumersService.setup(x => x.putReset(oldConsumers[0].name)) + .returns(() => of({})).verifiable(); - eventConsumersState.reset(oldConsumers[0]).subscribe(); + eventConsumersState.reset(oldConsumers[0]).subscribe(); - const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); + const es_1 = eventConsumersState.snapshot.eventConsumers.at(0); - expect(es_1.isResetting).toBeTruthy(); + expect(es_1.isResetting).toBeTruthy(); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.ts b/src/Squidex/app/features/administration/state/event-consumers.state.ts index 5cd3e9d1d..8ca47e0e1 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.ts @@ -10,7 +10,6 @@ import { Observable } from 'rxjs'; import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { - array, DialogService, ImmutableArray, State @@ -50,15 +49,17 @@ export class EventConsumersState extends State { this.resetState(); } - const stream = + const http$ = this.eventConsumersService.getEventConsumers().pipe( - map(dtos => array(dtos)), share()); + share()); - stream.subscribe(eventConsumers => { + http$.subscribe(response => { if (isReload && !silent) { this.dialogs.notifyInfo('Event Consumers reloaded.'); } + const eventConsumers = ImmutableArray.of(response); + this.next(s => { return { ...s, eventConsumers, isLoaded: true }; }); @@ -69,41 +70,41 @@ export class EventConsumersState extends State { } }); - return stream; + return http$; } public start(eventConsumer: EventConsumerDto): Observable { - const stream = + const http$ = this.eventConsumersService.putStart(eventConsumer.name).pipe( map(() => setStopped(eventConsumer, false), share())); - this.updateState(stream); + this.updateState(http$); - return stream; + return http$; } public stop(eventConsumer: EventConsumerDto): Observable { - const stream = + const http$ = this.eventConsumersService.putStop(eventConsumer.name).pipe( map(() => setStopped(eventConsumer, true), share())); - this.updateState(stream); + this.updateState(http$); - return stream; + return http$; } public reset(eventConsumer: EventConsumerDto): Observable { - const stream = + const http$ = this.eventConsumersService.putReset(eventConsumer.name).pipe( map(() => reset(eventConsumer), share())); - this.updateState(stream); + this.updateState(http$); - return stream; + return http$; } - private updateState(stream: Observable) { - stream.subscribe(updated => { + private updateState(http$: Observable) { + http$.subscribe(updated => { this.replaceEventConsumer(updated); }, error => { this.dialogs.notifyError(error); diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts index 3d799ff27..235108d73 100644 --- a/src/Squidex/app/features/administration/state/users.state.spec.ts +++ b/src/Squidex/app/features/administration/state/users.state.spec.ts @@ -40,181 +40,199 @@ describe('UsersState', () => { dialogs = Mock.ofType(); usersService = Mock.ofType(); - - usersService.setup(x => x.getUsers(10, 0, undefined)) - .returns(() => of(new UsersDto(200, oldUsers))).verifiable(Times.atLeastOnce()); - usersState = new UsersState(authService.object, dialogs.object, usersService.object); - usersState.load().subscribe(); }); afterEach(() => { usersService.verifyAll(); }); - it('should load users', () => { - expect(usersState.snapshot.users.values).toEqual([ - { isCurrentUser: false, user: oldUsers[0] }, - { isCurrentUser: true, user: oldUsers[1] } - ]); - expect(usersState.snapshot.usersPager.numberOfItems).toEqual(200); - expect(usersState.snapshot.isLoaded).toBeTruthy(); + describe('Loading', () => { + it('should load users', () => { + usersService.setup(x => x.getUsers(10, 0, undefined)) + .returns(() => of(new UsersDto(200, oldUsers))).verifiable(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + usersState.load().subscribe(); + + expect(usersState.snapshot.users.values).toEqual([ + { isCurrentUser: false, user: oldUsers[0] }, + { isCurrentUser: true, user: oldUsers[1] } + ]); + expect(usersState.snapshot.usersPager.numberOfItems).toEqual(200); + expect(usersState.snapshot.isLoaded).toBeTruthy(); - it('should show notification on load when reload is true', () => { - usersState.load(true).subscribe(); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - expect().nothing(); + it('should show notification on load when reload is true', () => { + usersService.setup(x => x.getUsers(10, 0, undefined)) + .returns(() => of(new UsersDto(200, oldUsers))).verifiable(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + usersState.load(true).subscribe(); - it('should replace selected user when reloading', () => { - usersState.select('id1').subscribe(); + expect().nothing(); - const newUsers = [ - new UserDto('id1', 'mail1@mail.de_new', 'name1_new', ['Permission1_New'], false), - new UserDto('id2', 'mail2@mail.de_new', 'name2_new', ['Permission2_New'], true) - ]; + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); - usersService.setup(x => x.getUsers(10, 0, undefined)) - .returns(() => of(new UsersDto(200, newUsers))); + it('should replace selected user when reloading', () => { + const newUsers = [ + new UserDto('id1', 'mail1@mail.de_new', 'name1_new', ['Permission1_New'], false), + new UserDto('id2', 'mail2@mail.de_new', 'name2_new', ['Permission2_New'], true) + ]; - usersState.load().subscribe(); + usersService.setup(x => x.getUsers(10, 0, undefined)) + .returns(() => of(new UsersDto(200, oldUsers))).verifiable(Times.exactly(2)); - expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUsers[0] }); - }); + usersService.setup(x => x.getUsers(10, 0, undefined)) + .returns(() => of(new UsersDto(200, newUsers))); - it('should return user on select and not load when already loaded', () => { - let selectedUser: SnapshotUser; + usersState.load().subscribe(); + usersState.select('id1').subscribe(); + usersState.load().subscribe(); - usersState.select('id1').subscribe(x => { - selectedUser = x!; + expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUsers[0] }); }); - expect(selectedUser!.user).toEqual(oldUsers[0]); - expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: oldUsers[0] }); - }); + it('should load next page and prev page when paging', () => { + usersService.setup(x => x.getUsers(10, 0, undefined)) + .returns(() => of(new UsersDto(200, oldUsers))).verifiable(Times.exactly(2)); - it('should return user on select and load when not loaded', () => { - usersService.setup(x => x.getUser('id3')) - .returns(() => of(newUser)); + usersService.setup(x => x.getUsers(10, 10, undefined)) + .returns(() => of(new UsersDto(200, []))).verifiable(); - let selectedUser: SnapshotUser; + usersState.load().subscribe(); + usersState.goNext().subscribe(); + usersState.goPrev().subscribe(); - usersState.select('id3').subscribe(x => { - selectedUser = x!; + expect().nothing(); }); - expect(selectedUser!.user).toEqual(newUser); - expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUser }); + it('should load with query when searching', () => { + usersService.setup(x => x.getUsers(10, 0, 'my-query')) + .returns(() => of(new UsersDto(0, []))).verifiable(); + + usersState.search('my-query').subscribe(); + + expect(usersState.snapshot.usersQuery).toEqual('my-query'); + }); }); - it('should return null on select when unselecting user', () => { - let selectedUser: SnapshotUser; + describe('Updates', () => { + beforeEach(() => { + usersService.setup(x => x.getUsers(10, 0, undefined)) + .returns(() => of(new UsersDto(200, oldUsers))).verifiable(); - usersState.select(null).subscribe(x => { - selectedUser = x!; + usersState.load().subscribe(); }); - expect(selectedUser!).toBeNull(); - expect(usersState.snapshot.selectedUser).toBeNull(); - }); + it('should return user on select and not load when already loaded', () => { + let selectedUser: SnapshotUser; - it('should return null on select when user is not found', () => { - usersService.setup(x => x.getUser('unknown')) - .returns(() => throwError({})).verifiable(); + usersState.select('id1').subscribe(x => { + selectedUser = x!; + }); - let selectedUser: SnapshotUser; + expect(selectedUser!.user).toEqual(oldUsers[0]); + expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: oldUsers[0] }); + }); - usersState.select('unknown').subscribe(x => { - selectedUser = x!; - }).unsubscribe(); + it('should return user on select and load when not loaded', () => { + usersService.setup(x => x.getUser('id3')) + .returns(() => of(newUser)); - expect(selectedUser!).toBeNull(); - expect(usersState.snapshot.selectedUser).toBeNull(); - }); + let selectedUser: SnapshotUser; - it('should mark as locked when locked', () => { - usersService.setup(x => x.lockUser('id1')) - .returns(() => of({})).verifiable(); + usersState.select('id3').subscribe(x => { + selectedUser = x!; + }); - usersState.select('id1').subscribe(); - usersState.lock(oldUsers[0]).subscribe(); + expect(selectedUser!.user).toEqual(newUser); + expect(usersState.snapshot.selectedUser).toEqual({ isCurrentUser: false, user: newUser }); + }); - const user_1 = usersState.snapshot.users.at(0); + it('should return null on select when unselecting user', () => { + let selectedUser: SnapshotUser; - expect(user_1.user.isLocked).toBeTruthy(); - expect(user_1).toBe(usersState.snapshot.selectedUser!); - }); + usersState.select(null).subscribe(x => { + selectedUser = x!; + }); - it('should unmark as locked when unlocked', () => { - usersService.setup(x => x.unlockUser('id2')) - .returns(() => of({})).verifiable(); + expect(selectedUser!).toBeNull(); + expect(usersState.snapshot.selectedUser).toBeNull(); + }); - usersState.select('id2').subscribe(); - usersState.unlock(oldUsers[1]).subscribe(); + it('should return null on select when user is not found', () => { + usersService.setup(x => x.getUser('unknown')) + .returns(() => throwError({})).verifiable(); - const user_1 = usersState.snapshot.users.at(1); + let selectedUser: SnapshotUser; - expect(user_1.user.isLocked).toBeFalsy(); - expect(user_1).toBe(usersState.snapshot.selectedUser!); - }); + usersState.select('unknown').subscribe(x => { + selectedUser = x!; + }).unsubscribe(); - it('should update user properties when updated', () => { - const request = { email: 'new@mail.com', displayName: 'New', permissions: ['Permission1'] }; + expect(selectedUser!).toBeNull(); + expect(usersState.snapshot.selectedUser).toBeNull(); + }); - usersService.setup(x => x.putUser('id1', request)) - .returns(() => of({})).verifiable(); + it('should mark as locked when locked', () => { + usersService.setup(x => x.lockUser('id1')) + .returns(() => of({})).verifiable(); - usersState.select('id1').subscribe(); - usersState.update(oldUsers[0], request).subscribe(); + usersState.select('id1').subscribe(); + usersState.lock(oldUsers[0]).subscribe(); - const user_1 = usersState.snapshot.users.at(0); + const user_1 = usersState.snapshot.users.at(0); - expect(user_1.user.email).toEqual(request.email); - expect(user_1.user.displayName).toEqual(request.displayName); - expect(user_1.user.permissions).toEqual(request.permissions); - expect(user_1).toBe(usersState.snapshot.selectedUser!); - }); + expect(user_1.user.isLocked).toBeTruthy(); + expect(user_1).toBe(usersState.snapshot.selectedUser!); + }); - it('should add user to snapshot when created', () => { - const request = { ...newUser, password: 'password' }; + it('should unmark as locked when unlocked', () => { + usersService.setup(x => x.unlockUser('id2')) + .returns(() => of({})).verifiable(); - usersService.setup(x => x.postUser(request)) - .returns(() => of(newUser)).verifiable(); + usersState.select('id2').subscribe(); + usersState.unlock(oldUsers[1]).subscribe(); - usersState.create(request).subscribe(); + const user_1 = usersState.snapshot.users.at(1); - expect(usersState.snapshot.users.values).toEqual([ - { isCurrentUser: false, user: newUser }, - { isCurrentUser: false, user: oldUsers[0] }, - { isCurrentUser: true, user: oldUsers[1] } - ]); - expect(usersState.snapshot.usersPager.numberOfItems).toBe(201); - }); + expect(user_1.user.isLocked).toBeFalsy(); + expect(user_1).toBe(usersState.snapshot.selectedUser!); + }); - it('should load next page and prev page when paging', () => { - usersService.setup(x => x.getUsers(10, 10, undefined)) - .returns(() => of(new UsersDto(200, []))).verifiable(); + it('should update user properties when updated', () => { + const request = { email: 'new@mail.com', displayName: 'New', permissions: ['Permission1'] }; - usersState.goNext().subscribe(); - usersState.goPrev().subscribe(); + usersService.setup(x => x.putUser('id1', request)) + .returns(() => of({})).verifiable(); - expect().nothing(); + usersState.select('id1').subscribe(); + usersState.update(oldUsers[0], request).subscribe(); - usersService.verify(x => x.getUsers(10, 10, undefined), Times.once()); - usersService.verify(x => x.getUsers(10, 0, undefined), Times.exactly(2)); - }); + const user_1 = usersState.snapshot.users.at(0); - it('should load with query when searching', () => { - usersService.setup(x => x.getUsers(10, 0, 'my-query')) - .returns(() => of(new UsersDto(0, []))).verifiable(); + expect(user_1.user.email).toEqual(request.email); + expect(user_1.user.displayName).toEqual(request.displayName); + expect(user_1.user.permissions).toEqual(request.permissions); + expect(user_1).toBe(usersState.snapshot.selectedUser!); + }); - usersState.search('my-query').subscribe(); + it('should add user to snapshot when created', () => { + const request = { ...newUser, password: 'password' }; - expect(usersState.snapshot.usersQuery).toEqual('my-query'); + usersService.setup(x => x.postUser(request)) + .returns(() => of(newUser)).verifiable(); + + usersState.create(request).subscribe(); + + expect(usersState.snapshot.users.values).toEqual([ + { isCurrentUser: false, user: newUser }, + { isCurrentUser: false, user: oldUsers[0] }, + { isCurrentUser: true, user: oldUsers[1] } + ]); + expect(usersState.snapshot.usersPager.numberOfItems).toBe(201); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/features/administration/state/users.state.ts b/src/Squidex/app/features/administration/state/users.state.ts index 2e0e7599b..51278708e 100644 --- a/src/Squidex/app/features/administration/state/users.state.ts +++ b/src/Squidex/app/features/administration/state/users.state.ts @@ -12,7 +12,6 @@ import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators'; import '@app/framework/utils/rxjs-extensions'; import { - array, AuthService, DialogService, ImmutableArray, @@ -82,13 +81,15 @@ export class UsersState extends State { } public select(id: string | null): Observable { - const stream = this.loadUser(id).pipe(share()); + const http$ = + this.loadUser(id).pipe( + share()); - stream.subscribe(selectedUser => { + http$.subscribe(selectedUser => { this.next(s => ({ ...s, selectedUser })); }); - return stream; + return http$; } private loadUser(id: string | null) { @@ -114,20 +115,21 @@ export class UsersState extends State { } private loadInternal(isReload = false): Observable { - const stream = + const http$ = this.usersService.getUsers( this.snapshot.usersPager.pageSize, this.snapshot.usersPager.skip, this.snapshot.usersQuery).pipe( - map(({ total, items }) => ({ total, users: array(items.map(x => this.createUser(x))) })), share()); + share()); - stream.subscribe(({ total, users }) => { + http$.subscribe(response => { if (isReload) { this.dialogs.notifyInfo('Users reloaded.'); } this.next(s => { - const usersPager = s.usersPager.setCount(total); + const usersPager = s.usersPager.setCount(response.total); + const users = ImmutableArray.of(response.items.map(x => this.createUser(x))); let selectedUser = s.selectedUser; @@ -142,13 +144,15 @@ export class UsersState extends State { this.dialogs.notifyError(error); }); - return stream; + return http$; } public create(request: CreateUserDto): Observable { - const stream = this.usersService.postUser(request).pipe(share()); + const http$ = + this.usersService.postUser(request).pipe( + share()); - stream.subscribe(dto => { + http$.subscribe(dto => { this.next(s => { const users = s.users.pushFront(this.createUser(dto)); const usersPager = s.usersPager.incrementCount(); @@ -157,37 +161,37 @@ export class UsersState extends State { }); }); - return stream; + return http$; } public update(user: UserDto, request: UpdateUserDto): Observable { - const stream = + const http$ = this.usersService.putUser(user.id, request).pipe( map(() => update(user, request)), share()); - this.updateState(stream, false); + this.updateState(http$, false); - return stream; + return http$; } public lock(user: UserDto): Observable { - const stream = + const http$ = this.usersService.lockUser(user.id).pipe( map(() => setLocked(user, true)), share()); - this.updateState(stream, true); + this.updateState(http$, true); - return stream; + return http$; } public unlock(user: UserDto): Observable { - const stream = + const http$ = this.usersService.unlockUser(user.id).pipe( map(() => setLocked(user, false)), share()); - this.updateState(stream, true); + this.updateState(http$, true); - return stream; + return http$; } public search(query: string): Observable { diff --git a/src/Squidex/app/features/rules/pages/rules/rules-page.component.ts b/src/Squidex/app/features/rules/pages/rules/rules-page.component.ts index 3c21249db..ff75e7716 100644 --- a/src/Squidex/app/features/rules/pages/rules/rules-page.component.ts +++ b/src/Squidex/app/features/rules/pages/rules/rules-page.component.ts @@ -6,7 +6,6 @@ */ import { Component, OnInit } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { ALL_TRIGGERS, @@ -42,29 +41,29 @@ export class RulesPageComponent implements OnInit { } public ngOnInit() { - this.rulesState.load().pipe(onErrorResumeNext()).subscribe(); + this.rulesState.load(); this.rulesService.getActions() .subscribe(actions => { this.ruleActions = actions; }); - this.schemasState.load().pipe(onErrorResumeNext()).subscribe(); + this.schemasState.load(); } public reload() { - this.rulesState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.rulesState.load(true); } public delete(rule: RuleDto) { - this.rulesState.delete(rule).pipe(onErrorResumeNext()).subscribe(); + this.rulesState.delete(rule); } public toggle(rule: RuleDto) { if (rule.isEnabled) { - this.rulesState.disable(rule).pipe(onErrorResumeNext()).subscribe(); + this.rulesState.disable(rule); } else { - this.rulesState.enable(rule).pipe(onErrorResumeNext()).subscribe(); + this.rulesState.enable(rule); } } diff --git a/src/Squidex/app/features/settings/pages/backups/backups-page.component.ts b/src/Squidex/app/features/settings/pages/backups/backups-page.component.ts index 281c4f9e6..9a0f1b700 100644 --- a/src/Squidex/app/features/settings/pages/backups/backups-page.component.ts +++ b/src/Squidex/app/features/settings/pages/backups/backups-page.component.ts @@ -30,7 +30,7 @@ export class BackupsPageComponent extends ResourceOwner implements OnInit { } public ngOnInit() { - this.backupsState.load().pipe(onErrorResumeNext()).subscribe(); + this.backupsState.load(); this.own( timer(3000, 3000).pipe(switchMap(() => this.backupsState.load(true, true).pipe(onErrorResumeNext()))) @@ -38,15 +38,15 @@ export class BackupsPageComponent extends ResourceOwner implements OnInit { } public reload() { - this.backupsState.load(true, false).pipe(onErrorResumeNext()).subscribe(); + this.backupsState.load(true, false); } public start() { - this.backupsState.start().pipe(onErrorResumeNext()).subscribe(); + this.backupsState.start(); } public delete(backup: BackupDto) { - this.backupsState.delete(backup).pipe(onErrorResumeNext()).subscribe(); + this.backupsState.delete(backup); } public trackByBackup(index: number, item: BackupDto) { diff --git a/src/Squidex/app/framework/utils/immutable-array.ts b/src/Squidex/app/framework/utils/immutable-array.ts index ecb1a9d3f..0779e947d 100644 --- a/src/Squidex/app/framework/utils/immutable-array.ts +++ b/src/Squidex/app/framework/utils/immutable-array.ts @@ -17,11 +17,6 @@ function freeze(items: T[]): T[] { return items; } - -export function array(items?: V[]): ImmutableArray { - return ImmutableArray.of(items); -} - export class ImmutableArray implements Iterable { private static readonly EMPTY = new ImmutableArray([]); private readonly items: T[]; diff --git a/src/Squidex/app/shared/components/comments.component.ts b/src/Squidex/app/shared/components/comments.component.ts index 5fe06b302..7f02e8476 100644 --- a/src/Squidex/app/shared/components/comments.component.ts +++ b/src/Squidex/app/shared/components/comments.component.ts @@ -56,18 +56,18 @@ export class CommentsComponent extends ResourceOwner implements OnInit { } public delete(comment: CommentDto) { - this.state.delete(comment.id).pipe(onErrorResumeNext()).subscribe(); + this.state.delete(comment); } public update(comment: CommentDto, text: string) { - this.state.update(comment.id, text).pipe(onErrorResumeNext()).subscribe(); + this.state.update(comment, text); } public comment() { const value = this.commentForm.submit(); if (value) { - this.state.create(value.text).pipe(onErrorResumeNext()).subscribe(); + this.state.create(value.text); this.commentForm.submitCompleted(); } diff --git a/src/Squidex/app/shared/state/apps.state.spec.ts b/src/Squidex/app/shared/state/apps.state.spec.ts index 83eecd9ea..42b547fbd 100644 --- a/src/Squidex/app/shared/state/apps.state.spec.ts +++ b/src/Squidex/app/shared/state/apps.state.spec.ts @@ -37,13 +37,16 @@ describe('AppsState', () => { appsService = Mock.ofType(); appsService.setup(x => x.getApps()) - .returns(() => of(oldApps)) - .verifiable(Times.once()); + .returns(() => of(oldApps)).verifiable(); appsState = new AppsState(appsService.object, dialogs.object); appsState.load().subscribe(); }); + afterEach(() => { + appsService.verifyAll(); + }); + it('should load apps', () => { expect(appsState.snapshot.apps.values).toEqual(oldApps); }); @@ -53,7 +56,7 @@ describe('AppsState', () => { appsState.select(oldApps[0].name).subscribe(x => { selectedApp = x!; - }).unsubscribe(); + }); expect(selectedApp!).toBe(oldApps[0]); expect(appsState.snapshot.selectedApp).toBe(oldApps[0]); @@ -64,7 +67,7 @@ describe('AppsState', () => { appsState.select(null).subscribe(x => { selectedApp = x!; - }).unsubscribe(); + }); expect(selectedApp!).toBeNull(); expect(appsState.snapshot.selectedApp).toBeNull(); @@ -75,7 +78,7 @@ describe('AppsState', () => { appsState.select('unknown').subscribe(x => { selectedApp = x!; - }).unsubscribe(); + }); expect(selectedApp!).toBeNull(); expect(appsState.snapshot.selectedApp).toBeNull(); @@ -85,7 +88,7 @@ describe('AppsState', () => { const request = { ...newApp }; appsService.setup(x => x.postApp(request)) - .returns(() => of(newApp)); + .returns(() => of(newApp)).verifiable(); appsState.create(request).subscribe(); @@ -96,10 +99,10 @@ describe('AppsState', () => { const request = { ...newApp }; appsService.setup(x => x.postApp(request)) - .returns(() => of(newApp)); + .returns(() => of(newApp)).verifiable(); appsService.setup(x => x.deleteApp(newApp.name)) - .returns(() => of({})); + .returns(() => of({})).verifiable(); appsState.create(request).subscribe(); diff --git a/src/Squidex/app/shared/state/apps.state.ts b/src/Squidex/app/shared/state/apps.state.ts index 388825ab6..4da6f9dcd 100644 --- a/src/Squidex/app/shared/state/apps.state.ts +++ b/src/Squidex/app/shared/state/apps.state.ts @@ -7,12 +7,11 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, State } from '@app/framework'; @@ -24,12 +23,14 @@ import { interface Snapshot { // All apps, loaded once. - apps: ImmutableArray; + apps: AppsList; // The selected app. selectedApp: AppDto | null; } +type AppsList = ImmutableArray; + function sameApp(lhs: AppDto, rhs?: AppDto): boolean { return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id); } @@ -56,50 +57,78 @@ export class AppsState extends State { } public select(name: string | null): Observable { - const observable = - !name ? - of(null) : - of(this.snapshot.apps.find(x => x.name === name) || null); - - return observable.pipe( - tap(selectedApp => { - this.next(s => ({ ...s, selectedApp })); - })); + const http$ = + this.loadApp(name) + .pipe(share()); + + http$.subscribe(selectedApp => { + this.next(s => ({ ...s, selectedApp })); + }); + + return http$; + } + + private loadApp(name: string | null) { + return of(name ? this.snapshot.apps.find(x => x.name === name) || null : null); } public load(): Observable { - return this.appsService.getApps().pipe( - tap((dto: AppDto[]) => { - this.next(s => { - const apps = ImmutableArray.of(dto); - - return { ...s, apps }; - }); - })); + const http$ = + this.appsService.getApps().pipe( + share()); + + http$.subscribe(response => { + this.next(s => { + const apps = ImmutableArray.of(response).sortByStringAsc(x => x.name); + + return { ...s, apps }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } public create(request: CreateAppDto): Observable { - return this.appsService.postApp(request).pipe( - tap(dto => { - this.next(s => { - const apps = s.apps.push(dto).sortByStringAsc(x => x.name); - - return { ...s, apps }; - }); - })); - } + const http$ = + this.appsService.postApp(request).pipe( + share()); - public delete(name: string): Observable { - return this.appsService.deleteApp(name).pipe( - tap(() => { - this.next(s => { - const apps = s.apps.filter(x => x.name !== name); + http$.subscribe(app => { + this.next(s => { + const apps = s.apps.push(app).sortByStringAsc(x => x.name); - const selectedApp = s.selectedApp && s.selectedApp.name === name ? null : s.selectedApp; + return { ...s, apps }; + }); + }, error => { + this.dialogs.notifyError(error); + }); - return { ...s, apps, selectedApp }; - }); - }), - notify(this.dialogs)); + return http$; + } + + public delete(name: string): Observable { + const http$ = + this.appsService.deleteApp(name).pipe( + share()); + + http$.subscribe(() => { + this.next(s => { + const apps = s.apps.filter(x => x.name !== name); + + const selectedApp = + s.selectedApp && + s.selectedApp.name === name ? + null : + s.selectedApp; + + return { ...s, apps, selectedApp }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } } \ No newline at end of file diff --git a/src/Squidex/app/shared/state/backups.state.spec.ts b/src/Squidex/app/shared/state/backups.state.spec.ts index 46d1119b1..e5f597be0 100644 --- a/src/Squidex/app/shared/state/backups.state.spec.ts +++ b/src/Squidex/app/shared/state/backups.state.spec.ts @@ -38,70 +38,88 @@ describe('BackupsState', () => { dialogs = Mock.ofType(); backupsService = Mock.ofType(); - - backupsService.setup(x => x.getBackups(app)) - .returns(() => of(oldBackups)); - backupsState = new BackupsState(appsState.object, backupsService.object, dialogs.object); - backupsState.load().subscribe(); }); - it('should load backups', () => { - expect(backupsState.snapshot.backups.values).toEqual(oldBackups); - expect(backupsState.snapshot.isLoaded).toBeTruthy(); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + afterEach(() => { + backupsService.verifyAll(); }); - it('should show notification on load when reload is true', () => { - backupsState.load(true, false).subscribe(); + describe('Loading', () => { + it('should load backups', () => { + backupsService.setup(x => x.getBackups(app)) + .returns(() => of(oldBackups)).verifiable(); - expect().nothing(); + backupsState.load().subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + expect(backupsState.snapshot.backups.values).toEqual(oldBackups); + expect(backupsState.snapshot.isLoaded).toBeTruthy(); - it('should show notification on load error when silent is false', () => { - backupsService.setup(x => x.getBackups(app)) - .returns(() => throwError({})); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - backupsState.load(true, false).pipe(onErrorResumeNext()).subscribe(); + it('should show notification on load when reload is true', () => { + backupsService.setup(x => x.getBackups(app)) + .returns(() => of(oldBackups)).verifiable(); - expect().nothing(); + backupsState.load(true, false).subscribe(); - dialogs.verify(x => x.notifyError(It.isAny()), Times.once()); - }); + expect().nothing(); - it('should not show notification on load error when silent is true', () => { - backupsService.setup(x => x.getBackups(app)) - .returns(() => throwError({})); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); - backupsState.load(true, true).pipe(onErrorResumeNext()).subscribe(); + it('should show notification on load error when silent is false', () => { + backupsService.setup(x => x.getBackups(app)) + .returns(() => throwError({})); - expect().nothing(); + backupsState.load(true, false).pipe(onErrorResumeNext()).subscribe(); - dialogs.verify(x => x.notifyError(It.isAny()), Times.never()); - }); + expect().nothing(); + + dialogs.verify(x => x.notifyError(It.isAny()), Times.once()); + }); - it('should not add backup to snapshot', () => { - backupsService.setup(x => x.postBackup(app)) - .returns(() => of({})); + it('should not show notification on load error when silent is true', () => { + backupsService.setup(x => x.getBackups(app)) + .returns(() => throwError({})); - backupsState.start().subscribe(); + backupsState.load(true, true).pipe(onErrorResumeNext()).subscribe(); - expect(backupsState.snapshot.backups.length).toBe(2); + expect().nothing(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + dialogs.verify(x => x.notifyError(It.isAny()), Times.never()); + }); }); - it('should not remove backup from snapshot', () => { - backupsService.setup(x => x.deleteBackup(app, oldBackups[0].id)) - .returns(() => of({})); + describe('Updates', () => { + beforeEach(() => { + backupsService.setup(x => x.getBackups(app)) + .returns(() => of(oldBackups)).verifiable(); + + backupsState.load().subscribe(); + }); + + it('should not add backup to snapshot', () => { + backupsService.setup(x => x.postBackup(app)) + .returns(() => of({})).verifiable(); + + backupsState.start().subscribe(); + + expect(backupsState.snapshot.backups.length).toBe(2); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); + + it('should not remove backup from snapshot', () => { + backupsService.setup(x => x.deleteBackup(app, oldBackups[0].id)) + .returns(() => of({})).verifiable(); - backupsState.delete(oldBackups[0]).subscribe(); + backupsState.delete(oldBackups[0]).subscribe(); - expect(backupsState.snapshot.backups.length).toBe(2); + expect(backupsState.snapshot.backups.length).toBe(2); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/backups.state.ts b/src/Squidex/app/shared/state/backups.state.ts index 02f885354..dedb7054b 100644 --- a/src/Squidex/app/shared/state/backups.state.ts +++ b/src/Squidex/app/shared/state/backups.state.ts @@ -6,13 +6,12 @@ */ import { Injectable } from '@angular/core'; -import { Observable, throwError } from 'rxjs'; -import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, State } from '@app/framework'; @@ -22,12 +21,14 @@ import { BackupDto, BackupsService } from './../services/backups.service'; interface Snapshot { // The current backups. - backups: ImmutableArray; + backups: BackupsList; // Indicates if the backups are loaded. isLoaded?: boolean; } +type BackupsList = ImmutableArray; + @Injectable() export class BackupsState extends State { public backups = @@ -55,41 +56,55 @@ export class BackupsState extends State { this.resetState(); } - return this.backupsService.getBackups(this.appName).pipe( - tap(dtos => { - if (isReload && !silent) { - this.dialogs.notifyInfo('Backups reloaded.'); - } - - this.next(s => { - const backups = ImmutableArray.of(dtos); - - return { ...s, backups, isLoaded: true }; - }); - }), - catchError(error => { - if (!silent) { - this.dialogs.notifyError(error); - } - - return throwError(error); - })); + const http$ = + this.backupsService.getBackups(this.appName).pipe( + share()); + + http$.subscribe(dtos => { + if (isReload && !silent) { + this.dialogs.notifyInfo('Backups reloaded.'); + } + + this.next(s => { + const backups = ImmutableArray.of(dtos); + + return { ...s, backups, isLoaded: true }; + }); + }, error => { + if (!silent) { + this.dialogs.notifyError(error); + } + }); + + return http$; } public start(): Observable { - return this.backupsService.postBackup(this.appsState.appName).pipe( - tap(() => { - this.dialogs.notifyInfo('Backup started, it can take several minutes to complete.'); - }), - notify(this.dialogs)); + const http$ = + this.backupsService.postBackup(this.appsState.appName).pipe( + share()); + + http$.subscribe(() => { + this.dialogs.notifyInfo('Backup started, it can take several minutes to complete.'); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } public delete(backup: BackupDto): Observable { - return this.backupsService.deleteBackup(this.appsState.appName, backup.id).pipe( - tap(() => { - this.dialogs.notifyInfo('Backup is about to be deleted.'); - }), - notify(this.dialogs)); + const http$ = + this.backupsService.deleteBackup(this.appsState.appName, backup.id).pipe( + share()); + + http$.subscribe(() => { + this.dialogs.notifyInfo('Backup is about to be deleted.'); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } private get appName() { diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index ad086db0d..b16b78325 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -40,70 +40,84 @@ describe('ClientsState', () => { dialogs = Mock.ofType(); clientsService = Mock.ofType(); - - clientsService.setup(x => x.getClients(app)) - .returns(() => of(new ClientsDto(oldClients, version))).verifiable(Times.atLeastOnce()); - clientsState = new ClientsState(clientsService.object, appsState.object, dialogs.object); - clientsState.load().subscribe(); }); afterEach(() => { clientsService.verifyAll(); }); - it('should load clients', () => { - expect(clientsState.snapshot.clients.values).toEqual(oldClients); - expect(clientsState.snapshot.version).toEqual(version); - expect(clientsState.isLoaded).toBeTruthy(); + describe('Loading', () => { + it('should load clients', () => { + clientsService.setup(x => x.getClients(app)) + .returns(() => of(new ClientsDto(oldClients, version))).verifiable(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + clientsState.load().subscribe(); + + expect(clientsState.snapshot.clients.values).toEqual(oldClients); + expect(clientsState.snapshot.version).toEqual(version); + expect(clientsState.isLoaded).toBeTruthy(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - it('should show notification on load when reload is true', () => { - clientsState.load(true).subscribe(); + it('should show notification on load when reload is true', () => { + clientsService.setup(x => x.getClients(app)) + .returns(() => of(new ClientsDto(oldClients, version))).verifiable(); - expect().nothing(); + clientsState.load(true).subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + expect().nothing(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should add client to snapshot when created', () => { - const newClient = new ClientDto('id3', 'name3', 'secret3'); + describe('Updates', () => { + beforeEach(() => { + clientsService.setup(x => x.getClients(app)) + .returns(() => of(new ClientsDto(oldClients, version))).verifiable(); - const request = { id: 'id3' }; + clientsState.load().subscribe(); + }); - clientsService.setup(x => x.postClient(app, request, version)) - .returns(() => of(new Versioned(newVersion, newClient))).verifiable(); + it('should add client to snapshot when created', () => { + const newClient = new ClientDto('id3', 'name3', 'secret3'); - clientsState.attach(request).subscribe(); + const request = { id: 'id3' }; - expect(clientsState.snapshot.clients.values).toEqual([...oldClients, newClient]); - expect(clientsState.snapshot.version).toEqual(newVersion); - }); + clientsService.setup(x => x.postClient(app, request, version)) + .returns(() => of(new Versioned(newVersion, newClient))).verifiable(); - it('should update properties when updated', () => { - const request = { name: 'NewName', role: 'NewRole' }; + clientsState.attach(request).subscribe(); - clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + expect(clientsState.snapshot.clients.values).toEqual([...oldClients, newClient]); + expect(clientsState.snapshot.version).toEqual(newVersion); + }); - clientsState.update(oldClients[0], request).subscribe(); + it('should update properties when updated', () => { + const request = { name: 'NewName', role: 'NewRole' }; - const client_1 = clientsState.snapshot.clients.at(0); + clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - expect(client_1.name).toBe('NewName'); - expect(client_1.role).toBe('NewRole'); - expect(clientsState.snapshot.version).toEqual(newVersion); - }); + clientsState.update(oldClients[0], request).subscribe(); + + const client_1 = clientsState.snapshot.clients.at(0); + + expect(client_1.name).toBe('NewName'); + expect(client_1.role).toBe('NewRole'); + expect(clientsState.snapshot.version).toEqual(newVersion); + }); - it('should remove client from snapshot when revoked', () => { - clientsService.setup(x => x.deleteClient(app, oldClients[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + it('should remove client from snapshot when revoked', () => { + clientsService.setup(x => x.deleteClient(app, oldClients[0].id, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - clientsState.revoke(oldClients[0]).subscribe(); + clientsState.revoke(oldClients[0]).subscribe(); - expect(clientsState.snapshot.clients.values).toEqual([oldClients[1]]); - expect(clientsState.snapshot.version).toEqual(newVersion); + expect(clientsState.snapshot.clients.values).toEqual([oldClients[1]]); + expect(clientsState.snapshot.version).toEqual(newVersion); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/clients.state.ts b/src/Squidex/app/shared/state/clients.state.ts index 2f43ec210..c8f185f80 100644 --- a/src/Squidex/app/shared/state/clients.state.ts +++ b/src/Squidex/app/shared/state/clients.state.ts @@ -12,7 +12,6 @@ import { Observable } from 'rxjs'; import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { - array, DialogService, ImmutableArray, State, @@ -64,45 +63,47 @@ export class ClientsState extends State { this.resetState(); } - const stream = + const http$ = this.clientsService.getClients(this.appName).pipe( - map(({ version, clients }) => ({ version, clients: array(clients) })), share()); + share()); - stream.subscribe(({ version, clients }) => { + http$.subscribe(response => { if (isReload) { this.dialogs.notifyInfo('Clients reloaded.'); } + const clients = ImmutableArray.of(response.clients); + this.next(s => { - return { ...s, clients, isLoaded: true, version }; + return { ...s, clients, isLoaded: true, version: response.version }; }); }); - return stream; + return http$; } public attach(request: CreateClientDto): Observable { - const stream = + const http$ = this.clientsService.postClient(this.appName, request, this.version).pipe( share()); - stream.subscribe(dto => { + http$.subscribe(({ version, payload }) => { this.next(s => { - const clients = s.clients.push(dto.payload); + const clients = s.clients.push(payload); - return { ...s, clients, version: dto.version }; + return { ...s, clients, version: version }; }); }); - return stream.pipe(map(x => x.payload)); + return http$.pipe(map(x => x.payload)); } public revoke(client: ClientDto): Observable { - const stream = + const http$ = this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( share()); - stream.subscribe(({ version }) => { + http$.subscribe(({ version }) => { this.next(s => { const clients = s.clients.filter(c => c.id !== client.id); @@ -110,15 +111,15 @@ export class ClientsState extends State { }); }); - return stream; + return http$; } public update(client: ClientDto, request: UpdateClientDto): Observable { - const stream = + const http$ = this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( map(({ version }) => ({ version, client: update(client, request) })), share()); - stream.subscribe(({ version, client }) => { + http$.subscribe(({ version, client }) => { this.next(s => { const clients = s.clients.replaceBy('id', client); @@ -126,7 +127,7 @@ export class ClientsState extends State { }); }); - return stream.pipe(map(x => x.client)); + return http$.pipe(map(x => x.client)); } private get appName() { diff --git a/src/Squidex/app/shared/state/comments.state.spec.ts b/src/Squidex/app/shared/state/comments.state.spec.ts index d917b340c..a26d15d56 100644 --- a/src/Squidex/app/shared/state/comments.state.spec.ts +++ b/src/Squidex/app/shared/state/comments.state.spec.ts @@ -6,7 +6,7 @@ */ import { of } from 'rxjs'; -import { IMock, It, Mock, Times } from 'typemoq'; +import { IMock, Mock } from 'typemoq'; import { CommentDto, @@ -43,78 +43,86 @@ describe('CommentsState', () => { dialogs = Mock.ofType(); commentsService = Mock.ofType(); - - commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) - .returns(() => of(oldComments)).verifiable(Times.atLeastOnce()); - commentsState = new CommentsState(appsState.object, commentsId, commentsService.object, dialogs.object); - commentsState.load().subscribe(); }); beforeEach(() => { commentsService.verifyAll(); }); - it('should load and merge comments', () => { - const newComments = new CommentsDto([ - new CommentDto('3', now, 'text3', creator) - ], [ - new CommentDto('2', now, 'text2_2', creator) - ], ['1'], new Version('2')); + describe('Loading', () => { + it('should load and merge comments', () => { + const newComments = new CommentsDto([ + new CommentDto('3', now, 'text3', creator) + ], [ + new CommentDto('2', now, 'text2_2', creator) + ], ['1'], new Version('2')); - commentsService.setup(x => x.getComments(app, commentsId, new Version('1'))) - .returns(() => of(newComments)).verifiable(); + commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) + .returns(() => of(oldComments)).verifiable(); - commentsState.load().subscribe(); + commentsService.setup(x => x.getComments(app, commentsId, new Version('1'))) + .returns(() => of(newComments)).verifiable(); - expect(commentsState.snapshot.isLoaded).toBeTruthy(); - expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('2', now, 'text2_2', creator), - new CommentDto('3', now, 'text3', creator) - ])); + commentsState.load().subscribe(); + commentsState.load().subscribe(); - commentsService.verify(x => x.getComments(app, commentsId, It.isAny()), Times.exactly(2)); + expect(commentsState.snapshot.isLoaded).toBeTruthy(); + expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ + new CommentDto('2', now, 'text2_2', creator), + new CommentDto('3', now, 'text3', creator) + ])); + }); }); - it('should add comment to snapshot when created', () => { - const newComment = new CommentDto('3', now, 'text3', creator); + describe('Updates', () => { + beforeEach(() => { + commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) + .returns(() => of(oldComments)).verifiable(); - const request = { text: 'text3' }; + commentsState.load().subscribe(); + }); - commentsService.setup(x => x.postComment(app, commentsId, request)) - .returns(() => of(newComment)).verifiable(); + it('should add comment to snapshot when created', () => { + const newComment = new CommentDto('3', now, 'text3', creator); - commentsState.create('text3').subscribe(); + const request = { text: 'text3' }; - expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', creator), - new CommentDto('2', now, 'text2', creator), - new CommentDto('3', now, 'text3', creator) - ])); - }); + commentsService.setup(x => x.postComment(app, commentsId, request)) + .returns(() => of(newComment)).verifiable(); - it('should update properties when updated', () => { - const request = { text: 'text2_2' }; + commentsState.create('text3').subscribe(); - commentsService.setup(x => x.putComment(app, commentsId, '2', request)) - .returns(() => of({})).verifiable(); + expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ + new CommentDto('1', now, 'text1', creator), + new CommentDto('2', now, 'text2', creator), + new CommentDto('3', now, 'text3', creator) + ])); + }); - commentsState.update(oldComments.createdComments[1], 'text2_2', now).subscribe(); + it('should update properties when updated', () => { + const request = { text: 'text2_2' }; - expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', creator), - new CommentDto('2', now, 'text2_2', creator) - ])); - }); + commentsService.setup(x => x.putComment(app, commentsId, '2', request)) + .returns(() => of({})).verifiable(); + + commentsState.update(oldComments.createdComments[1], 'text2_2', now).subscribe(); + + expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ + new CommentDto('1', now, 'text1', creator), + new CommentDto('2', now, 'text2_2', creator) + ])); + }); - it('should remove comment from snapshot when deleted', () => { - commentsService.setup(x => x.deleteComment(app, commentsId, '2')) - .returns(() => of({})).verifiable(); + it('should remove comment from snapshot when deleted', () => { + commentsService.setup(x => x.deleteComment(app, commentsId, '2')) + .returns(() => of({})).verifiable(); - commentsState.delete(oldComments.createdComments[1]).subscribe(); + commentsState.delete(oldComments.createdComments[1]).subscribe(); - expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', creator) - ])); + expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ + new CommentDto('1', now, 'text1', creator) + ])); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/comments.state.ts b/src/Squidex/app/shared/state/comments.state.ts index 6dd85841c..d0701942c 100644 --- a/src/Squidex/app/shared/state/comments.state.ts +++ b/src/Squidex/app/shared/state/comments.state.ts @@ -12,12 +12,11 @@ import { DateTime, DialogService, ImmutableArray, - notify, State, Version } from '@app/framework'; -import { CommentDto, CommentsDto, CommentsService } from './../services/comments.service'; +import { CommentDto, CommentsService } from './../services/comments.service'; import { AppsState } from './apps.state'; interface Snapshot { @@ -51,12 +50,12 @@ export class CommentsState extends State { super({ comments: ImmutableArray.empty(), version: new Version('-1') }); } - public load(): Observable { - const stream = + public load(): Observable { + const http$ = this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe( share()); - stream.subscribe(response => { + http$.subscribe(response => { this.next(s => { let comments = s.comments; @@ -80,15 +79,15 @@ export class CommentsState extends State { this.dialogs.notifyError(error); }); - return stream; + return http$; } public create(text: string): Observable { - const stream = + const http$ = this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( share()); - stream.subscribe(comment => { + http$.subscribe(comment => { this.next(s => { const comments = s.comments.push(comment); @@ -98,15 +97,15 @@ export class CommentsState extends State { this.dialogs.notifyError(error); }); - return stream; + return http$; } public update(comment: CommentDto, text: string, now?: DateTime): Observable { - const stream = + const http$ = this.commentsService.putComment(this.appName, this.commentsId, comment.id, { text }).pipe( map(() => update(comment, text, now || DateTime.now())), share()); - stream.subscribe(updated => { + http$.subscribe(updated => { this.next(s => { const comments = s.comments.replaceBy('id', updated); @@ -116,15 +115,15 @@ export class CommentsState extends State { this.dialogs.notifyError(error); }); - return stream; + return http$; } public delete(comment: CommentDto): Observable { - const stream = + const http$ = this.commentsService.deleteComment(this.appName, this.commentsId, comment.id).pipe( share()); - stream.subscribe(() => { + http$.subscribe(() => { this.next(s => { const comments = s.comments.removeBy('id', comment); @@ -134,7 +133,7 @@ export class CommentsState extends State { this.dialogs.notifyError(error); }); - return stream; + return http$; } private get version() { diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index ab605fc01..0633cbc0c 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -42,89 +42,103 @@ describe('ContributorsState', () => { dialogs = Mock.ofType(); contributorsService = Mock.ofType(); - - contributorsService.setup(x => x.getContributors(app)) - .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(Times.atLeastOnce()); - contributorsState = new ContributorsState(contributorsService.object, appsState.object, authService.object, dialogs.object); - contributorsState.load().subscribe(); }); afterEach(() => { contributorsService.verifyAll(); }); - it('should load contributors', () => { - expect(contributorsState.snapshot.contributors.values).toEqual([ - { isCurrentUser: false, contributor: oldContributors[0] }, - { isCurrentUser: true, contributor: oldContributors[1] } - ]); - expect(contributorsState.snapshot.isMaxReached).toBeFalsy(); - expect(contributorsState.snapshot.isLoaded).toBeTruthy(); - expect(contributorsState.snapshot.maxContributors).toBe(3); - expect(contributorsState.snapshot.version).toEqual(version); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + describe('Loading', () => { + it('should load contributors', () => { + contributorsService.setup(x => x.getContributors(app)) + .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(); + + contributorsState.load().subscribe(); + + expect(contributorsState.snapshot.contributors.values).toEqual([ + { isCurrentUser: false, contributor: oldContributors[0] }, + { isCurrentUser: true, contributor: oldContributors[1] } + ]); + expect(contributorsState.snapshot.isMaxReached).toBeFalsy(); + expect(contributorsState.snapshot.isLoaded).toBeTruthy(); + expect(contributorsState.snapshot.maxContributors).toBe(3); + expect(contributorsState.snapshot.version).toEqual(version); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - it('should show notification on load when reload is true', () => { - contributorsState.load(true).subscribe(); + it('should show notification on load when reload is true', () => { + contributorsService.setup(x => x.getContributors(app)) + .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(); - expect().nothing(); + contributorsState.load(true).subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + expect().nothing(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should add contributor to snapshot when assigned', () => { - const newContributor = new ContributorDto('id3', 'Developer'); + describe('Updates', () => { + beforeEach(() => { + contributorsService.setup(x => x.getContributors(app)) + .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(); - const request = { contributorId: 'mail2stehle@gmail.com', role: newContributor.role }; - const response = { contributorId: newContributor.contributorId, isCreated: true }; + contributorsState.load().subscribe(); + }); - contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, response))).verifiable(); + it('should add contributor to snapshot when assigned', () => { + const newContributor = new ContributorDto('id3', 'Developer'); - contributorsState.assign(request).subscribe(); + const request = { contributorId: 'mail2stehle@gmail.com', role: newContributor.role }; + const response = { contributorId: newContributor.contributorId, isCreated: true }; - expect(contributorsState.snapshot.contributors.values).toEqual([ - { isCurrentUser: false, contributor: oldContributors[0] }, - { isCurrentUser: true, contributor: oldContributors[1] }, - { isCurrentUser: false, contributor: newContributor } - ]); - expect(contributorsState.snapshot.isMaxReached).toBeTruthy(); - expect(contributorsState.snapshot.maxContributors).toBe(3); - expect(contributorsState.snapshot.version).toEqual(newVersion); - }); + contributorsService.setup(x => x.postContributor(app, request, version)) + .returns(() => of(new Versioned(newVersion, response))).verifiable(); - it('should update contributor in snapshot when assigned and already added', () => { - const newContributor = new ContributorDto(userId, 'Owner'); + contributorsState.assign(request).subscribe(); - const request = { ...newContributor }; - const response = { contributorId: newContributor.contributorId, isCreated: true }; + expect(contributorsState.snapshot.contributors.values).toEqual([ + { isCurrentUser: false, contributor: oldContributors[0] }, + { isCurrentUser: true, contributor: oldContributors[1] }, + { isCurrentUser: false, contributor: newContributor } + ]); + expect(contributorsState.snapshot.isMaxReached).toBeTruthy(); + expect(contributorsState.snapshot.maxContributors).toBe(3); + expect(contributorsState.snapshot.version).toEqual(newVersion); + }); - contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, response))).verifiable(); + it('should update contributor in snapshot when assigned and already added', () => { + const newContributor = new ContributorDto(userId, 'Owner'); - contributorsState.assign(request).subscribe(); + const request = { ...newContributor }; + const response = { contributorId: newContributor.contributorId, isCreated: true }; - expect(contributorsState.snapshot.contributors.values).toEqual([ - { isCurrentUser: false, contributor: oldContributors[0] }, - { isCurrentUser: true, contributor: newContributor } - ]); - expect(contributorsState.snapshot.isMaxReached).toBeFalsy(); - expect(contributorsState.snapshot.maxContributors).toBe(3); - expect(contributorsState.snapshot.version).toEqual(newVersion); - }); + contributorsService.setup(x => x.postContributor(app, request, version)) + .returns(() => of(new Versioned(newVersion, response))).verifiable(); + + contributorsState.assign(request).subscribe(); + + expect(contributorsState.snapshot.contributors.values).toEqual([ + { isCurrentUser: false, contributor: oldContributors[0] }, + { isCurrentUser: true, contributor: newContributor } + ]); + expect(contributorsState.snapshot.isMaxReached).toBeFalsy(); + expect(contributorsState.snapshot.maxContributors).toBe(3); + expect(contributorsState.snapshot.version).toEqual(newVersion); + }); - it('should remove contributor from snapshot when revoked', () => { - contributorsService.setup(x => x.deleteContributor(app, oldContributors[0].contributorId, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + it('should remove contributor from snapshot when revoked', () => { + contributorsService.setup(x => x.deleteContributor(app, oldContributors[0].contributorId, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - contributorsState.revoke(oldContributors[0]).subscribe(); + contributorsState.revoke(oldContributors[0]).subscribe(); - expect(contributorsState.snapshot.contributors.values).toEqual([ - { isCurrentUser: true, contributor: oldContributors[1] } - ]); - expect(contributorsState.snapshot.version).toEqual(newVersion); + expect(contributorsState.snapshot.contributors.values).toEqual([ + { isCurrentUser: true, contributor: oldContributors[1] } + ]); + expect(contributorsState.snapshot.version).toEqual(newVersion); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/contributors.state.ts b/src/Squidex/app/shared/state/contributors.state.ts index a8b4a7873..3571bf1ed 100644 --- a/src/Squidex/app/shared/state/contributors.state.ts +++ b/src/Squidex/app/shared/state/contributors.state.ts @@ -10,7 +10,6 @@ import { Observable, throwError } from 'rxjs'; import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators'; import { - array, DialogService, ErrorDto, ImmutableArray, @@ -87,28 +86,31 @@ export class ContributorsState extends State { this.resetState(); } - const stream = + const http$ = this.contributorsService.getContributors(this.appName).pipe( - map(({ contributors, ...other }) => ({ ...other, contributors: array(contributors.map(x => this.createContributor(x))) })), share()); + share()); - stream.subscribe(({ version, contributors, maxContributors }) => { + http$.subscribe(response => { if (isReload) { this.dialogs.notifyInfo('Contributors reloaded.'); } - this.replaceContributors(contributors, version, maxContributors); + const contributors = ImmutableArray.of(response.contributors.map(x => this.createContributor(x))); + + this.replaceContributors(contributors, response.version, response.maxContributors); }, error => { this.dialogs.notifyError(error); }); - return stream; + return http$; } public revoke(contributor: ContributorDto): Observable { - const stream = - this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe(share()); + const http$ = + this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( + share()); - stream.subscribe(({ version }) => { + http$.subscribe(({ version }) => { const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId); this.replaceContributors(contributors, version); @@ -116,11 +118,11 @@ export class ContributorsState extends State { this.dialogs.notifyError(error); }); - return stream; + return http$; } public assign(request: AssignContributorDto): Observable { - const stream = + const http$ = this.contributorsService.postContributor(this.appName, request, this.version).pipe( catchError(error => { if (Types.is(error, ErrorDto) && error.statusCode === 404) { @@ -131,7 +133,7 @@ export class ContributorsState extends State { }), share()); - stream.subscribe(({ payload, version }) => { + http$.subscribe(({ payload, version }) => { const contributors = this.updateContributors(payload.contributorId, request.role); this.replaceContributors(contributors, version); @@ -139,7 +141,7 @@ export class ContributorsState extends State { this.dialogs.notifyError(error); }); - return stream.pipe(map(x => x.payload.isCreated)); + return http$.pipe(map(x => x.payload.isCreated)); } private updateContributors(id: string, role: string) { diff --git a/src/Squidex/app/shared/state/languages.state.spec.ts b/src/Squidex/app/shared/state/languages.state.spec.ts index 74b810c8c..4fbf63d6a 100644 --- a/src/Squidex/app/shared/state/languages.state.spec.ts +++ b/src/Squidex/app/shared/state/languages.state.spec.ts @@ -41,9 +41,9 @@ describe('LanguagesState', () => { ]; let dialogs: IMock; - let allLanguagesService: IMock; let languagesService: IMock; let languagesState: LanguagesState; + let allLanguagesService: IMock; beforeEach(() => { dialogs = Mock.ofType(); @@ -51,111 +51,126 @@ describe('LanguagesState', () => { allLanguagesService = Mock.ofType(); allLanguagesService.setup(x => x.getLanguages()) - .returns(() => of([languageDE, languageEN, languageIT, languageES])); + .returns(() => of([languageDE, languageEN, languageIT, languageES])).verifiable(); languagesService = Mock.ofType(); languagesService.setup(x => x.getLanguages(app)) - .returns(() => of(new AppLanguagesDto(oldLanguages, version))); + .returns(() => of(new AppLanguagesDto(oldLanguages, version))).verifiable(); languagesState = new LanguagesState(languagesService.object, appsState.object, dialogs.object, allLanguagesService.object); - languagesState.load().subscribe(); - }); - - it('should load languages', () => { - expect(languagesState.snapshot.languages.values).toEqual([ - { - language: oldLanguages[0], - fallbackLanguages: ImmutableArray.empty(), - fallbackLanguagesNew: ImmutableArray.of([oldLanguages[1]]) - }, { - language: oldLanguages[1], - fallbackLanguages: ImmutableArray.of([oldLanguages[0]]), - fallbackLanguagesNew: ImmutableArray.empty() - } - ]); - expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageIT, languageES]); - expect(languagesState.snapshot.isLoaded).toBeTruthy(); - expect(languagesState.snapshot.version).toEqual(version); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); }); - it('should show notification on load when reload is true', () => { - languagesState.load(true).subscribe(); - - expect().nothing(); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + afterEach(() => { + languagesService.verifyAll(); - it('should add language to snapshot when assigned', () => { - const newLanguage = new AppLanguageDto(languageIT.iso2Code, languageIT.englishName, false, false, []); - - languagesService.setup(x => x.postLanguage(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, newLanguage))); - - languagesState.add(languageIT).subscribe(); - - expect(languagesState.snapshot.languages.values).toEqual([ - { - language: oldLanguages[0], - fallbackLanguages: ImmutableArray.empty(), - fallbackLanguagesNew: ImmutableArray.of([oldLanguages[1], newLanguage]) - }, { - language: oldLanguages[1], - fallbackLanguages: ImmutableArray.of([oldLanguages[0]]), - fallbackLanguagesNew: ImmutableArray.of([newLanguage]) - }, { - language: newLanguage, - fallbackLanguages: ImmutableArray.of(), - fallbackLanguagesNew: ImmutableArray.of([oldLanguages[0], oldLanguages[1]]) - } - ]); - expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageES]); - expect(languagesState.snapshot.version).toEqual(newVersion); + allLanguagesService.verifyAll(); }); - it('should update language in snapshot when updated', () => { - const request = { isMaster: true, isOptional: false, fallback: [] }; - - languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); - - languagesState.update(oldLanguages[1], request).subscribe(); - - const newLanguage1 = AppLanguageDto.fromLanguage(languageDE, true); - const newLanguage2 = AppLanguageDto.fromLanguage(languageEN); - - expect(languagesState.snapshot.languages.values).toEqual([ - { - language: newLanguage1, - fallbackLanguages: ImmutableArray.empty(), - fallbackLanguagesNew: ImmutableArray.of([newLanguage2]) - }, { - language: newLanguage2, - fallbackLanguages: ImmutableArray.empty(), - fallbackLanguagesNew: ImmutableArray.of([newLanguage1]) - } - ]); - expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageIT, languageES]); - expect(languagesState.snapshot.version).toEqual(newVersion); + describe('Loading', () => { + it('should load languages', () => { + languagesState.load().subscribe(); + + expect(languagesState.snapshot.languages.values).toEqual([ + { + language: oldLanguages[0], + fallbackLanguages: ImmutableArray.empty(), + fallbackLanguagesNew: ImmutableArray.of([oldLanguages[1]]) + }, { + language: oldLanguages[1], + fallbackLanguages: ImmutableArray.of([oldLanguages[0]]), + fallbackLanguagesNew: ImmutableArray.empty() + } + ]); + expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageIT, languageES]); + expect(languagesState.snapshot.isLoaded).toBeTruthy(); + expect(languagesState.snapshot.version).toEqual(version); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); + + it('should show notification on load when reload is true', () => { + languagesState.load(true).subscribe(); + + expect().nothing(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should remove language from snapshot when deleted', () => { - languagesService.setup(x => x.deleteLanguage(app, oldLanguages[1].iso2Code, version)) - .returns(() => of(new Versioned(newVersion, {}))); - - languagesState.remove(oldLanguages[1]).subscribe(); - - expect(languagesState.snapshot.languages.values).toEqual([ - { - language: oldLanguages[0], - fallbackLanguages: ImmutableArray.empty(), - fallbackLanguagesNew: ImmutableArray.empty() - } - ]); - expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageDE, languageIT, languageES]); - expect(languagesState.snapshot.version).toEqual(newVersion); + describe('Updates', () => { + beforeEach(() => { + languagesState.load().subscribe(); + }); + + it('should add language to snapshot when assigned', () => { + const newLanguage = new AppLanguageDto(languageIT.iso2Code, languageIT.englishName, false, false, []); + + languagesService.setup(x => x.postLanguage(app, It.isAny(), version)) + .returns(() => of(new Versioned(newVersion, newLanguage))).verifiable(); + + languagesState.add(languageIT).subscribe(); + + expect(languagesState.snapshot.languages.values).toEqual([ + { + language: oldLanguages[0], + fallbackLanguages: ImmutableArray.empty(), + fallbackLanguagesNew: ImmutableArray.of([oldLanguages[1], newLanguage]) + }, { + language: oldLanguages[1], + fallbackLanguages: ImmutableArray.of([oldLanguages[0]]), + fallbackLanguagesNew: ImmutableArray.of([newLanguage]) + }, { + language: newLanguage, + fallbackLanguages: ImmutableArray.of(), + fallbackLanguagesNew: ImmutableArray.of([oldLanguages[0], oldLanguages[1]]) + } + ]); + expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageES]); + expect(languagesState.snapshot.version).toEqual(newVersion); + }); + + it('should update language in snapshot when updated', () => { + const request = { isMaster: true, isOptional: false, fallback: [] }; + + languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + + languagesState.update(oldLanguages[1], request).subscribe(); + + const newLanguage1 = AppLanguageDto.fromLanguage(languageDE, true); + const newLanguage2 = AppLanguageDto.fromLanguage(languageEN); + + expect(languagesState.snapshot.languages.values).toEqual([ + { + language: newLanguage1, + fallbackLanguages: ImmutableArray.empty(), + fallbackLanguagesNew: ImmutableArray.of([newLanguage2]) + }, { + language: newLanguage2, + fallbackLanguages: ImmutableArray.empty(), + fallbackLanguagesNew: ImmutableArray.of([newLanguage1]) + } + ]); + expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageIT, languageES]); + expect(languagesState.snapshot.version).toEqual(newVersion); + }); + + it('should remove language from snapshot when deleted', () => { + languagesService.setup(x => x.deleteLanguage(app, oldLanguages[1].iso2Code, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + + languagesState.remove(oldLanguages[1]).subscribe(); + + expect(languagesState.snapshot.languages.values).toEqual([ + { + language: oldLanguages[0], + fallbackLanguages: ImmutableArray.empty(), + fallbackLanguagesNew: ImmutableArray.empty() + } + ]); + expect(languagesState.snapshot.allLanguagesNew.values).toEqual([languageDE, languageIT, languageES]); + expect(languagesState.snapshot.version).toEqual(newVersion); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/languages.state.ts b/src/Squidex/app/shared/state/languages.state.ts index 74210b669..e414c5e0c 100644 --- a/src/Squidex/app/shared/state/languages.state.ts +++ b/src/Squidex/app/shared/state/languages.state.ts @@ -7,7 +7,7 @@ import { Injectable } from '@angular/core'; import { forkJoin, Observable } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, share, tap } from 'rxjs/operators'; import { DialogService, @@ -31,24 +31,24 @@ interface SnapshotLanguage { language: AppLanguageDto; // All configured fallback languages. - fallbackLanguages: ImmutableArray; + fallbackLanguages: LanguageList; // The fallback languages that have not been added yet. - fallbackLanguagesNew: ImmutableArray; + fallbackLanguagesNew: LanguageList; } interface Snapshot { // the configured languages as plan format. - plainLanguages: ImmutableArray; + plainLanguages: AppLanguagesList; // All supported languages. - allLanguages: ImmutableArray; + allLanguages: LanguageList; // The languages that have not been added yet. - allLanguagesNew: ImmutableArray; + allLanguagesNew: LanguageList; // The configured languages with extra information. - languages: ImmutableArray; + languages: LanguageResultList; // The app version. version: Version; @@ -57,6 +57,10 @@ interface Snapshot { isLoaded?: boolean; } +type AppLanguagesList = ImmutableArray; +type LanguageList = ImmutableArray; +type LanguageResultList = ImmutableArray; + @Injectable() export class LanguagesState extends State { public languages = @@ -91,22 +95,29 @@ export class LanguagesState extends State { this.resetState(); } - return forkJoin( + const http$ = + forkJoin( this.languagesService.getLanguages(), this.appLanguagesService.getLanguages(this.appName)).pipe( - map(args => { - return { allLanguages: args[0], languages: args[1] }; - }), - tap(dtos => { - if (isReload) { - this.dialogs.notifyInfo('Languages reloaded.'); - } + map(args => { + return { allLanguages: args[0], languages: args[1] }; + }), + share()); - const sorted = ImmutableArray.of(dtos.allLanguages).sortByStringAsc(x => x.englishName); + http$.subscribe(response => { + if (isReload) { + this.dialogs.notifyInfo('Languages reloaded.'); + } - this.replaceLanguages(ImmutableArray.of(dtos.languages.languages), dtos.languages.version, sorted); - }), - notify(this.dialogs)); + const sorted = ImmutableArray.of(response.allLanguages).sortByStringAsc(x => x.englishName); + + this.replaceLanguages(ImmutableArray.of(response.languages.languages), response.languages.version, sorted); + + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } public add(language: LanguageDto): Observable { @@ -147,7 +158,7 @@ export class LanguagesState extends State { notify(this.dialogs)); } - private replaceLanguages(languages: ImmutableArray, version: Version, allLanguages?: ImmutableArray) { + private replaceLanguages(languages: AppLanguagesList, version: Version, allLanguages?: LanguageList) { this.next(s => { allLanguages = allLanguages || s.allLanguages; @@ -177,7 +188,7 @@ export class LanguagesState extends State { return this.snapshot.version; } - private createLanguage(language: AppLanguageDto, languages: ImmutableArray): SnapshotLanguage { + private createLanguage(language: AppLanguageDto, languages: AppLanguagesList): SnapshotLanguage { return { language, fallbackLanguages: diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index 3a1a3c56b..d92a2db72 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -40,66 +40,84 @@ describe('PatternsState', () => { dialogs = Mock.ofType(); patternsService = Mock.ofType(); - - patternsService.setup(x => x.getPatterns(app)) - .returns(() => of(new PatternsDto(oldPatterns, version))); - patternsState = new PatternsState(patternsService.object, appsState.object, dialogs.object); - patternsState.load().subscribe(); }); - it('should load patterns', () => { - expect(patternsState.snapshot.patterns.values).toEqual(oldPatterns); - expect(patternsState.snapshot.version).toEqual(version); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + afterEach(() => { + patternsService.verifyAll(); }); - it('should show notification on load when reload is true', () => { - patternsState.load(true).subscribe(); + describe('Loading', () => { + it('should load patterns', () => { + patternsService.setup(x => x.getPatterns(app)) + .returns(() => of(new PatternsDto(oldPatterns, version))).verifiable(); - expect().nothing(); + patternsState.load().subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + expect(patternsState.snapshot.patterns.values).toEqual(oldPatterns); + expect(patternsState.snapshot.version).toEqual(version); - it('should add pattern to snapshot when created', () => { - const newPattern = new PatternDto('id3', 'name3', 'pattern3', ''); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - const request = { ...newPattern }; + it('should show notification on load when reload is true', () => { + patternsService.setup(x => x.getPatterns(app)) + .returns(() => of(new PatternsDto(oldPatterns, version))).verifiable(); - patternsService.setup(x => x.postPattern(app, request, version)) - .returns(() => of(new Versioned(newVersion, newPattern))); + patternsState.load(true).subscribe(); - patternsState.create(request).subscribe(); + expect().nothing(); - expect(patternsState.snapshot.patterns.values).toEqual([...oldPatterns, newPattern]); - expect(patternsState.snapshot.version).toEqual(newVersion); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should update properties when updated', () => { - const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' }; + describe('Updates', () => { + beforeEach(() => { + patternsService.setup(x => x.getPatterns(app)) + .returns(() => of(new PatternsDto(oldPatterns, version))).verifiable(); - patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + patternsState.load().subscribe(); + }); - patternsState.update(oldPatterns[1], request).subscribe(); + it('should add pattern to snapshot when created', () => { + const newPattern = new PatternDto('id3', 'name3', 'pattern3', ''); - const pattern_1 = patternsState.snapshot.patterns.at(1); + const request = { ...newPattern }; - expect(pattern_1.name).toBe(request.name); - expect(pattern_1.pattern).toBe(request.pattern); - expect(pattern_1.message).toBe(request.message); - expect(patternsState.snapshot.version).toEqual(newVersion); - }); + patternsService.setup(x => x.postPattern(app, request, version)) + .returns(() => of(new Versioned(newVersion, newPattern))).verifiable(); + + patternsState.create(request).subscribe(); + + expect(patternsState.snapshot.patterns.values).toEqual([...oldPatterns, newPattern]); + expect(patternsState.snapshot.version).toEqual(newVersion); + }); + + it('should update properties when updated', () => { + const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' }; + + patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + + patternsState.update(oldPatterns[1], request).subscribe(); + + const pattern_1 = patternsState.snapshot.patterns.at(1); + + expect(pattern_1.name).toBe(request.name); + expect(pattern_1.pattern).toBe(request.pattern); + expect(pattern_1.message).toBe(request.message); + expect(patternsState.snapshot.version).toEqual(newVersion); + }); - it('should remove pattern from snapshot when deleted', () => { - patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + it('should remove pattern from snapshot when deleted', () => { + patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - patternsState.delete(oldPatterns[0]).subscribe(); + patternsState.delete(oldPatterns[0]).subscribe(); - expect(patternsState.snapshot.patterns.values).toEqual([oldPatterns[1]]); - expect(patternsState.snapshot.version).toEqual(newVersion); + expect(patternsState.snapshot.patterns.values).toEqual([oldPatterns[1]]); + expect(patternsState.snapshot.version).toEqual(newVersion); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/patterns.state.ts b/src/Squidex/app/shared/state/patterns.state.ts index 4ae94204a..7206ec626 100644 --- a/src/Squidex/app/shared/state/patterns.state.ts +++ b/src/Squidex/app/shared/state/patterns.state.ts @@ -7,12 +7,11 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, State, Version } from '@app/framework'; @@ -27,7 +26,7 @@ import { interface Snapshot { // The current patterns. - patterns: ImmutableArray; + patterns: PatternsList; // The app version. version: Version; @@ -36,6 +35,8 @@ interface Snapshot { isLoaded?: boolean; } +type PatternsList = ImmutableArray; + @Injectable() export class PatternsState extends State { public patterns = @@ -59,55 +60,79 @@ export class PatternsState extends State { this.resetState(); } - return this.patternsService.getPatterns(this.appName).pipe( - tap(dtos => { - if (isReload) { - this.dialogs.notifyInfo('Patterns reloaded.'); - } + const update$ = + this.patternsService.getPatterns(this.appName).pipe( + share()); + + update$.subscribe(({ version, patterns: items }) => { + if (isReload) { + this.dialogs.notifyInfo('Patterns reloaded.'); + } + + this.next(s => { + const patterns = ImmutableArray.of(items).sortByStringAsc(x => x.name); - this.next(s => { - const patterns = ImmutableArray.of(dtos.patterns).sortByStringAsc(x => x.name); + return { ...s, patterns, isLoaded: true, version: version }; + }); + }, error => { + this.dialogs.notifyError(error); + }); - return { ...s, patterns, isLoaded: true, version: dtos.version }; - }); - }), - notify(this.dialogs)); + return update$; } - public create(request: EditPatternDto): Observable { - return this.patternsService.postPattern(this.appName, request, this.version).pipe( - tap(dto => { - this.next(s => { - const patterns = s.patterns.push(dto.payload).sortByStringAsc(x => x.name); + public create(request: EditPatternDto): Observable { + const update$ = + this.patternsService.postPattern(this.appName, request, this.version).pipe( + share()); + + update$.subscribe(({ version, payload: pattern }) => { + this.next(s => { + const patterns = s.patterns.push(pattern).sortByStringAsc(x => x.name); + + return { ...s, patterns, version: version }; + }); + }, error => { + this.dialogs.notifyError(error); + }); - return { ...s, patterns, version: dto.version }; - }); - }), - notify(this.dialogs)); + return update$.pipe(map(x => x.payload)); } - public update(pattern: PatternDto, request: EditPatternDto): Observable { - return this.patternsService.putPattern(this.appName, pattern.id, request, this.version).pipe( - tap(dto => { - this.next(s => { - const patterns = s.patterns.replaceBy('id', update(pattern, request)).sortByStringAsc(x => x.name); + public update(pattern: PatternDto, request: EditPatternDto): Observable { + const update$ = + this.patternsService.putPattern(this.appName, pattern.id, request, this.version).pipe( + map(({ version }) => ({ version, payload: update(pattern, request) })), share()); - return { ...s, patterns, version: dto.version }; - }); - }), - notify(this.dialogs)); + update$.subscribe(({ version, payload }) => { + this.next(s => { + const patterns = s.patterns.replaceBy('id', payload).sortByStringAsc(x => x.name); + + return { ...s, patterns, version: version }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return update$.pipe(map(x => x.payload)); } public delete(pattern: PatternDto): Observable { - return this.patternsService.deletePattern(this.appName, pattern.id, this.version).pipe( - tap(dto => { - this.next(s => { - const patterns = s.patterns.filter(c => c.id !== pattern.id); - - return { ...s, patterns, version: dto.version }; - }); - }), - notify(this.dialogs)); + const update$ = + this.patternsService.deletePattern(this.appName, pattern.id, this.version).pipe( + share()); + + update$.subscribe(({ version }) => { + this.next(s => { + const patterns = s.patterns.filter(c => c.id !== pattern.id); + + return { ...s, patterns, version: version }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return update$; } private get appName() { diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index 297eedb5e..f1715c2b7 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -40,65 +40,79 @@ describe('RolesState', () => { dialogs = Mock.ofType(); rolesService = Mock.ofType(); - - rolesService.setup(x => x.getRoles(app)) - .returns(() => of(new RolesDto(oldRoles, version))); - rolesState = new RolesState(rolesService.object, appsState.object, dialogs.object); - rolesState.load().subscribe(); }); - it('should load roles', () => { - expect(rolesState.snapshot.roles.values).toEqual(oldRoles); - expect(rolesState.snapshot.isLoaded).toBeTruthy(); - expect(rolesState.snapshot.version).toEqual(version); + describe('Loading', () => { + it('should load roles', () => { + rolesService.setup(x => x.getRoles(app)) + .returns(() => of(new RolesDto(oldRoles, version))).verifiable(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + rolesState.load().subscribe(); + + expect(rolesState.snapshot.roles.values).toEqual(oldRoles); + expect(rolesState.snapshot.isLoaded).toBeTruthy(); + expect(rolesState.snapshot.version).toEqual(version); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - it('should show notification on load when reload is true', () => { - rolesState.load(true).subscribe(); + it('should show notification on load when reload is true', () => { + rolesService.setup(x => x.getRoles(app)) + .returns(() => of(new RolesDto(oldRoles, version))).verifiable(); - expect().nothing(); + rolesState.load(true).subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + expect().nothing(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should add role to snapshot when added', () => { - const newRole = new RoleDto('Role3', 0, 0, ['P3']); + describe('Updates', () => { + beforeEach(() => { + rolesService.setup(x => x.getRoles(app)) + .returns(() => of(new RolesDto(oldRoles, version))); - const request = { name: newRole.name }; + rolesState.load().subscribe(); + }); - rolesService.setup(x => x.postRole(app, request, version)) - .returns(() => of(new Versioned(newVersion, newRole))); + it('should add role to snapshot when added', () => { + const newRole = new RoleDto('Role3', 0, 0, ['P3']); - rolesState.add(request).subscribe(); + const request = { name: newRole.name }; - expect(rolesState.snapshot.roles.values).toEqual([oldRoles[0], oldRoles[1], newRole]); - expect(rolesState.snapshot.version).toEqual(newVersion); - }); + rolesService.setup(x => x.postRole(app, request, version)) + .returns(() => of(new Versioned(newVersion, newRole))); - it('should update permissions when updated', () => { - const request = { permissions: ['P4', 'P5'] }; + rolesState.add(request).subscribe(); - rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(rolesState.snapshot.roles.values).toEqual([oldRoles[0], oldRoles[1], newRole]); + expect(rolesState.snapshot.version).toEqual(newVersion); + }); - rolesState.update(oldRoles[1], request).subscribe(); + it('should update permissions when updated', () => { + const request = { permissions: ['P4', 'P5'] }; - const role_1 = rolesState.snapshot.roles.at(1); + rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version)) + .returns(() => of(new Versioned(newVersion, {}))); - expect(role_1.permissions).toEqual(request.permissions); - expect(rolesState.snapshot.version).toEqual(newVersion); - }); + rolesState.update(oldRoles[1], request).subscribe(); + + const role_1 = rolesState.snapshot.roles.at(1); + + expect(role_1.permissions).toEqual(request.permissions); + expect(rolesState.snapshot.version).toEqual(newVersion); + }); - it('should remove role from snapshot when deleted', () => { - rolesService.setup(x => x.deleteRole(app, oldRoles[0].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + it('should remove role from snapshot when deleted', () => { + rolesService.setup(x => x.deleteRole(app, oldRoles[0].name, version)) + .returns(() => of(new Versioned(newVersion, {}))); - rolesState.delete(oldRoles[0]).subscribe(); + rolesState.delete(oldRoles[0]).subscribe(); - expect(rolesState.snapshot.roles.values).toEqual([oldRoles[1]]); - expect(rolesState.snapshot.version).toEqual(newVersion); + expect(rolesState.snapshot.roles.values).toEqual([oldRoles[1]]); + expect(rolesState.snapshot.version).toEqual(newVersion); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/roles.state.ts b/src/Squidex/app/shared/state/roles.state.ts index 276a5b505..cd3f36e19 100644 --- a/src/Squidex/app/shared/state/roles.state.ts +++ b/src/Squidex/app/shared/state/roles.state.ts @@ -28,7 +28,7 @@ import { interface Snapshot { // The current roles. - roles: ImmutableArray; + roles: RolesList; // The app version. version: Version; @@ -37,6 +37,8 @@ interface Snapshot { isLoaded?: boolean; } +type RolesList = ImmutableArray; + @Injectable() export class RolesState extends State { public roles = @@ -91,7 +93,7 @@ export class RolesState extends State { return this.rolesService.deleteRole(this.appName, role.name, this.version).pipe( tap(dto => { this.next(s => { - const roles = s.roles.filter(c => c.name !== role.name); + const roles = s.roles.removeBy('name', role); return { ...s, roles, version: dto.version }; }); diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index 6292a1610..025e5c4c1 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -14,7 +14,6 @@ import { DialogService, RuleDto, RulesService, - UpdateRuleDto, Versioned } from './../'; @@ -46,106 +45,125 @@ describe('RulesState', () => { dialogs = Mock.ofType(); rulesService = Mock.ofType(); - - rulesService.setup(x => x.getRules(app)) - .returns(() => of(oldRules)); - rulesState = new RulesState(appsState.object, authService.object, dialogs.object, rulesService.object); - rulesState.load().subscribe(); }); - it('should load rules', () => { - expect(rulesState.snapshot.rules.values).toEqual(oldRules); - expect(rulesState.snapshot.isLoaded).toBeTruthy(); - - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + afterEach(() => { + rulesService.verifyAll(); }); - it('should show notification on load when reload is true', () => { - rulesState.load(true).subscribe(); + describe('Loading', () => { + it('should load rules', () => { + rulesService.setup(x => x.getRules(app)) + .returns(() => of(oldRules)).verifiable(); - expect().nothing(); + rulesState.load().subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + expect(rulesState.snapshot.rules.values).toEqual(oldRules); + expect(rulesState.snapshot.isLoaded).toBeTruthy(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - it('should add rule to snapshot when created', () => { - const newRule = new RuleDto('id3', creator, creator, creation, creation, version, false, {}, 'trigger3', {}, 'action3'); + it('should show notification on load when reload is true', () => { + rulesService.setup(x => x.getRules(app)) + .returns(() => of(oldRules)).verifiable(); - const request = { action: {}, trigger: {} }; + rulesState.load(true).subscribe(); - rulesService.setup(x => x.postRule(app, request, modifier, creation)) - .returns(() => of(newRule)); + expect().nothing(); - rulesState.create(request, creation).subscribe(); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); - expect(rulesState.snapshot.rules.values).toEqual([...oldRules, newRule]); }); - it('should update action and update and user info when updated action', () => { - const newAction = {}; + describe('Updates', () => { + beforeEach(() => { + rulesService.setup(x => x.getRules(app)) + .returns(() => of(oldRules)).verifiable(); - rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(() => true), version)) - .returns(() => of(new Versioned(newVersion, {}))); + rulesState.load().subscribe(); + }); - rulesState.updateAction(oldRules[0], newAction, modified).subscribe(); + it('should add rule to snapshot when created', () => { + const newRule = new RuleDto('id3', creator, creator, creation, creation, version, false, {}, 'trigger3', {}, 'action3'); - const rule_1 = rulesState.snapshot.rules.at(0); + const request = { action: {}, trigger: {} }; - expect(rule_1.action).toBe(newAction); - expectToBeModified(rule_1); - }); + rulesService.setup(x => x.postRule(app, request, modifier, creation)) + .returns(() => of(newRule)); - it('should update trigger and update and user info when updated trigger', () => { - const newTrigger = {}; + rulesState.create(request, creation).subscribe(); - rulesService.setup(x => x.putRule(app, oldRules[0].id, It.is(() => true), version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(rulesState.snapshot.rules.values).toEqual([...oldRules, newRule]); + }); - rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe(); + it('should update action and update and user info when updated action', () => { + const newAction = {}; - const rule_1 = rulesState.snapshot.rules.at(0); + rulesService.setup(x => x.putRule(app, oldRules[0].id, It.isAny(), version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - expect(rule_1.trigger).toBe(newTrigger); - expectToBeModified(rule_1); - }); + rulesState.updateAction(oldRules[0], newAction, modified).subscribe(); - it('should mark as enabled and update and user info when enabled', () => { - rulesService.setup(x => x.enableRule(app, oldRules[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + const rule_1 = rulesState.snapshot.rules.at(0); - rulesState.enable(oldRules[0], modified).subscribe(); + expect(rule_1.action).toBe(newAction); + expectToBeModified(rule_1); + }); - const rule_1 = rulesState.snapshot.rules.at(0); + it('should update trigger and update and user info when updated trigger', () => { + const newTrigger = {}; - expect(rule_1.isEnabled).toBeTruthy(); - expectToBeModified(rule_1); - }); + rulesService.setup(x => x.putRule(app, oldRules[0].id, It.isAny(), version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - it('should mark as disabled and update and user info when disabled', () => { - rulesService.setup(x => x.disableRule(app, oldRules[1].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe(); - rulesState.disable(oldRules[1], modified).subscribe(); + const rule_1 = rulesState.snapshot.rules.at(0); - const rule_1 = rulesState.snapshot.rules.at(1); + expect(rule_1.trigger).toBe(newTrigger); + expectToBeModified(rule_1); + }); - expect(rule_1.isEnabled).toBeFalsy(); - expectToBeModified(rule_1); - }); + it('should mark as enabled and update and user info when enabled', () => { + rulesService.setup(x => x.enableRule(app, oldRules[0].id, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); - it('should remove rule from snapshot when deleted', () => { - rulesService.setup(x => x.deleteRule(app, oldRules[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + rulesState.enable(oldRules[0], modified).subscribe(); - rulesState.delete(oldRules[0]).subscribe(); + const rule_1 = rulesState.snapshot.rules.at(0); - expect(rulesState.snapshot.rules.values).toEqual([oldRules[1]]); - }); + expect(rule_1.isEnabled).toBeTruthy(); + expectToBeModified(rule_1); + }); + + it('should mark as disabled and update and user info when disabled', () => { + rulesService.setup(x => x.disableRule(app, oldRules[1].id, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + + rulesState.disable(oldRules[1], modified).subscribe(); + + const rule_1 = rulesState.snapshot.rules.at(1); + + expect(rule_1.isEnabled).toBeFalsy(); + expectToBeModified(rule_1); + }); - function expectToBeModified(rule_1: RuleDto) { - expect(rule_1.lastModified).toEqual(modified); - expect(rule_1.lastModifiedBy).toEqual(modifier); - expect(rule_1.version).toEqual(newVersion); - } + it('should remove rule from snapshot when deleted', () => { + rulesService.setup(x => x.deleteRule(app, oldRules[0].id, version)) + .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + + rulesState.delete(oldRules[0]).subscribe(); + + expect(rulesState.snapshot.rules.values).toEqual([oldRules[1]]); + }); + + function expectToBeModified(rule_1: RuleDto) { + expect(rule_1.lastModified).toEqual(modified); + expect(rule_1.lastModifiedBy).toEqual(modifier); + expect(rule_1.version).toEqual(newVersion); + } + }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/rules.state.ts b/src/Squidex/app/shared/state/rules.state.ts index 6cc19956a..5288f3c44 100644 --- a/src/Squidex/app/shared/state/rules.state.ts +++ b/src/Squidex/app/shared/state/rules.state.ts @@ -7,13 +7,12 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, share } from 'rxjs/operators'; import { DateTime, DialogService, ImmutableArray, - notify, State, Version } from '@app/framework'; @@ -29,12 +28,14 @@ import { interface Snapshot { // The current rules. - rules: ImmutableArray; + rules: RulesList; // Indicates if the rules are loaded. isLoaded?: boolean; } +type RulesList = ImmutableArray; + @Injectable() export class RulesState extends State { public rules = @@ -59,82 +60,112 @@ export class RulesState extends State { this.resetState(); } - return this.rulesService.getRules(this.appName).pipe( - tap(dtos => { - if (isReload) { - this.dialogs.notifyInfo('Rules reloaded.'); - } + const http$ = + this.rulesService.getRules(this.appName).pipe( + share()); + + http$.subscribe(response => { + if (isReload) { + this.dialogs.notifyInfo('Rules reloaded.'); + } - this.next(s => { - const rules = ImmutableArray.of(dtos); + this.next(s => { + const rules = ImmutableArray.of(response); - return { ...s, rules, isLoaded: true }; - }); - }), - notify(this.dialogs)); + return { ...s, rules, isLoaded: true }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } - public create(request: CreateRuleDto, now?: DateTime): Observable { - return this.rulesService.postRule(this.appName, request, this.user, now || DateTime.now()).pipe( - tap(dto => { - this.next(s => { - const rules = s.rules.push(dto); + public create(request: CreateRuleDto, now?: DateTime): Observable { + const http$ = + this.rulesService.postRule(this.appName, request, this.user, now || DateTime.now()).pipe( + share()); + + http$.subscribe(rule => { + this.next(s => { + const rules = s.rules.push(rule); - return { ...s, rules }; - }); - }), - notify(this.dialogs)); + return { ...s, rules }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } public delete(rule: RuleDto): Observable { - return this.rulesService.deleteRule(this.appName, rule.id, rule.version).pipe( - tap(() => { - this.next(s => { - const rules = s.rules.removeAll(x => x.id === rule.id); - - return { ...s, rules }; - }); - }), - notify(this.dialogs)); + const http$ = + this.rulesService.deleteRule(this.appName, rule.id, rule.version).pipe( + share()); + + http$.subscribe(() => { + this.next(s => { + const rules = s.rules.removeAll(x => x.id === rule.id); + + return { ...s, rules }; + }); + }, error => { + this.dialogs.notifyError(error); + }); + + return http$; } public updateAction(rule: RuleDto, action: any, now?: DateTime): Observable { - return this.rulesService.putRule(this.appName, rule.id, { action }, rule.version).pipe( - tap(dto => { - this.replaceRule(updateAction(rule, action, this.user, dto.version, now)); - }), - notify(this.dialogs)); + const http$ = + this.rulesService.putRule(this.appName, rule.id, { action }, rule.version).pipe( + map(({ version }) => updateAction(rule, action, this.user, version, now)), share()); + + this.replaceRule(http$); + + return http$; } public updateTrigger(rule: RuleDto, trigger: any, now?: DateTime): Observable { - return this.rulesService.putRule(this.appName, rule.id, { trigger }, rule.version).pipe( - tap(dto => { - this.replaceRule(updateTrigger(rule, trigger, this.user, dto.version, now)); - }), - notify(this.dialogs)); + const http$ = + this.rulesService.putRule(this.appName, rule.id, { trigger }, rule.version).pipe( + map(({ version }) => updateTrigger(rule, trigger, this.user, version, now)), share()); + + this.replaceRule(http$); + + return http$; } public enable(rule: RuleDto, now?: DateTime): Observable { - return this.rulesService.enableRule(this.appName, rule.id, rule.version).pipe( - tap(dto => { - this.replaceRule(setEnabled(rule, true, this.user, dto.version, now)); - }), - notify(this.dialogs)); + const http$ = + this.rulesService.enableRule(this.appName, rule.id, rule.version).pipe( + map(({ version }) => setEnabled(rule, true, this.user, version, now)), share()); + + this.replaceRule(http$); + + return http$; } public disable(rule: RuleDto, now?: DateTime): Observable { - return this.rulesService.disableRule(this.appName, rule.id, rule.version).pipe( - tap(dto => { - this.replaceRule(setEnabled(rule, false, this.user, dto.version, now)); - }), - notify(this.dialogs)); + const http$ = + this.rulesService.disableRule(this.appName, rule.id, rule.version).pipe( + map(({ version }) => setEnabled(rule, false, this.user, version, now)), share()); + + this.replaceRule(http$); + + return http$; } - private replaceRule(rule: RuleDto) { - this.next(s => { - const rules = s.rules.replaceBy('id', rule); + private replaceRule(http$: Observable) { + http$.subscribe(rule => { + this.next(s => { + const rules = s.rules.replaceBy('id', rule); - return { ...s, rules }; + return { ...s, rules }; + }); + }, error => { + this.dialogs.notifyError(error); }); } From d24d4961bd3c5b3fc0ecd4ec8b4095b1d1d624af Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 28 Apr 2019 10:40:20 +0200 Subject: [PATCH 09/20] T --- .../shared/components/asset.component.html | 20 +- .../app/shared/components/asset.component.ts | 91 +++++++- .../app/shared/state/assets.state.spec.ts | 14 +- src/Squidex/app/shared/state/assets.state.ts | 194 +----------------- 4 files changed, 111 insertions(+), 208 deletions(-) diff --git a/src/Squidex/app/shared/components/asset.component.html b/src/Squidex/app/shared/components/asset.component.html index 9045a0e5d..bb466fb5c 100644 --- a/src/Squidex/app/shared/components/asset.component.html +++ b/src/Squidex/app/shared/components/asset.component.html @@ -1,7 +1,7 @@
-
+
{{asset.fileType}} @@ -46,11 +46,11 @@
-
- +
+
-
+
Drop to update
@@ -77,14 +77,14 @@
-
+
-
+
- +
@@ -113,11 +113,11 @@
-
- +
+
-
+
Drop to update
diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 30fdd6eae..6550d3bda 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -5,15 +5,26 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnInit, Output } from '@angular/core'; import { + AppsState, AssetDto, + AssetsService, + AuthService, + DateTime, DialogModel, + DialogService, fadeAnimation, - UploadingAsset + StatefulComponent, + Types, + Versioned } from '@app/shared/internal'; +interface State { + progress: number; +} + @Component({ selector: 'sqx-asset', styleUrls: ['./asset.component.scss'], @@ -23,9 +34,9 @@ import { ], changeDetection: ChangeDetectionStrategy.OnPush }) -export class AssetComponent { +export class AssetComponent extends StatefulComponent implements OnInit { @Input() - public upload: UploadingAsset; + public initFile: File; @Input() public asset: AssetDto; @@ -52,13 +63,16 @@ export class AssetComponent { public allTags: string[]; @Output() - public remove = new EventEmitter(); + public load = new EventEmitter(); @Output() - public update = new EventEmitter(); + public loadError = new EventEmitter(); @Output() - public uploadFile = new EventEmitter(); + public remove = new EventEmitter(); + + @Output() + public update = new EventEmitter(); @Output() public delete = new EventEmitter(); @@ -68,9 +82,54 @@ export class AssetComponent { public editDialog = new DialogModel(); - public updateFile(files: File[]) { + constructor(changeDetector: ChangeDetectorRef, + private readonly appsState: AppsState, + private readonly assetsService: AssetsService, + private readonly authState: AuthService, + private readonly dialogs: DialogService + ) { + super(changeDetector, { + progress: 0 + }); + } + + public ngOnInit() { + const initFile = this.initFile; + + if (initFile) { + this.setProgress(1); + + this.assetsService.uploadFile(this.appsState.appName, initFile, this.authState.user!.token, DateTime.now()) + .subscribe(dto => { + if (Types.is(dto, AssetDto)) { + this.emitLoad(dto); + } else { + this.setProgress(dto); + } + }, error => { + this.dialogs.notifyError(error); + + this.emitLoadError(error); + }); + } + } + + public updateFile(files: FileList) { if (files.length === 1) { - this.uploadFile.emit(files[0]); + this.setProgress(1); + + this.assetsService.replaceFile(this.appsState.appName, this.asset.id, files[0], this.asset.version) + .subscribe(dto => { + if (Types.is(dto, Versioned)) { + this.updateAsset(this.asset.update(dto.payload, this.authState.user!.token, dto.version), true); + } else { + this.setProgress(dto); + } + }, error => { + this.dialogs.notifyError(error); + + this.setProgress(0); + }); } } @@ -92,6 +151,14 @@ export class AssetComponent { this.delete.emit(this.asset); } + public emitLoad(asset: AssetDto) { + this.load.emit(asset); + } + + public emitLoadError(error: any) { + this.loadError.emit(error); + } + public emitUpdate() { this.update.emit(this.asset); } @@ -100,6 +167,10 @@ export class AssetComponent { this.remove.emit(this.asset); } + private setProgress(progress: number) { + this.next(s => ({ ...s, progress })); + } + public updateAsset(asset: AssetDto, emitEvent: boolean) { this.asset = asset; @@ -107,6 +178,8 @@ export class AssetComponent { this.emitUpdate(); } + this.next(s => ({ ...s, progress: 0 })); + this.cancelEdit(); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index b69927318..702954a2f 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -23,7 +23,6 @@ describe('AssetsState', () => { const { app, appsState, - authService, creation, creator, modified, @@ -52,7 +51,7 @@ describe('AssetsState', () => { assetsService.setup(x => x.getTags(app)) .returns(() => of({ tag1: 1, shared: 2, tag2: 1 })); - assetsState = new AssetsState(appsState.object, assetsService.object, authService.object, dialogs.object); + assetsState = new AssetsState(appsState.object, assetsService.object, dialogs.object); assetsState.load().subscribe(); }); @@ -77,6 +76,15 @@ describe('AssetsState', () => { dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); }); + it('should add asset to snapshot when created', () => { + const newAsset = new AssetDto('id3', creator, creator, creation, creation, 'name3', 'hash3', 'type3', 3, 3, 'mime3', false, true, 0, 0, 'slug2', [], 'url3', version); + + assetsState.add(newAsset); + + expect(assetsState.snapshot.assets.values).toEqual([newAsset, ...oldAssets]); + expect(assetsState.snapshot.assetsPager.numberOfItems).toBe(201); + }); + it('should update properties when updated', () => { const newAsset = new AssetDto('id1', modifier, modifier, modified, modified, 'name3', 'hash3', 'type3', 3, 3, 'mime3', false, true, 0, 0, 'slug3', ['new'], 'url3', version); @@ -90,7 +98,7 @@ describe('AssetsState', () => { it('should remove asset from snapshot when deleted', () => { assetsService.setup(x => x.deleteAsset(app, oldAssets[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(new Versioned(newVersion, {}))); assetsState.delete(oldAssets[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/assets.state.ts b/src/Squidex/app/shared/state/assets.state.ts index 5186a5e6d..5c6fb58cd 100644 --- a/src/Squidex/app/shared/state/assets.state.ts +++ b/src/Squidex/app/shared/state/assets.state.ts @@ -6,49 +6,20 @@ */ import { Injectable } from '@angular/core'; -import { combineLatest, Observable, Subject, Subscription } from 'rxjs'; +import { combineLatest, Observable } from 'rxjs'; import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { - DateTime, DialogService, ImmutableArray, - MathHelper, notify, Pager, - State, - Types + State } from '@app/framework'; -import { AuthService } from '../services/auth.service'; -import { AssetDto, AssetsService } from './../services/assets.service'; +import { AssetDto, AssetsService} from './../services/assets.service'; import { AppsState } from './apps.state'; -export interface UploadingAsset { - // Unique id. - id: string; - - // The name of the asset. - name: string; - - // The upload subscription. - subscription: Subscription; - - // The progress. - progress: number; - - // Indicates if the upload has been completed. - isCompleted?: boolean; -} - -export interface AssetWithUpload { - // The asset. - asset: AssetDto; - - // The corresponding upload. - upload?: UploadingAsset; -} - interface Snapshot { // All assets tags. tags: { [name: string]: number }; @@ -56,12 +27,6 @@ interface Snapshot { // The selected asset tags. tagsSelected: { [name: string]: boolean }; - // The uploads. - uploadsDirect: ImmutableArray; - - // The uploads removed with a delay. - uploadsDelayed: ImmutableArray; - // The current assets. assets: ImmutableArray; @@ -93,10 +58,6 @@ export class AssetsState extends State { this.changes.pipe(map(x => x.assets), distinctUntilChanged()); - public assetsWithUploads = - this.changes.pipe(map(x => getAssetsWithUploads(x)), - distinctUntilChanged()); - public assetsQuery = this.changes.pipe(map(x => x.assetsQuery), distinctUntilChanged()); @@ -105,14 +66,6 @@ export class AssetsState extends State { this.changes.pipe(map(x => x.assetsPager), distinctUntilChanged()); - public uploads = - this.changes.pipe(map(x => x.uploadsDirect), - distinctUntilChanged()); - - public uploadsDelayed = - this.changes.pipe(map(x => x.uploadsDelayed), - distinctUntilChanged()); - public isLoaded = this.changes.pipe(map(x => !!x.isLoaded), distinctUntilChanged()); @@ -120,17 +73,9 @@ export class AssetsState extends State { constructor( private readonly appsState: AppsState, private readonly assetsService: AssetsService, - private readonly authService: AuthService, private readonly dialogs: DialogService ) { - super({ - assets: ImmutableArray.empty(), - assetsPager: new Pager(0, 0, 30), - uploadsDirect: ImmutableArray.empty(), - uploadsDelayed: ImmutableArray.empty(), - tags: {}, - tagsSelected: {} - }); + super({ assets: ImmutableArray.empty(), assetsPager: new Pager(0, 0, 30), tags: {}, tagsSelected: {} }); } public load(isReload = false): Observable { @@ -165,100 +110,6 @@ export class AssetsState extends State { notify(this.dialogs)); } - public remove(upload: UploadingAsset, delayed = false) { - upload.subscription.unsubscribe(); - - this.next(s => { - let uploadsDirect = s.uploadsDirect.removeBy('id', upload); - let uploadsDelayed = s.uploadsDelayed; - - if (!delayed) { - uploadsDelayed = s.uploadsDelayed.removeBy('id', upload); - } - - return { ...s, uploadsDirect, uploadsDelayed }; - }); - - if (!delayed) { - setTimeout(() => { - this.remove(upload, true); - }, 10000); - } - } - - public upload(file: File, now?: DateTime): Observable { - const observable = this.assetsService.uploadFile(this.appName, file, this.user, now || DateTime.now()); - - let upload: UploadingAsset; - - const subject = new Subject(); - const subscription = observable.subscribe(event => { - if (Types.isNumber(event)) { - this.setProgress(upload, event); - - subject.next(event); - } else { - if (event.isDuplicate) { - this.dialogs.notifyError('The same asset has already been uploaded.'); - } else { - this.add(event); - } - - subject.next(event); - } - - }, error => { - subject.error(error); - - this.remove(upload, true); - }, () => { - subject.complete(); - - this.remove(upload, true); - }); - - upload = { id: MathHelper.guid(), name: file.name, progress: 0, subscription }; - - this.addUpload(upload); - - return subject; - } - - public replaceFile(asset: AssetDto, file: File, now?: DateTime): Observable { - const observable = this.assetsService.replaceFile(this.appName, asset.id, file, asset.version); - - let upload: UploadingAsset; - - const subject = new Subject(); - const subscription = observable.subscribe(event => { - if (Types.isNumber(event)) { - this.setProgress(upload, event); - - subject.next(event); - } else { - const newAsset = asset.update(event.payload, this.user, event.version, now || DateTime.now()); - - this.update(newAsset); - - subject.next(newAsset); - } - }, error => { - subject.error(error); - - this.remove(upload, true); - }, () => { - subject.complete(); - - this.remove(upload, true); - }); - - upload = { id: asset.id, name: file.name, progress: 0, subscription }; - - this.addUpload(upload); - - return subject; - } - public add(asset: AssetDto) { this.next(s => { const assets = s.assets.pushFront(asset); @@ -373,41 +224,9 @@ export class AssetsState extends State { return Object.keys(this.snapshot.tagsSelected).length === 0; } - private setProgress(upload: UploadingAsset, progress: number) { - this.next(s => { - const newUpload = { ...upload, progress }; - - const uploadsDirect = s.uploadsDirect.replaceBy('id', newUpload); - const uploadsDelayed = s.uploadsDelayed.replaceBy('id', newUpload); - - return { ...s, uploadsDirect, uploadsDelayed }; - }); - } - - private addUpload(upload: UploadingAsset) { - this.next(s => { - const uploadsDirect = s.uploadsDirect.pushFront(upload); - const uploadsDelayed = s.uploadsDelayed.pushFront(upload); - - return { ...s, uploadsDirect, uploadsDelayed }; - }); - } - private get appName() { return this.appsState.appName; } - - private get user() { - return this.authService.user!.token; - } -} - -function getAssetsWithUploads(state: Snapshot) { - return state.assets.map(asset => { - const upload = state.uploadsDirect.find(x => x.id === x.id); - - return { upload, asset }; - }); } function addTags(asset: AssetDto, tags: { [x: string]: number; }) { @@ -443,4 +262,7 @@ function sort(tags: { [name: string]: number }) { }).map(key => { return { name: key, count: tags[key] }; }); -} \ No newline at end of file +} + +@Injectable() +export class AssetsDialogState extends AssetsState { } \ No newline at end of file From d8628ccb5cabad8c312320d311873ad49ab43058 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 28 Apr 2019 16:05:29 +0200 Subject: [PATCH 10/20] Continued --- src/Squidex/.vscode/settings.json | 12 +- src/Squidex/app-config/webpack.config.js | 2 +- .../app-config/webpack.test.coverage.js | 4 +- .../pages/restore/restore-page.component.html | 2 +- .../pages/restore/restore-page.component.ts | 25 +- .../services/event-consumers.service.ts | 11 +- .../administration/services/users.service.ts | 35 +- .../state/event-consumers.state.ts | 83 +- .../administration/state/users.state.ts | 139 +- .../pages/assets-filters-page.component.ts | 9 +- .../assets/pages/assets-page.component.ts | 15 +- .../content/content-history-page.component.ts | 5 +- .../pages/content/content-page.component.ts | 2 +- .../contents-filters-page.component.ts | 3 +- .../pages/contents/contents-page.component.ts | 18 +- .../pages/schemas/schemas-page.component.ts | 3 +- .../shared/contents-selector.component.ts | 11 +- .../events/rule-events-page.component.ts | 13 +- .../schemas/pages/schema/field.component.ts | 13 +- .../pages/schema/schema-page.component.ts | 3 +- .../pages/schemas/schemas-page.component.ts | 4 +- .../pages/languages/language.component.ts | 3 +- .../languages/languages-page.component.ts | 5 +- .../pages/patterns/pattern.component.ts | 3 +- .../pages/patterns/patterns-page.component.ts | 5 +- .../pages/plans/plans-page.component.ts | 7 +- .../settings/pages/roles/role.component.ts | 3 +- .../pages/roles/roles-page.component.ts | 5 +- .../framework/angular/http/http-extensions.ts | 2 +- .../app/framework/utils/rxjs-extensions.ts | 59 +- .../app/framework/utils/version.spec.ts | 11 +- src/Squidex/app/framework/utils/version.ts | 12 +- .../components/asset-uploader.component.ts | 17 +- .../app/shared/components/asset.component.ts | 15 +- .../components/assets-list.component.ts | 25 +- .../components/assets-selector.component.ts | 9 +- .../shared/components/history.component.ts | 7 +- .../components/schema-category.component.ts | 3 +- .../services/app-languages.service.spec.ts | 8 +- .../shared/services/app-languages.service.ts | 31 +- .../app/shared/services/apps.service.ts | 30 +- .../app/shared/services/assets.service.ts | 22 +- .../app/shared/services/backups.service.ts | 27 +- .../shared/services/clients.service.spec.ts | 8 +- .../app/shared/services/clients.service.ts | 31 +- .../app/shared/services/comments.service.ts | 24 +- .../app/shared/services/contents.service.ts | 50 +- .../services/contributors.service.spec.ts | 15 +- .../shared/services/contributors.service.ts | 38 +- .../app/shared/services/history.service.ts | 11 +- .../app/shared/services/languages.service.ts | 21 +- .../app/shared/services/news.service.ts | 20 +- .../shared/services/patterns.service.spec.ts | 10 +- .../app/shared/services/patterns.service.ts | 34 +- .../app/shared/services/plans.service.spec.ts | 21 +- .../app/shared/services/plans.service.ts | 51 +- .../app/shared/services/roles.service.spec.ts | 7 +- .../app/shared/services/roles.service.ts | 29 +- .../app/shared/services/rules.service.ts | 42 +- .../app/shared/services/schemas.service.ts | 36 +- .../shared/services/translations.service.ts | 4 +- .../app/shared/services/usages.service.ts | 39 +- .../app/shared/services/users.service.ts | 21 +- .../app/shared/state/apps.state.spec.ts | 20 +- src/Squidex/app/shared/state/apps.state.ts | 109 +- .../app/shared/state/assets.state.spec.ts | 4 +- src/Squidex/app/shared/state/assets.state.ts | 6 +- src/Squidex/app/shared/state/backups.state.ts | 65 +- .../app/shared/state/clients.state.spec.ts | 15 +- src/Squidex/app/shared/state/clients.state.ts | 97 +- .../app/shared/state/comments.state.ts | 124 +- .../app/shared/state/contents.state.ts | 19 +- .../shared/state/contributors.state.spec.ts | 15 +- .../app/shared/state/contributors.state.ts | 79 +- .../app/shared/state/languages.state.spec.ts | 11 +- .../app/shared/state/languages.state.ts | 63 +- .../app/shared/state/patterns.state.spec.ts | 15 +- .../app/shared/state/patterns.state.ts | 105 +- .../app/shared/state/plans.state.spec.ts | 147 +- src/Squidex/app/shared/state/plans.state.ts | 18 +- .../app/shared/state/roles.state.spec.ts | 15 +- src/Squidex/app/shared/state/roles.state.ts | 40 +- .../app/shared/state/rule-events.state.ts | 8 +- .../app/shared/state/rules.state.spec.ts | 12 +- src/Squidex/app/shared/state/rules.state.ts | 143 +- .../app/shared/state/schemas.state.spec.ts | 630 +- src/Squidex/app/shared/state/schemas.state.ts | 179 +- src/Squidex/package-lock.json | 10700 ++++++++++------ src/Squidex/package.json | 93 +- src/Squidex/tsconfig.json | 8 +- 90 files changed, 8524 insertions(+), 5449 deletions(-) diff --git a/src/Squidex/.vscode/settings.json b/src/Squidex/.vscode/settings.json index 515c80252..26a63fc30 100644 --- a/src/Squidex/.vscode/settings.json +++ b/src/Squidex/.vscode/settings.json @@ -7,7 +7,6 @@ // Configure glob patterns for excluding files and folders. "files.exclude": { - "_test-output": true, "**/node_modules": true, "**/Assets": true, "**/artifacts": true, @@ -23,10 +22,15 @@ "**/*.user": true, "**/*.xproj": true, "**/*.gitattributes": true, - "appsetttings.Development.json", - "appsetttings.Production.json", + "appsetttings.Development.json": true, + "appsetttings.Production.json": true, ".awcache": true, ".vs:": true, ".vscode:": true - } + }, + + "coverage-gutters.coverageFileNames": [ + "_test-output/coverage/lcov.info" + ], + "coverage-gutters.showLineCoverage": true } \ No newline at end of file diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js index ddf15f032..588d04e85 100644 --- a/src/Squidex/app-config/webpack.config.js +++ b/src/Squidex/app-config/webpack.config.js @@ -57,7 +57,7 @@ module.exports = { }, { test: /\.ts$/, use: [{ - loader: 'awesome-typescript-loader', options: { useCache: true, useBabel: true } + loader: 'awesome-typescript-loader' }, { loader: 'angular-router-loader' }, { diff --git a/src/Squidex/app-config/webpack.test.coverage.js b/src/Squidex/app-config/webpack.test.coverage.js index 5e4f8c70b..1989b80d4 100644 --- a/src/Squidex/app-config/webpack.test.coverage.js +++ b/src/Squidex/app-config/webpack.test.coverage.js @@ -16,7 +16,7 @@ module.exports = webpackMerge(testConfig, { rules: [{ test: /\.ts$/, use: [{ - loader: 'awesome-typescript-loader' + loader: 'ts-loader' }], include: [/\.(e2e|spec)\.ts$/], @@ -25,7 +25,7 @@ module.exports = webpackMerge(testConfig, { use: [{ loader: 'istanbul-instrumenter-loader' }, { - loader: 'awesome-typescript-loader' + loader: 'ts-loader' }, { loader: 'angular-router-loader' }, { diff --git a/src/Squidex/app/features/administration/pages/restore/restore-page.component.html b/src/Squidex/app/features/administration/pages/restore/restore-page.component.html index 6e72c95aa..3f6105e1b 100644 --- a/src/Squidex/app/features/administration/pages/restore/restore-page.component.html +++ b/src/Squidex/app/features/administration/pages/restore/restore-page.component.html @@ -6,7 +6,7 @@ -
+
diff --git a/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts b/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts index 32437b609..51cfa686e 100644 --- a/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts +++ b/src/Squidex/app/features/administration/pages/restore/restore-page.component.ts @@ -5,18 +5,16 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { timer } from 'rxjs'; -import { onErrorResumeNext, switchMap } from 'rxjs/operators'; import { AuthService, BackupsService, DialogService, - ResourceOwner, - RestoreDto, - RestoreForm + RestoreForm, + switchSafe } from '@app/shared'; @Component({ @@ -24,27 +22,18 @@ import { styleUrls: ['./restore-page.component.scss'], templateUrl: './restore-page.component.html' }) -export class RestorePageComponent extends ResourceOwner implements OnInit { - public restoreJob: RestoreDto | null; +export class RestorePageComponent { public restoreForm = new RestoreForm(this.formBuilder); + public restoreJob = + timer(0, 2000).pipe(switchSafe(() => this.backupsService.getRestore())); + constructor( public readonly authState: AuthService, private readonly backupsService: BackupsService, private readonly dialogs: DialogService, private readonly formBuilder: FormBuilder ) { - super(); - } - - public ngOnInit() { - this.own( - timer(0, 2000).pipe(switchMap(() => this.backupsService.getRestore().pipe(onErrorResumeNext()))) - .subscribe(job => { - if (job) { - this.restoreJob = job; - } - })); } public restore() { diff --git a/src/Squidex/app/features/administration/services/event-consumers.service.ts b/src/Squidex/app/features/administration/services/event-consumers.service.ts index 169850008..05b2cd0fd 100644 --- a/src/Squidex/app/features/administration/services/event-consumers.service.ts +++ b/src/Squidex/app/features/administration/services/event-consumers.service.ts @@ -40,15 +40,16 @@ export class EventConsumersService { const url = this.apiUrl.buildUrl('/api/event-consumers'); return this.http.get(url).pipe( - map(response => { - return response.map(item => { - return new EventConsumerDto( + map(body => { + const eventConsumers = body.map(item => + new EventConsumerDto( item.name, item.isStopped, item.isResetting, item.error, - item.position); - }); + item.position)); + + return eventConsumers; }), pretifyError('Failed to load event consumers. Please reload.')); } diff --git a/src/Squidex/app/features/administration/services/users.service.ts b/src/Squidex/app/features/administration/services/users.service.ts index 524f4b5d4..a657eee38 100644 --- a/src/Squidex/app/features/administration/services/users.service.ts +++ b/src/Squidex/app/features/administration/services/users.service.ts @@ -61,17 +61,16 @@ export class UsersService { const url = this.apiUrl.buildUrl(`api/user-management?take=${take}&skip=${skip}&query=${query || ''}`); return this.http.get<{ total: number, items: any[] }>(url).pipe( - map(response => { - const users = response.items.map(item => { - return new UserDto( + map(body => { + const users = body.items.map(item => + new UserDto( item.id, item.email, item.displayName, item.permissions, - item.isLocked); - }); + item.isLocked)); - return new UsersDto(response.total, users); + return new UsersDto(body.total, users); }), pretifyError('Failed to load users. Please reload.')); } @@ -80,13 +79,15 @@ export class UsersService { const url = this.apiUrl.buildUrl(`api/user-management/${id}`); return this.http.get(url).pipe( - map(response => { - return new UserDto( - response.id, - response.email, - response.displayName, - response.permissions, - response.isLocked); + map(body => { + const user = new UserDto( + body.id, + body.email, + body.displayName, + body.permissions, + body.isLocked); + + return user; }), pretifyError('Failed to load user. Please reload.')); } @@ -95,13 +96,15 @@ export class UsersService { const url = this.apiUrl.buildUrl('api/user-management'); return this.http.post(url, dto).pipe( - map(response => { - return new UserDto( - response.id, + map(body => { + const user = new UserDto( + body.id, dto.email, dto.displayName, dto.permissions, false); + + return user; }), pretifyError('Failed to create user. Please reload.')); } diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.ts b/src/Squidex/app/features/administration/state/event-consumers.state.ts index 8ca47e0e1..f5c5a0d1d 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.ts @@ -7,11 +7,12 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, + shareSubscribed, State } from '@app/shared'; @@ -49,66 +50,46 @@ export class EventConsumersState extends State { this.resetState(); } - const http$ = - this.eventConsumersService.getEventConsumers().pipe( - share()); + return this.eventConsumersService.getEventConsumers().pipe( + tap(payload => { + if (isReload && !silent) { + this.dialogs.notifyInfo('Event Consumers reloaded.'); + } - http$.subscribe(response => { - if (isReload && !silent) { - this.dialogs.notifyInfo('Event Consumers reloaded.'); - } + const eventConsumers = ImmutableArray.of(payload); - const eventConsumers = ImmutableArray.of(response); - - this.next(s => { - return { ...s, eventConsumers, isLoaded: true }; - }); - - }, error => { - if (!silent) { - this.dialogs.notifyError(error); - } - }); - - return http$; + this.next(s => { + return { ...s, eventConsumers, isLoaded: true }; + }); + }), + shareSubscribed(this.dialogs, { silent })); } public start(eventConsumer: EventConsumerDto): Observable { - const http$ = - this.eventConsumersService.putStart(eventConsumer.name).pipe( - map(() => setStopped(eventConsumer, false), share())); - - this.updateState(http$); - - return http$; + return this.eventConsumersService.putStart(eventConsumer.name).pipe( + map(() => setStopped(eventConsumer, false)), + tap(updated => { + this.replaceEventConsumer(updated); + }), + shareSubscribed(this.dialogs)); } public stop(eventConsumer: EventConsumerDto): Observable { - const http$ = - this.eventConsumersService.putStop(eventConsumer.name).pipe( - map(() => setStopped(eventConsumer, true), share())); - - this.updateState(http$); - - return http$; - } - - public reset(eventConsumer: EventConsumerDto): Observable { - const http$ = - this.eventConsumersService.putReset(eventConsumer.name).pipe( - map(() => reset(eventConsumer), share())); - - this.updateState(http$); - - return http$; + return this.eventConsumersService.putStop(eventConsumer.name).pipe( + map(() => setStopped(eventConsumer, true)), + tap(updated => { + this.replaceEventConsumer(updated); + }), + shareSubscribed(this.dialogs)); } - private updateState(http$: Observable) { - http$.subscribe(updated => { - this.replaceEventConsumer(updated); - }, error => { - this.dialogs.notifyError(error); - }); + public reset(eventConsumer: EventConsumerDto): Observable { + return this.eventConsumersService.putReset(eventConsumer.name).pipe( + map(() => reset(eventConsumer)), + tap(updated => { + this.replaceEventConsumer(updated); + }), + shareSubscribed(this.dialogs)); } private replaceEventConsumer(eventConsumer: EventConsumerDto) { diff --git a/src/Squidex/app/features/administration/state/users.state.ts b/src/Squidex/app/features/administration/state/users.state.ts index 51278708e..c78a7aec7 100644 --- a/src/Squidex/app/features/administration/state/users.state.ts +++ b/src/Squidex/app/features/administration/state/users.state.ts @@ -7,7 +7,7 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; -import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators'; import '@app/framework/utils/rxjs-extensions'; @@ -16,6 +16,7 @@ import { DialogService, ImmutableArray, Pager, + shareSubscribed, State } from '@app/shared'; @@ -81,15 +82,11 @@ export class UsersState extends State { } public select(id: string | null): Observable { - const http$ = - this.loadUser(id).pipe( - share()); - - http$.subscribe(selectedUser => { - this.next(s => ({ ...s, selectedUser })); - }); - - return http$; + return this.loadUser(id).pipe( + tap(selectedUser => { + this.next(s => ({ ...s, selectedUser })); + }), + shareSubscribed(this.dialogs, { silent: true })); } private loadUser(id: string | null) { @@ -115,83 +112,69 @@ export class UsersState extends State { } private loadInternal(isReload = false): Observable { - const http$ = - this.usersService.getUsers( + return this.usersService.getUsers( this.snapshot.usersPager.pageSize, this.snapshot.usersPager.skip, this.snapshot.usersQuery).pipe( - share()); - - http$.subscribe(response => { - if (isReload) { - this.dialogs.notifyInfo('Users reloaded.'); - } - - this.next(s => { - const usersPager = s.usersPager.setCount(response.total); - const users = ImmutableArray.of(response.items.map(x => this.createUser(x))); - - let selectedUser = s.selectedUser; - - if (selectedUser) { - selectedUser = users.find(x => x.user.id === selectedUser!.user.id) || selectedUser; + tap(({ total, items }) => { + if (isReload) { + this.dialogs.notifyInfo('Users reloaded.'); } - return { ...s, users, usersPager, selectedUser, isLoaded: true }; - }); + this.next(s => { + const usersPager = s.usersPager.setCount(total); + const users = ImmutableArray.of(items.map(x => this.createUser(x))); - }, error => { - this.dialogs.notifyError(error); - }); + let selectedUser = s.selectedUser; + + if (selectedUser) { + selectedUser = users.find(x => x.user.id === selectedUser!.user.id) || selectedUser; + } - return http$; + return { ...s, users, usersPager, selectedUser, isLoaded: true }; + }); + }), + shareSubscribed(this.dialogs)); } public create(request: CreateUserDto): Observable { - const http$ = - this.usersService.postUser(request).pipe( - share()); - - http$.subscribe(dto => { - this.next(s => { - const users = s.users.pushFront(this.createUser(dto)); - const usersPager = s.usersPager.incrementCount(); - - return { ...s, users, usersPager }; - }); - }); + return this.usersService.postUser(request).pipe( + tap(payload => { + this.next(s => { + const users = s.users.pushFront(this.createUser(payload)); + const usersPager = s.usersPager.incrementCount(); - return http$; + return { ...s, users, usersPager }; + }); + }), + shareSubscribed(this.dialogs, { silent: true })); } public update(user: UserDto, request: UpdateUserDto): Observable { - const http$ = - this.usersService.putUser(user.id, request).pipe( - map(() => update(user, request)), share()); - - this.updateState(http$, false); - - return http$; + return this.usersService.putUser(user.id, request).pipe( + map(() => update(user, request)), + tap(updated => { + this.replaceUser(updated); + }), + shareSubscribed(this.dialogs)); } public lock(user: UserDto): Observable { - const http$ = - this.usersService.lockUser(user.id).pipe( - map(() => setLocked(user, true)), share()); - - this.updateState(http$, true); - - return http$; + return this.usersService.lockUser(user.id).pipe( + map(() => setLocked(user, true)), + tap(updated => { + this.replaceUser(updated); + }), + shareSubscribed(this.dialogs)); } public unlock(user: UserDto): Observable { - const http$ = - this.usersService.unlockUser(user.id).pipe( - map(() => setLocked(user, false)), share()); - - this.updateState(http$, true); - - return http$; + return this.usersService.unlockUser(user.id).pipe( + map(() => setLocked(user, false)), + tap(updated => { + this.replaceUser(updated); + }), + shareSubscribed(this.dialogs)); } public search(query: string): Observable { @@ -214,7 +197,7 @@ export class UsersState extends State { private replaceUser(user: UserDto) { return this.next(s => { - const users = s.users.map(u => u.user.id === user.id ? this.createUser(user, u) : u); + const users = s.users.map(u => u.user.id === user.id ? this.createUser(user) : u); const selectedUser = s.selectedUser && @@ -230,24 +213,8 @@ export class UsersState extends State { return this.authState.user!.id; } - private updateState(stream: Observable, notify: boolean) { - stream.subscribe(dto => { - this.replaceUser(dto); - }, error => { - if (notify) { - this.dialogs.notifyError(error); - } - }); - } - - private createUser(user: UserDto, current?: SnapshotUser): SnapshotUser { - if (!user) { - return null!; - } else if (current && current.user === user) { - return current; - } else { - return { user, isCurrentUser: user.id === this.userId }; - } + private createUser(user: UserDto): SnapshotUser { + return { user, isCurrentUser: user.id === this.userId }; } } diff --git a/src/Squidex/app/features/assets/pages/assets-filters-page.component.ts b/src/Squidex/app/features/assets/pages/assets-filters-page.component.ts index 69c0852de..1497e5bc6 100644 --- a/src/Squidex/app/features/assets/pages/assets-filters-page.component.ts +++ b/src/Squidex/app/features/assets/pages/assets-filters-page.component.ts @@ -6,7 +6,6 @@ */ import { Component } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AssetsState, @@ -29,19 +28,19 @@ export class AssetsFiltersPageComponent { } public search(query: string) { - this.assetsState.search(query).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.search(query); } public selectTags(tags: string[]) { - this.assetsState.selectTags(tags).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.selectTags(tags); } public toggleTag(tag: string) { - this.assetsState.toggleTag(tag).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.toggleTag(tag); } public resetTags() { - this.assetsState.resetTags().pipe(onErrorResumeNext()).subscribe(); + this.assetsState.resetTags(); } public isSelectedQuery(query: string) { diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.ts b/src/Squidex/app/features/assets/pages/assets-page.component.ts index 5f47ad012..dbab6b358 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.ts +++ b/src/Squidex/app/features/assets/pages/assets-page.component.ts @@ -7,7 +7,6 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppsState, @@ -45,7 +44,7 @@ export class AssetsPageComponent extends ResourceOwner implements OnInit { } public ngOnInit() { - this.assetsState.load().pipe(onErrorResumeNext()).subscribe(); + this.assetsState.load(); this.own( this.assetsState.assetsQuery @@ -55,27 +54,27 @@ export class AssetsPageComponent extends ResourceOwner implements OnInit { } public reload() { - this.assetsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.load(true); } public search() { - this.assetsState.search(this.filter.apiFilter).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.search(this.filter.apiFilter); } public selectTags(tags: string[]) { - this.assetsState.selectTags(tags).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.selectTags(tags); } public toggleTag(tag: string) { - this.assetsState.toggleTag(tag).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.toggleTag(tag); } public goNext() { - this.assetsState.goNext().pipe(onErrorResumeNext()).subscribe(); + this.assetsState.goNext(); } public goPrev() { - this.assetsState.goPrev().pipe(onErrorResumeNext()).subscribe(); + this.assetsState.goPrev(); } public changeView(isListView: boolean) { diff --git a/src/Squidex/app/features/content/pages/content/content-history-page.component.ts b/src/Squidex/app/features/content/pages/content/content-history-page.component.ts index 96d9fa43d..74410e37d 100644 --- a/src/Squidex/app/features/content/pages/content/content-history-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-history-page.component.ts @@ -8,7 +8,7 @@ import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { merge, Observable, timer } from 'rxjs'; -import { delay, onErrorResumeNext, switchMap } from 'rxjs/operators'; +import { delay } from 'rxjs/operators'; import { allParams, @@ -17,6 +17,7 @@ import { HistoryEventDto, HistoryService, MessageBus, + switchSafe, Version } from '@app/shared'; @@ -51,7 +52,7 @@ export class ContentHistoryPageComponent { timer(0, 10000), this.messageBus.of(HistoryChannelUpdated).pipe(delay(1000)) ).pipe( - switchMap(() => this.historyService.getHistory(this.appsState.appName, this.channel).pipe(onErrorResumeNext()))); + switchSafe(() => this.historyService.getHistory(this.appsState.appName, this.channel))); constructor( private readonly appsState: AppsState, diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.ts b/src/Squidex/app/features/content/pages/content/content-page.component.ts index 610094887..d36bf696a 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-page.component.ts @@ -171,7 +171,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD } public discardChanges() { - this.contentsState.discardChanges(this.content).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.discardChanges(this.content); } public publish() { diff --git a/src/Squidex/app/features/content/pages/contents/contents-filters-page.component.ts b/src/Squidex/app/features/content/pages/contents/contents-filters-page.component.ts index 6f7bbd691..4779955c7 100644 --- a/src/Squidex/app/features/content/pages/contents/contents-filters-page.component.ts +++ b/src/Squidex/app/features/content/pages/contents/contents-filters-page.component.ts @@ -6,7 +6,6 @@ */ import { Component, OnInit } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { ContentsState, @@ -43,7 +42,7 @@ export class ContentsFiltersPageComponent extends ResourceOwner implements OnIni } public search(query: string) { - this.contentsState.search(query).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.search(query); } public isSelectedQuery(query: string) { diff --git a/src/Squidex/app/features/content/pages/contents/contents-page.component.ts b/src/Squidex/app/features/content/pages/contents/contents-page.component.ts index 76285718d..4a84c8670 100644 --- a/src/Squidex/app/features/content/pages/contents/contents-page.component.ts +++ b/src/Squidex/app/features/content/pages/contents/contents-page.component.ts @@ -77,7 +77,7 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit { this.schema = schema!; this.schemaQueries = new Queries(this.uiState, `schemas.${this.schema.name}`); - this.contentsState.init().pipe(onErrorResumeNext()).subscribe(); + this.contentsState.init(); })); this.own( @@ -103,15 +103,15 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit { } public reload() { - this.contentsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.load(true); } public deleteSelected() { - this.contentsState.deleteMany(this.selectItems()).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.deleteMany(this.selectItems()); } public delete(content: ContentDto) { - this.contentsState.deleteMany([content]).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.deleteMany([content]); } public publish(content: ContentDto) { @@ -147,7 +147,7 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit { } public clone(content: ContentDto) { - this.contentsState.create(content.dataDraft, false).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.create(content.dataDraft, false); } private changeContentItems(contents: ContentDto[], action: string) { @@ -165,19 +165,19 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit { } public goArchive(isArchive: boolean) { - this.contentsState.goArchive(isArchive).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.goArchive(isArchive); } public goPrev() { - this.contentsState.goPrev().pipe(onErrorResumeNext()).subscribe(); + this.contentsState.goPrev(); } public goNext() { - this.contentsState.goNext().pipe(onErrorResumeNext()).subscribe(); + this.contentsState.goNext(); } public search() { - this.contentsState.search(this.filter.apiFilter).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.search(this.filter.apiFilter); } public selectLanguage(language: AppLanguageDto) { diff --git a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts index a2184efee..273951329 100644 --- a/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts @@ -7,7 +7,6 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppsState, SchemasState } from '@app/shared'; @@ -26,7 +25,7 @@ export class SchemasPageComponent implements OnInit { } public ngOnInit() { - this.schemasState.load().pipe(onErrorResumeNext()).subscribe(); + this.schemasState.load(); } public trackByCategory(index: number, category: string) { diff --git a/src/Squidex/app/features/content/shared/contents-selector.component.ts b/src/Squidex/app/features/content/shared/contents-selector.component.ts index 50d40796b..0c3a2b254 100644 --- a/src/Squidex/app/features/content/shared/contents-selector.component.ts +++ b/src/Squidex/app/features/content/shared/contents-selector.component.ts @@ -6,7 +6,6 @@ */ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { ContentDto, @@ -54,23 +53,23 @@ export class ContentsSelectorComponent implements OnInit { public ngOnInit() { this.contentsState.schema = this.schema; - this.contentsState.load().pipe(onErrorResumeNext()).subscribe(); + this.contentsState.load(); } public reload() { - this.contentsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.load(true); } public search() { - this.contentsState.search(this.filter.apiFilter).pipe(onErrorResumeNext()).subscribe(); + this.contentsState.search(this.filter.apiFilter); } public goNext() { - this.contentsState.goNext().pipe(onErrorResumeNext()).subscribe(); + this.contentsState.goNext(); } public goPrev() { - this.contentsState.goPrev().pipe(onErrorResumeNext()).subscribe(); + this.contentsState.goPrev(); } public isItemSelected(content: ContentDto) { diff --git a/src/Squidex/app/features/rules/pages/events/rule-events-page.component.ts b/src/Squidex/app/features/rules/pages/events/rule-events-page.component.ts index 694d58a00..298d0a6f3 100644 --- a/src/Squidex/app/features/rules/pages/events/rule-events-page.component.ts +++ b/src/Squidex/app/features/rules/pages/events/rule-events-page.component.ts @@ -6,7 +6,6 @@ */ import { Component, OnInit } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppsState, @@ -29,27 +28,27 @@ export class RuleEventsPageComponent implements OnInit { } public ngOnInit() { - this.ruleEventsState.load().pipe(onErrorResumeNext()).subscribe(); + this.ruleEventsState.load(); } public reload() { - this.ruleEventsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.ruleEventsState.load(true); } public goNext() { - this.ruleEventsState.goNext().pipe(onErrorResumeNext()).subscribe(); + this.ruleEventsState.goNext(); } public goPrev() { - this.ruleEventsState.goPrev().pipe(onErrorResumeNext()).subscribe(); + this.ruleEventsState.goPrev(); } public enqueue(event: RuleEventDto) { - this.ruleEventsState.enqueue(event).pipe(onErrorResumeNext()).subscribe(); + this.ruleEventsState.enqueue(event); } public cancel(event: RuleEventDto) { - this.ruleEventsState.cancel(event).pipe(onErrorResumeNext()).subscribe(); + this.ruleEventsState.cancel(event); } public selectEvent(id: string) { diff --git a/src/Squidex/app/features/schemas/pages/schema/field.component.ts b/src/Squidex/app/features/schemas/pages/schema/field.component.ts index 2e64fdf05..15bb242ee 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/field.component.ts @@ -7,7 +7,6 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { createProperties, @@ -82,23 +81,23 @@ export class FieldComponent implements OnChanges { } public deleteField() { - this.schemasState.deleteField(this.schema, this.field).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.deleteField(this.schema, this.field); } public enableField() { - this.schemasState.enableField(this.schema, this.field).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.enableField(this.schema, this.field); } public disableField() { - this.schemasState.disableField(this.schema, this.field).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.disableField(this.schema, this.field); } public showField() { - this.schemasState.showField(this.schema, this.field).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.showField(this.schema, this.field); } public hideField() { - this.schemasState.hideField(this.schema, this.field).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.hideField(this.schema, this.field); } public sortFields(fields: NestedFieldDto[]) { @@ -106,7 +105,7 @@ export class FieldComponent implements OnChanges { } public lockField() { - this.schemasState.lockField(this.schema, this.field).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.lockField(this.schema, this.field); } public trackByField(index: number, field: NestedFieldDto) { diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts index 6affed5fb..abc5b1f46 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts @@ -9,7 +9,6 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppsState, @@ -66,7 +65,7 @@ export class SchemaPageComponent extends ResourceOwner implements OnInit { } public ngOnInit() { - this.patternsState.load().pipe(onErrorResumeNext()).subscribe(); + this.patternsState.load(); this.own( this.schemasState.selectedSchema diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index 75d6d9b30..7c8aa690f 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -8,7 +8,7 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormControl } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; -import { map, onErrorResumeNext } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { AppsState, @@ -63,7 +63,7 @@ export class SchemasPageComponent extends ResourceOwner implements OnInit { } })); - this.schemasState.load().pipe(onErrorResumeNext()).subscribe(); + this.schemasState.load(); } public removeCategory(name: string) { diff --git a/src/Squidex/app/features/settings/pages/languages/language.component.ts b/src/Squidex/app/features/settings/pages/languages/language.component.ts index 6d1ed36e1..53d4d228a 100644 --- a/src/Squidex/app/features/settings/pages/languages/language.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/language.component.ts @@ -7,7 +7,6 @@ import { Component, Input, OnChanges } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppLanguageDto, @@ -56,7 +55,7 @@ export class LanguageComponent implements OnChanges { } public remove() { - this.languagesState.remove(this.language).pipe(onErrorResumeNext()).subscribe(); + this.languagesState.remove(this.language); } public save() { diff --git a/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts b/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts index 31634d509..a41d8d505 100644 --- a/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts @@ -7,7 +7,6 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AddLanguageForm, @@ -42,11 +41,11 @@ export class LanguagesPageComponent extends ResourceOwner implements OnInit { } })); - this.languagesState.load().pipe(onErrorResumeNext()).subscribe(); + this.languagesState.load(); } public reload() { - this.languagesState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.languagesState.load(true); } public addLanguage() { diff --git a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts index e1a45b953..2540ffc0e 100644 --- a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts @@ -7,7 +7,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { EditPatternForm, @@ -41,7 +40,7 @@ export class PatternComponent implements OnInit { } public delete() { - this.patternsState.delete(this.pattern).pipe(onErrorResumeNext()).subscribe(); + this.patternsState.delete(this.pattern); } public save() { diff --git a/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts b/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts index 01ff48e92..a99b188e0 100644 --- a/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/patterns-page.component.ts @@ -6,7 +6,6 @@ */ import { Component, OnInit } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AppsState, @@ -27,11 +26,11 @@ export class PatternsPageComponent implements OnInit { } public ngOnInit() { - this.patternsState.load().pipe(onErrorResumeNext()).subscribe(); + this.patternsState.load(); } public reload() { - this.patternsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.patternsState.load(true); } public trackByPattern(index: number, pattern: PatternDto) { diff --git a/src/Squidex/app/features/settings/pages/plans/plans-page.component.ts b/src/Squidex/app/features/settings/pages/plans/plans-page.component.ts index 8c1d125e5..ec4c90da8 100644 --- a/src/Squidex/app/features/settings/pages/plans/plans-page.component.ts +++ b/src/Squidex/app/features/settings/pages/plans/plans-page.component.ts @@ -7,7 +7,6 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { onErrorResumeNext } from 'rxjs/operators'; import { ApiUrlConfig, @@ -39,15 +38,15 @@ export class PlansPageComponent implements OnInit { this.overridePlanId = params['planId']; }).unsubscribe(); - this.plansState.load(false, this.overridePlanId).pipe(onErrorResumeNext()).subscribe(); + this.plansState.load(false, this.overridePlanId); } public reload() { - this.plansState.load(true, this.overridePlanId).pipe(onErrorResumeNext()).subscribe(); + this.plansState.load(true, this.overridePlanId); } public change(planId: string) { - this.plansState.change(planId).pipe(onErrorResumeNext()).subscribe(); + this.plansState.change(planId); } public trackByPlan(index: number, planInfo: { plan: PlanDto }) { diff --git a/src/Squidex/app/features/settings/pages/roles/role.component.ts b/src/Squidex/app/features/settings/pages/roles/role.component.ts index 78e77aa06..385fe6cf2 100644 --- a/src/Squidex/app/features/settings/pages/roles/role.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/role.component.ts @@ -7,7 +7,6 @@ import { Component, Input, OnChanges, ViewChild } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AddPermissionForm, @@ -76,7 +75,7 @@ export class RoleComponent implements OnChanges { } public remove() { - this.rolesState.delete(this.role).pipe(onErrorResumeNext()).subscribe(); + this.rolesState.delete(this.role); } public addPermission() { diff --git a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts index edad41b92..f70cb83f6 100644 --- a/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts +++ b/src/Squidex/app/features/settings/pages/roles/roles-page.component.ts @@ -8,7 +8,6 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { Observable, of } from 'rxjs'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AddRoleForm, @@ -50,11 +49,11 @@ export class RolesPageComponent implements OnInit { } public ngOnInit() { - this.rolesState.load().pipe(onErrorResumeNext()).subscribe(); + this.rolesState.load(); } public reload() { - this.rolesState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.rolesState.load(true); } public cancelAddRole() { diff --git a/src/Squidex/app/framework/angular/http/http-extensions.ts b/src/Squidex/app/framework/angular/http/http-extensions.ts index 543213b9a..3566c63a3 100644 --- a/src/Squidex/app/framework/angular/http/http-extensions.ts +++ b/src/Squidex/app/framework/angular/http/http-extensions.ts @@ -56,7 +56,7 @@ export module HTTP { return httpRequest.pipe(map((response: HttpResponse) => { const etag = response.headers.get('etag') || ''; - return new Versioned(new Version(etag), response); + return { version: new Version(etag), payload: response }; })); } } diff --git a/src/Squidex/app/framework/utils/rxjs-extensions.ts b/src/Squidex/app/framework/utils/rxjs-extensions.ts index 37211ea59..4e54b9f2c 100644 --- a/src/Squidex/app/framework/utils/rxjs-extensions.ts +++ b/src/Squidex/app/framework/utils/rxjs-extensions.ts @@ -5,16 +5,61 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ +// tslint:disable: only-arrow-functions + import { Observable, throwError } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { catchError, map, onErrorResumeNext, shareReplay, switchMap } from 'rxjs/operators'; import { DialogService } from './../services/dialog.service'; -/* tslint:disable:no-shadowed-variable */ +import { + Version, + versioned, + Versioned +} from './version'; + +export function mapVersioned(project: (value: T, version: Version) => R) { + return function mapOperation(source: Observable>) { + return source.pipe(map, Versioned>(({ version, payload }) => { + return versioned(version, project(payload, version)); + })); + }; +} + +export function notify(dialogs: DialogService) { + return function mapOperation(source: Observable) { + return source.pipe(catchError(error => { + dialogs.notifyError(error); + + return throwError(error); + })); + }; +} + +type Options = { silent?: boolean, project?: ((value: T) => R) }; + +export function shareSubscribed(dialogs: DialogService, options?: Options) { + return function mapOperation(source: Observable) { + const shared = source.pipe(shareReplay()); + + shared.subscribe(undefined, error => { + if (dialogs && (!options || !options.silent)) { + dialogs.notifyError(error); + } + }); + + if (options && !!options.project) { + const project = options.project; -export const notify = (dialogs: DialogService) => (source: Observable) => - source.pipe(catchError(error => { - dialogs.notifyError(error); + return shared.pipe(map(x => project(x))); + } else { + return shared; + } + }; +} - return throwError(error); - })); \ No newline at end of file +export function switchSafe(project: (source: T) => Observable) { + return function mapOperation(source: Observable) { + return source.pipe(switchMap(project), onErrorResumeNext()); + }; +} \ No newline at end of file diff --git a/src/Squidex/app/framework/utils/version.spec.ts b/src/Squidex/app/framework/utils/version.spec.ts index 6cf3e24fe..1e69d63b8 100644 --- a/src/Squidex/app/framework/utils/version.spec.ts +++ b/src/Squidex/app/framework/utils/version.spec.ts @@ -5,7 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { Version, Versioned } from './version'; +import { Version } from './version'; describe('Version', () => { it('should initialize with init value', () => { @@ -20,13 +20,4 @@ describe('Version', () => { expect(new Version('W/2').eq(new Version('2'))).toBeTruthy(); expect(new Version('W/2').eq(new Version('W/2'))).toBeTruthy(); }); -}); - -describe('Versioned', () => { - it('should initialize with version and payload', () => { - const versioned = new Versioned(new Version('1.0'), 123); - - expect(versioned.version.value).toBe('1.0'); - expect(versioned.payload).toBe(123); - }); }); \ No newline at end of file diff --git a/src/Squidex/app/framework/utils/version.ts b/src/Squidex/app/framework/utils/version.ts index e7bf99dd6..1f4888e28 100644 --- a/src/Squidex/app/framework/utils/version.ts +++ b/src/Squidex/app/framework/utils/version.ts @@ -24,10 +24,8 @@ export class Version { } } -export class Versioned { - constructor( - public readonly version: Version, - public readonly payload: T - ) { - } -} \ No newline at end of file +export function versioned(version: Version, payload: T = undefined!): Versioned { + return { version, payload }; +} + +export type Versioned = { readonly version: Version, readonly payload: T }; \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset-uploader.component.ts b/src/Squidex/app/shared/components/asset-uploader.component.ts index c8c5c8f5c..a4c13faac 100644 --- a/src/Squidex/app/shared/components/asset-uploader.component.ts +++ b/src/Squidex/app/shared/components/asset-uploader.component.ts @@ -10,8 +10,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { AssetsState, DialogModel, - fadeAnimation, - UploadingAsset + fadeAnimation } from '@app/shared/internal'; @Component({ @@ -31,19 +30,7 @@ export class AssetUploaderComponent { ) { } - public addFiles(files: File[]) { - for (let file of files) { - this.assets.upload(file).subscribe(); - } - + public addFiles() { this.modalMenu.show(); } - - public stopUpload(upload: UploadingAsset) { - this.assets.remove(upload); - } - - public trackByUpload(index: number, upload: UploadingAsset) { - return upload.id; - } } \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 6550d3bda..dc6ec3698 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -17,8 +17,7 @@ import { DialogService, fadeAnimation, StatefulComponent, - Types, - Versioned + Types } from '@app/shared/internal'; interface State { @@ -101,10 +100,10 @@ export class AssetComponent extends StatefulComponent implements OnInit { this.assetsService.uploadFile(this.appsState.appName, initFile, this.authState.user!.token, DateTime.now()) .subscribe(dto => { - if (Types.is(dto, AssetDto)) { - this.emitLoad(dto); - } else { + if (Types.isNumber(dto)) { this.setProgress(dto); + } else { + this.emitLoad(dto); } }, error => { this.dialogs.notifyError(error); @@ -120,10 +119,10 @@ export class AssetComponent extends StatefulComponent implements OnInit { this.assetsService.replaceFile(this.appsState.appName, this.asset.id, files[0], this.asset.version) .subscribe(dto => { - if (Types.is(dto, Versioned)) { - this.updateAsset(this.asset.update(dto.payload, this.authState.user!.token, dto.version), true); - } else { + if (Types.isNumber(dto)) { this.setProgress(dto); + } else { + this.updateAsset(this.asset.update(dto.payload, this.authState.user!.token, dto.version), true); } }, error => { this.dialogs.notifyError(error); diff --git a/src/Squidex/app/shared/components/assets-list.component.ts b/src/Squidex/app/shared/components/assets-list.component.ts index 1f4931b76..4838ef066 100644 --- a/src/Squidex/app/shared/components/assets-list.component.ts +++ b/src/Squidex/app/shared/components/assets-list.component.ts @@ -11,7 +11,7 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { AssetDto, AssetsState, - AssetWithUpload + ImmutableArray } from '@app/shared/internal'; @Component({ @@ -21,6 +21,8 @@ import { changeDetection: ChangeDetectionStrategy.OnPush }) export class AssetsListComponent { + public newFiles = ImmutableArray.empty(); + @Input() public state: AssetsState; @@ -36,6 +38,12 @@ export class AssetsListComponent { @Output() public select = new EventEmitter(); + public add(file: File, asset: AssetDto) { + this.newFiles = this.newFiles.remove(file); + + this.state.add(asset); + } + public search() { this.state.load().pipe(onErrorResumeNext()).subscribe(); } @@ -56,10 +64,6 @@ export class AssetsListComponent { this.state.update(asset); } - public updateFile(asset: AssetDto, file: File) { - this.state.replaceFile(asset, file).pipe(onErrorResumeNext()).subscribe(); - } - public emitSelect(asset: AssetDto) { this.select.emit(asset); } @@ -68,9 +72,13 @@ export class AssetsListComponent { return this.selectedIds && this.selectedIds[asset.id]; } + public remove(file: File) { + this.newFiles = this.newFiles.remove(file); + } + public addFiles(files: File[]) { for (let file of files) { - this.state.upload(file); + this.newFiles = this.newFiles.pushFront(file); } return true; @@ -79,9 +87,4 @@ export class AssetsListComponent { public trackByAsset(index: number, asset: AssetDto) { return asset.id; } - - public trackByUpload(index: number, upload: AssetWithUpload) { - return upload.asset.id; - } } - diff --git a/src/Squidex/app/shared/components/assets-selector.component.ts b/src/Squidex/app/shared/components/assets-selector.component.ts index 507ea931a..4956ffd64 100644 --- a/src/Squidex/app/shared/components/assets-selector.component.ts +++ b/src/Squidex/app/shared/components/assets-selector.component.ts @@ -6,7 +6,6 @@ */ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, OnInit, Output } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { AssetDto, @@ -51,15 +50,15 @@ export class AssetsSelectorComponent extends StatefulComponent implements } public ngOnInit() { - this.assetsState.load().pipe(onErrorResumeNext()).subscribe(); + this.assetsState.load(); } public reload() { - this.assetsState.load(true).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.load(true); } public search() { - this.assetsState.search(this.filter.apiFilter).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.search(this.filter.apiFilter); } public emitComplete() { @@ -71,7 +70,7 @@ export class AssetsSelectorComponent extends StatefulComponent implements } public selectTags(tags: string[]) { - this.assetsState.selectTags(tags).pipe(onErrorResumeNext()).subscribe(); + this.assetsState.selectTags(tags); } public selectAsset(asset: AssetDto) { diff --git a/src/Squidex/app/shared/components/history.component.ts b/src/Squidex/app/shared/components/history.component.ts index bb1eb37bf..435196a59 100644 --- a/src/Squidex/app/shared/components/history.component.ts +++ b/src/Squidex/app/shared/components/history.component.ts @@ -8,7 +8,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { merge, Observable, timer } from 'rxjs'; -import { delay, onErrorResumeNext, switchMap } from 'rxjs/operators'; +import { delay } from 'rxjs/operators'; import { allParams, @@ -16,7 +16,8 @@ import { HistoryChannelUpdated, HistoryEventDto, HistoryService, - MessageBus + MessageBus, + switchSafe } from '@app/shared/internal'; @Component({ @@ -33,7 +34,7 @@ export class HistoryComponent { timer(0, 10000), this.messageBus.of(HistoryChannelUpdated).pipe(delay(1000)) ).pipe( - switchMap(() => this.historyService.getHistory(this.appsState.appName, this.channel).pipe(onErrorResumeNext()))); + switchSafe(() => this.historyService.getHistory(this.appsState.appName, this.channel))); constructor( private readonly appsState: AppsState, diff --git a/src/Squidex/app/shared/components/schema-category.component.ts b/src/Squidex/app/shared/components/schema-category.component.ts index 103bdf481..569d37749 100644 --- a/src/Squidex/app/shared/components/schema-category.component.ts +++ b/src/Squidex/app/shared/components/schema-category.component.ts @@ -6,7 +6,6 @@ */ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; -import { onErrorResumeNext } from 'rxjs/operators'; import { fadeAnimation, @@ -127,7 +126,7 @@ export class SchemaCategoryComponent extends StatefulComponent implements } public changeCategory(schema: SchemaDto) { - this.schemasState.changeCategory(schema, this.name).pipe(onErrorResumeNext()).subscribe(); + this.schemasState.changeCategory(schema, this.name); } public emitRemove() { diff --git a/src/Squidex/app/shared/services/app-languages.service.spec.ts b/src/Squidex/app/shared/services/app-languages.service.spec.ts index 273a57ba4..4c41624de 100644 --- a/src/Squidex/app/shared/services/app-languages.service.spec.ts +++ b/src/Squidex/app/shared/services/app-languages.service.spec.ts @@ -71,11 +71,13 @@ describe('AppLanguagesService', () => { } }); - expect(languages!).toEqual( - new AppLanguagesDto([ + expect(languages!).toEqual({ + payload: [ new AppLanguageDto('en', 'English', true, true, ['de', 'en']), new AppLanguageDto('it', 'Italian', false, false, []) - ], new Version('2'))); + ], + version: new Version('2') + }); })); it('should make post request to add language', diff --git a/src/Squidex/app/shared/services/app-languages.service.ts b/src/Squidex/app/shared/services/app-languages.service.ts index 3f35b6ebd..8df82330c 100644 --- a/src/Squidex/app/shared/services/app-languages.service.ts +++ b/src/Squidex/app/shared/services/app-languages.service.ts @@ -8,12 +8,13 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { AnalyticsService, ApiUrlConfig, HTTP, + mapVersioned, Model, pretifyError, Version, @@ -22,14 +23,7 @@ import { import { LanguageDto } from './languages.service'; -export class AppLanguagesDto extends Model { - constructor( - public readonly languages: AppLanguageDto[], - public readonly version: Version - ) { - super(); - } -} +export type AppLanguagesDto = Versioned; export class AppLanguageDto extends Model { constructor( @@ -75,21 +69,18 @@ export class AppLanguagesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const items: any[] = body; - const languages = items.map(item => { - return new AppLanguageDto( + const languages = items.map(item => + new AppLanguageDto( item.iso2Code, item.englishName, item.isMaster, item.isOptional, - item.fallback || []); - }); + item.fallback || [])); - return new AppLanguagesDto(languages, response.version); + return languages; }), pretifyError('Failed to load languages. Please reload.')); } @@ -98,9 +89,7 @@ export class AppLanguagesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages`); return HTTP.postVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const language = new AppLanguageDto( body.iso2Code, body.englishName, @@ -108,7 +97,7 @@ export class AppLanguagesService { body.isOptional, body.fallback || []); - return new Versioned(response.version, language); + return language; }), tap(() => { this.analytics.trackEvent('Language', 'Added', appName); diff --git a/src/Squidex/app/shared/services/apps.service.ts b/src/Squidex/app/shared/services/apps.service.ts index 5771c9775..382a14eeb 100644 --- a/src/Squidex/app/shared/services/apps.service.ts +++ b/src/Squidex/app/shared/services/apps.service.ts @@ -14,7 +14,6 @@ import { AnalyticsService, ApiUrlConfig, DateTime, - HTTP, Model, Permission, pretifyError @@ -51,13 +50,9 @@ export class AppsService { public getApps(): Observable { const url = this.apiUrl.buildUrl('/api/apps'); - return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; - - const items: any[] = body; - - return items.map(item => { + return this.http.get(url).pipe( + map(body => { + const apps = body.map(item => { const permissions = (item.permissions).map(x => new Permission(x)); return new AppDto( @@ -69,6 +64,8 @@ export class AppsService { item.planName, item.planUpgrade); }); + + return apps; }), pretifyError('Failed to load apps. Please reload.')); } @@ -76,15 +73,22 @@ export class AppsService { public postApp(dto: CreateAppDto, now?: DateTime): Observable { const url = this.apiUrl.buildUrl('api/apps'); - return HTTP.postVersioned(this.http, url, dto).pipe( - map(response => { - const body = response.payload.body; - + return this.http.post(url, dto).pipe( + map(body => { now = now || DateTime.now(); const permissions = (body.permissions).map(x => new Permission(x)); - return new AppDto(body.id, dto.name, permissions, now, now, body.planName, body.planUpgrade); + const app = new AppDto( + body.id, + dto.name, + permissions, + now, + now, + body.planName, + body.planUpgrade); + + return app; }), tap(() => { this.analytics.trackEvent('App', 'Created', dto.name); diff --git a/src/Squidex/app/shared/services/assets.service.ts b/src/Squidex/app/shared/services/assets.service.ts index d5ac43806..d38e82af0 100644 --- a/src/Squidex/app/shared/services/assets.service.ts +++ b/src/Squidex/app/shared/services/assets.service.ts @@ -21,7 +21,8 @@ import { ResultSet, Types, Version, - Versioned + Versioned, + versioned } from '@app/framework'; export class AssetsDto extends ResultSet { } @@ -102,8 +103,7 @@ export class AssetsService { public getTags(appName: string): Observable<{ [name: string]: number }> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/tags`); - return HTTP.getVersioned(this.http, url).pipe( - map(response => response.payload.body)); + return this.http.get<{ [name: string]: number }>(url); } public getAssets(appName: string, take: number, skip: number, query?: string, tags?: string[], ids?: string[]): Observable { @@ -141,12 +141,12 @@ export class AssetsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets?${fullQuery}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ payload }) => { + const body = payload.body; const items: any[] = body.items; - return new AssetsDto(body.total, items.map(item => { + const assets = new AssetsDto(body.total, items.map(item => { const assetUrl = this.apiUrl.buildUrl(`api/assets/${item.id}`); return new AssetDto( @@ -170,6 +170,8 @@ export class AssetsService { assetUrl, new Version(item.version.toString())); })); + + return assets; }), pretifyError('Failed to load assets. Please reload.')); } @@ -239,8 +241,8 @@ export class AssetsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ version, payload }) => { + const body = payload.body; const assetUrl = this.apiUrl.buildUrl(`api/assets/${body.id}`); @@ -263,7 +265,7 @@ export class AssetsService { body.slug, body.tags || [], assetUrl, - response.version); + version); }), pretifyError('Failed to load assets. Please reload.')); } @@ -285,7 +287,7 @@ export class AssetsService { } else if (Types.is(event, HttpResponse)) { const response: any = event.body; - return new Versioned(new Version(event.headers.get('etag')!), response); + return versioned(new Version(event.headers.get('etag')!), response); } else { throw 'Invalid'; } diff --git a/src/Squidex/app/shared/services/backups.service.ts b/src/Squidex/app/shared/services/backups.service.ts index 4a9f0dbea..b45dea288 100644 --- a/src/Squidex/app/shared/services/backups.service.ts +++ b/src/Squidex/app/shared/services/backups.service.ts @@ -62,16 +62,17 @@ export class BackupsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/backups`); return this.http.get(url).pipe( - map(response => { - return response.map(item => { - return new BackupDto( + map(body => { + const backups = body.map(item => + new BackupDto( item.id, DateTime.parseISO_UTC(item.started), item.stopped ? DateTime.parseISO_UTC(item.stopped) : null, item.handledEvents, item.handledAssets, - item.status); - }); + item.status)); + + return backups; }), pretifyError('Failed to load backups.')); } @@ -80,13 +81,15 @@ export class BackupsService { const url = this.apiUrl.buildUrl(`api/apps/restore`); return this.http.get(url).pipe( - map(response => { - return new RestoreDto( - response.url, - DateTime.parseISO_UTC(response.started), - response.stopped ? DateTime.parseISO_UTC(response.stopped) : null, - response.status, - response.log); + map(body => { + const restore = new RestoreDto( + body.url, + DateTime.parseISO_UTC(body.started), + body.stopped ? DateTime.parseISO_UTC(body.stopped) : null, + body.status, + body.log); + + return restore; }), catchError(error => { if (Types.is(error, HttpErrorResponse) && error.status === 404) { diff --git a/src/Squidex/app/shared/services/clients.service.spec.ts b/src/Squidex/app/shared/services/clients.service.spec.ts index 14ced0b32..25c9c9e97 100644 --- a/src/Squidex/app/shared/services/clients.service.spec.ts +++ b/src/Squidex/app/shared/services/clients.service.spec.ts @@ -71,11 +71,13 @@ describe('ClientsService', () => { } }); - expect(clients!).toEqual( - new ClientsDto([ + expect(clients!).toEqual({ + payload: [ new ClientDto('client1', 'Client 1', 'secret1', 'Editor'), new ClientDto('client2', 'Client 2', 'secret2', 'Developer') - ], new Version('2'))); + ], + version: new Version('2') + }); })); it('should make post request to create client', diff --git a/src/Squidex/app/shared/services/clients.service.ts b/src/Squidex/app/shared/services/clients.service.ts index 396e3182e..ee1e9a72d 100644 --- a/src/Squidex/app/shared/services/clients.service.ts +++ b/src/Squidex/app/shared/services/clients.service.ts @@ -14,20 +14,14 @@ import { AnalyticsService, ApiUrlConfig, HTTP, + mapVersioned, Model, pretifyError, Version, Versioned } from '@app/framework'; -export class ClientsDto extends Model { - constructor( - public readonly clients: ClientDto[], - public readonly version: Version - ) { - super(); - } -} +export type ClientsDto = Versioned; export class ClientDto extends Model { constructor( @@ -70,20 +64,17 @@ export class ClientsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const items: any[] = body; - const clients = items.map(item => { - return new ClientDto( + const clients = items.map(item => + new ClientDto( item.id, - item.name || body.id, + item.name || item.id, item.secret, - item.role); - }); + item.role)); - return new ClientsDto(clients, response.version); + return clients; }), pretifyError('Failed to load clients. Please reload.')); } @@ -92,16 +83,14 @@ export class ClientsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`); return HTTP.postVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const client = new ClientDto( body.id, body.name || body.id, body.secret, body.role); - return new Versioned(response.version, client); + return client; }), tap(() => { this.analytics.trackEvent('Client', 'Created', appName); diff --git a/src/Squidex/app/shared/services/comments.service.ts b/src/Squidex/app/shared/services/comments.service.ts index b170ccfd0..36694e8da 100644 --- a/src/Squidex/app/shared/services/comments.service.ts +++ b/src/Squidex/app/shared/services/comments.service.ts @@ -56,25 +56,27 @@ export class CommentsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/comments/${commentsId}?version=${version.value}`); return this.http.get(url).pipe( - map(response => { - return new CommentsDto( - response.createdComments.map((item: any) => { + map(body => { + const comments = new CommentsDto( + body.createdComments.map((item: any) => { return new CommentDto( item.id, DateTime.parseISO_UTC(item.time), item.text, item.user); }), - response.updatedComments.map((item: any) => { + body.updatedComments.map((item: any) => { return new CommentDto( item.id, DateTime.parseISO_UTC(item.time), item.text, item.user); }), - response.deletedComments, - new Version(response.version) + body.deletedComments, + new Version(body.version) ); + + return comments; }), pretifyError('Failed to load comments.')); } @@ -82,15 +84,15 @@ export class CommentsService { public postComment(appName: string, commentsId: string, dto: UpsertCommentDto): Observable { const url = this.apiUrl.buildUrl(`api/apps/${appName}/comments/${commentsId}`); - return this.http.post(url, dto).pipe( - map(response => { - const body: any = response; - - return new CommentDto( + return this.http.post(url, dto).pipe( + map(body => { + const comment = new CommentDto( body.id, DateTime.parseISO_UTC(body.time), body.text, body.user); + + return comment; }), pretifyError('Failed to create comment.')); } diff --git a/src/Squidex/app/shared/services/contents.service.ts b/src/Squidex/app/shared/services/contents.service.ts index 6888dc646..1e451a5dd 100644 --- a/src/Squidex/app/shared/services/contents.service.ts +++ b/src/Squidex/app/shared/services/contents.service.ts @@ -15,6 +15,7 @@ import { ApiUrlConfig, DateTime, HTTP, + mapVersioned, Model, pretifyError, ResultSet, @@ -99,13 +100,13 @@ export class ContentsService { const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}?${fullQuery}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ payload }) => { + const body = payload.body; const items: any[] = body.items; - return new ContentsDto(body.total, items.map(item => { - return new ContentDto( + const contents = new ContentsDto(body.total, items.map(item => + new ContentDto( item.id, item.status, DateTime.parseISO_UTC(item.created), item.createdBy, @@ -119,8 +120,9 @@ export class ContentsService { item.isPending === true, item.data, item.dataDraft, - new Version(item.version.toString())); - })); + new Version(item.version.toString())))); + + return contents; }), pretifyError('Failed to load contents. Please reload.')); } @@ -129,10 +131,10 @@ export class ContentsService { const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ version, payload }) => { + const body = payload.body; - return new ContentDto( + const content = new ContentDto( body.id, body.status, DateTime.parseISO_UTC(body.created), body.createdBy, @@ -146,7 +148,9 @@ export class ContentsService { body.isPending === true, body.data, body.dataDraft, - response.version); + version); + + return content; }), pretifyError('Failed to load content. Please reload.')); } @@ -155,8 +159,8 @@ export class ContentsService { const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}/${version.value}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - return new Versioned(response.version, response.payload.body); + mapVersioned(({ body }) => { + return body; }), pretifyError('Failed to load data. Please reload.')); } @@ -165,10 +169,10 @@ export class ContentsService { const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}?publish=${publish}`); return HTTP.postVersioned(this.http, url, dto).pipe( - map(response => { - const body = response.payload.body; + map(({ version, payload }) => { + const body = payload.body; - return new ContentDto( + const content = new ContentDto( body.id, body.status, DateTime.parseISO_UTC(body.created), body.createdBy, @@ -177,7 +181,9 @@ export class ContentsService { body.isPending, null, body.data, - response.version); + version); + + return content; }), tap(() => { this.analytics.trackEvent('Content', 'Created', appName); @@ -189,10 +195,8 @@ export class ContentsService { const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}?asDraft=${asDraft}`); return HTTP.putVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - - return new Versioned(response.version, body); + mapVersioned(payload => { + return payload.body; }), tap(() => { this.analytics.trackEvent('Content', 'Updated', appName); @@ -204,10 +208,8 @@ export class ContentsService { const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}`); return HTTP.patchVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - - return new Versioned(response.version, body); + mapVersioned(payload => { + return payload.body; }), tap(() => { this.analytics.trackEvent('Content', 'Updated', appName); diff --git a/src/Squidex/app/shared/services/contributors.service.spec.ts b/src/Squidex/app/shared/services/contributors.service.spec.ts index 502e753a5..55a92e447 100644 --- a/src/Squidex/app/shared/services/contributors.service.spec.ts +++ b/src/Squidex/app/shared/services/contributors.service.spec.ts @@ -70,11 +70,16 @@ describe('ContributorsService', () => { } }); - expect(contributors!).toEqual( - new ContributorsDto([ - new ContributorDto('123', 'Owner'), - new ContributorDto('456', 'Owner') - ], 100, new Version('2'))); + expect(contributors!).toEqual({ + payload: { + contributors: [ + new ContributorDto('123', 'Owner'), + new ContributorDto('456', 'Owner') + ], + maxContributors: 100 + }, + version: new Version('2') + }); })); it('should make post request to assign contributor', diff --git a/src/Squidex/app/shared/services/contributors.service.ts b/src/Squidex/app/shared/services/contributors.service.ts index 94c9b0f22..690d10818 100644 --- a/src/Squidex/app/shared/services/contributors.service.ts +++ b/src/Squidex/app/shared/services/contributors.service.ts @@ -8,27 +8,23 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { AnalyticsService, ApiUrlConfig, HTTP, + mapVersioned, Model, pretifyError, Version, Versioned } from '@app/framework'; -export class ContributorsDto extends Model { - constructor( - public readonly contributors: ContributorDto[], - public readonly maxContributors: number, - public readonly version: Version - ) { - super(); - } -} +export type ContributorsDto = Versioned<{ + readonly contributors: ContributorDto[], + readonly maxContributors: number +}>; export class ContributorDto extends Model { constructor( @@ -63,18 +59,18 @@ export class ContributorsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + mapVersioned(payload => { + const body = payload.body; const items: any[] = body.contributors; - return new ContributorsDto( - items.map(item => { - return new ContributorDto( + const contributors = + items.map(item => + new ContributorDto( item.contributorId, - item.role); - }), - body.maxContributors, response.version); + item.role)); + + return { contributors, maxContributors: body.maxContributors }; }), pretifyError('Failed to load contributors. Please reload.')); } @@ -83,10 +79,8 @@ export class ContributorsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors`); return HTTP.postVersioned(this.http, url, dto, version).pipe( - map(response => { - const body: any = response.payload.body; - - return new Versioned(response.version, body); + mapVersioned(payload => { + return payload.body; }), tap(() => { this.analytics.trackEvent('Contributor', 'Configured', appName); diff --git a/src/Squidex/app/shared/services/history.service.ts b/src/Squidex/app/shared/services/history.service.ts index b2c00fbae..d79add475 100644 --- a/src/Squidex/app/shared/services/history.service.ts +++ b/src/Squidex/app/shared/services/history.service.ts @@ -82,15 +82,16 @@ export class HistoryService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/history?channel=${channel}`); return this.http.get(url).pipe( - map(response => { - return response.map(item => { - return new HistoryEventDto( + map(body => { + const history = body.map(item => + new HistoryEventDto( item.eventId, item.actor, item.message, item.version, - DateTime.parseISO_UTC(item.created)); - }); + DateTime.parseISO_UTC(item.created))); + + return history; }), pretifyError('Failed to load history. Please reload.')); } diff --git a/src/Squidex/app/shared/services/languages.service.ts b/src/Squidex/app/shared/services/languages.service.ts index d2af87541..ea76d2936 100644 --- a/src/Squidex/app/shared/services/languages.service.ts +++ b/src/Squidex/app/shared/services/languages.service.ts @@ -10,11 +10,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { - ApiUrlConfig, - HTTP, - pretifyError -} from '@app/framework'; +import { ApiUrlConfig, pretifyError } from '@app/framework'; export class LanguageDto { constructor( @@ -35,15 +31,14 @@ export class LanguagesService { public getLanguages(): Observable { const url = this.apiUrl.buildUrl('api/languages'); - return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const items: any[] = response.payload.body; - - return items.map(item => { - return new LanguageDto( + return this.http.get(url).pipe( + map(body => { + const languages = body.map(item => + new LanguageDto( item.iso2Code, - item.englishName); - }); + item.englishName)); + + return languages; }), pretifyError('Failed to load languages. Please reload.')); } diff --git a/src/Squidex/app/shared/services/news.service.ts b/src/Squidex/app/shared/services/news.service.ts index 0a161c9b8..db7e02a5f 100644 --- a/src/Squidex/app/shared/services/news.service.ts +++ b/src/Squidex/app/shared/services/news.service.ts @@ -40,18 +40,18 @@ export class NewsService { const url = this.apiUrl.buildUrl(`api/news/features?version=${version}`); return this.http.get(url).pipe( - map(response => { - const items: any[] = response.features; + map(body => { + const items: any[] = body.features; - return new FeaturesDto( - items.map(item => { - return new FeatureDto( + const features = new FeaturesDto( + items.map(item => + new FeatureDto( item.name, - item.text - ); - }), - response.version - ); + item.text) + ), + body.version); + + return features; }), pretifyError('Failed to load features. Please reload.')); } diff --git a/src/Squidex/app/shared/services/patterns.service.spec.ts b/src/Squidex/app/shared/services/patterns.service.spec.ts index e98ba43a2..3c6800391 100644 --- a/src/Squidex/app/shared/services/patterns.service.spec.ts +++ b/src/Squidex/app/shared/services/patterns.service.spec.ts @@ -69,11 +69,13 @@ describe('PatternsService', () => { } }); - expect(patterns!).toEqual( - new PatternsDto([ + expect(patterns!).toEqual({ + payload: [ new PatternDto('1', 'Number', '[0-9]', 'Message1'), new PatternDto('2', 'Numbers', '[0-9]*', 'Message2') - ], new Version('2'))); + ], + version: new Version('2') + }); })); it('should make post request to add pattern', @@ -93,9 +95,9 @@ describe('PatternsService', () => { expect(req.request.headers.get('If-Match')).toEqual(version.value); req.flush({ + name: 'Number', patternId: '1', pattern: '[0-9]', - name: 'Number', message: 'Message1' }); diff --git a/src/Squidex/app/shared/services/patterns.service.ts b/src/Squidex/app/shared/services/patterns.service.ts index 209c93ede..694999bf3 100644 --- a/src/Squidex/app/shared/services/patterns.service.ts +++ b/src/Squidex/app/shared/services/patterns.service.ts @@ -8,26 +8,20 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { AnalyticsService, ApiUrlConfig, HTTP, + mapVersioned, Model, pretifyError, Version, Versioned } from '@app/framework'; -export class PatternsDto extends Model { - constructor( - public readonly patterns: PatternDto[], - public readonly version: Version - ) { - super(); - } -} +export type PatternsDto = Versioned; export class PatternDto extends Model { constructor( @@ -59,20 +53,18 @@ export class PatternsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/patterns`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const items: any[] = body; - return new PatternsDto( - items.map(item => { - return new PatternDto( + const patterns = + items.map(item => + new PatternDto( item.patternId, item.name, item.pattern, - item.message); - }), - response.version); + item.message)); + + return patterns; }), pretifyError('Failed to add pattern. Please reload.')); } @@ -81,16 +73,14 @@ export class PatternsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/patterns`); return HTTP.postVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const pattern = new PatternDto( body.patternId, body.name, body.pattern, body.message); - return new Versioned(response.version, pattern); + return pattern; }), tap(() => { this.analytics.trackEvent('Patterns', 'Created', appName); diff --git a/src/Squidex/app/shared/services/plans.service.spec.ts b/src/Squidex/app/shared/services/plans.service.spec.ts index 27cb2f149..3369a6425 100644 --- a/src/Squidex/app/shared/services/plans.service.spec.ts +++ b/src/Squidex/app/shared/services/plans.service.spec.ts @@ -54,7 +54,6 @@ describe('PlansService', () => { req.flush({ currentPlanId: '123', - hasPortal: true, planOwner: '456', plans: [ { @@ -77,24 +76,26 @@ describe('PlansService', () => { maxAssetSize: 5500, maxContributors: 6500 } - ] + ], + hasPortal: true }, { headers: { etag: '2' } }); - expect(plans!).toEqual( - new PlansDto( - '123', - '456', - true, - [ + expect(plans!).toEqual({ + payload: { + currentPlanId: '123', + planOwner: '456', + plans: [ new PlanDto('free', 'Free', '14 €', 'free_yearly', '12 €', 1000, 1500, 2500), new PlanDto('prof', 'Prof', '18 €', 'prof_yearly', '16 €', 4000, 5500, 6500) ], - new Version('2') - )); + hasPortal: true + }, + version: new Version('2') + }); })); it('should make put request to change plan', diff --git a/src/Squidex/app/shared/services/plans.service.ts b/src/Squidex/app/shared/services/plans.service.ts index 5298380ee..1d295fc6c 100644 --- a/src/Squidex/app/shared/services/plans.service.ts +++ b/src/Squidex/app/shared/services/plans.service.ts @@ -8,29 +8,25 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { AnalyticsService, ApiUrlConfig, HTTP, + mapVersioned, Model, pretifyError, Version, Versioned } from '@app/framework'; -export class PlansDto extends Model { - constructor( - public readonly currentPlanId: string, - public readonly planOwner: string, - public readonly hasPortal: boolean, - public readonly plans: PlanDto[], - public readonly version: Version - ) { - super(); - } -} +export type PlansDto = Versioned<{ + readonly currentPlanId: string, + readonly planOwner: string, + readonly hasPortal: boolean, + readonly plans: PlanDto[] +}>; export class PlanDto extends Model { constructor( @@ -68,17 +64,16 @@ export class PlansService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/plans`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const items: any[] = body.plans; - return new PlansDto( - body.currentPlanId, - body.planOwner, - body.hasPortal, - items.map(item => { - return new PlanDto( + const { hasPortal, currentPlanId, planOwner } = body; + + const plans = { + currentPlanId, + planOwner, + plans: items.map(item => + new PlanDto( item.id, item.name, item.costs, @@ -86,9 +81,11 @@ export class PlansService { item.yearlyCosts, item.maxApiCalls, item.maxAssetSize, - item.maxContributors); - }), - response.version); + item.maxContributors)), + hasPortal + }; + + return plans; }), pretifyError('Failed to load plans. Please reload.')); } @@ -97,10 +94,8 @@ export class PlansService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/plan`); return HTTP.putVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - - return new Versioned(response.version, body); + mapVersioned(payload => { + return payload.body; }), tap(() => { this.analytics.trackEvent('Plan', 'Changed', appName); diff --git a/src/Squidex/app/shared/services/roles.service.spec.ts b/src/Squidex/app/shared/services/roles.service.spec.ts index cf64c4d0b..91cd3c879 100644 --- a/src/Squidex/app/shared/services/roles.service.spec.ts +++ b/src/Squidex/app/shared/services/roles.service.spec.ts @@ -88,12 +88,13 @@ describe('RolesService', () => { } }); - expect(roles!).toEqual( - new RolesDto([ + expect(roles!).toEqual({ + payload: [ new RoleDto('Role1', 3, 5, ['P1']), new RoleDto('Role2', 7, 9, ['P2']) ], - new Version('2'))); + version: new Version('2') + }); })); it('should make post request to add role', diff --git a/src/Squidex/app/shared/services/roles.service.ts b/src/Squidex/app/shared/services/roles.service.ts index e45ce027c..ac1c27a39 100644 --- a/src/Squidex/app/shared/services/roles.service.ts +++ b/src/Squidex/app/shared/services/roles.service.ts @@ -8,26 +8,20 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { AnalyticsService, ApiUrlConfig, HTTP, + mapVersioned, Model, pretifyError, Version, Versioned } from '@app/framework'; -export class RolesDto extends Model { - constructor( - public readonly roles: RoleDto[], - public readonly version: Version - ) { - super(); - } -} +export type RolesDto = Versioned; export class RoleDto extends Model { constructor( @@ -61,20 +55,17 @@ export class RolesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/roles`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { const items: any[] = body.roles; - const roles = items.map(item => { - return new RoleDto( + const roles = items.map(item => + new RoleDto( item.name, item.numClients, item.numContributors, - item.permissions); - }); + item.permissions)); - return new RolesDto(roles, response.version); + return roles; }), pretifyError('Failed to load roles. Please reload.')); } @@ -83,10 +74,10 @@ export class RolesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/roles`); return HTTP.postVersioned(this.http, url, dto, version).pipe( - map(response => { + mapVersioned(() => { const role = new RoleDto(dto.name, 0, 0, []); - return new Versioned(response.version, role); + return role; }), tap(() => { this.analytics.trackEvent('Role', 'Created', appName); diff --git a/src/Squidex/app/shared/services/rules.service.ts b/src/Squidex/app/shared/services/rules.service.ts index 11b5f6e5a..820f3152b 100644 --- a/src/Squidex/app/shared/services/rules.service.ts +++ b/src/Squidex/app/shared/services/rules.service.ts @@ -132,10 +132,10 @@ export class RulesService { const url = this.apiUrl.buildUrl('api/rules/actions'); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const items: { [name: string]: any } = response.payload.body; + map(({ payload }) => { + const items: { [name: string]: any } = payload.body; - const result: { [name: string]: RuleElementDto } = {}; + const actions: { [name: string]: RuleElementDto } = {}; for (let key of Object.keys(items).sort()) { const value = items[key]; @@ -150,7 +150,7 @@ export class RulesService { property.isRequired )); - result[key] = new RuleElementDto( + actions[key] = new RuleElementDto( value.display, value.description, value.iconColor, @@ -159,7 +159,7 @@ export class RulesService { properties); } - return result; + return actions; }), pretifyError('Failed to load Rules. Please reload.')); } @@ -168,11 +168,11 @@ export class RulesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/rules`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const items: any[] = response.payload.body; + map(({ payload }) => { + const items: any[] = payload.body; - return items.map(item => { - return new RuleDto( + const rules = items.map(item => + new RuleDto( item.id, item.createdBy, item.lastModifiedBy, @@ -183,8 +183,9 @@ export class RulesService { item.trigger, item.trigger.triggerType, item.action, - item.action.actionType); - }); + item.action.actionType)); + + return rules; }), pretifyError('Failed to load Rules. Please reload.')); } @@ -193,8 +194,8 @@ export class RulesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/rules`); return HTTP.postVersioned(this.http, url, dto).pipe( - map(response => { - const body = response.payload.body; + map(({ version, payload }) => { + const body = payload.body; return new RuleDto( body.id, @@ -202,7 +203,7 @@ export class RulesService { user, now, now, - response.version, + version, true, dto.trigger, dto.trigger.triggerType, @@ -259,13 +260,13 @@ export class RulesService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/rules/events?take=${take}&skip=${skip}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ payload }) => { + const body = payload.body; const items: any[] = body.items; - return new RuleEventsDto(body.total, items.map(item => { - return new RuleEventDto( + const ruleEvents = new RuleEventsDto(body.total, items.map(item => + new RuleEventDto( item.id, DateTime.parseISO_UTC(item.created), item.nextAttempt ? DateTime.parseISO_UTC(item.nextAttempt) : null, @@ -274,8 +275,9 @@ export class RulesService { item.lastDump, item.result, item.jobResult, - item.numCalls); - })); + item.numCalls))); + + return ruleEvents; }), pretifyError('Failed to load events. Please reload.')); } diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index 863f9b95f..b3da2159d 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -15,6 +15,7 @@ import { ApiUrlConfig, DateTime, HTTP, + mapVersioned, Model, pretifyError, StringHelper, @@ -215,12 +216,12 @@ export class SchemasService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ payload }) => { + const body = payload.body; const items: any[] = body; - return items.map(item => { + const schemas = items.map(item => { const properties = new SchemaPropertiesDto(item.properties.label, item.properties.hints); return new SchemaDto( @@ -233,6 +234,8 @@ export class SchemasService { DateTime.parseISO_UTC(item.lastModified), item.lastModifiedBy, new Version(item.version.toString())); }); + + return schemas; }), pretifyError('Failed to load schemas. Please reload.')); } @@ -241,8 +244,8 @@ export class SchemasService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${id}`); return HTTP.getVersioned(this.http, url).pipe( - map(response => { - const body = response.payload.body; + map(({ version, payload }) => { + const body = payload.body; const fields = body.fields.map((item: any) => { const propertiesDto = @@ -292,7 +295,7 @@ export class SchemasService { body.isPublished, DateTime.parseISO_UTC(body.created), body.createdBy, DateTime.parseISO_UTC(body.lastModified), body.lastModifiedBy, - response.version, + version, fields, body.scripts || {}, body.previewUrls || {}); @@ -304,22 +307,23 @@ export class SchemasService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas`); return HTTP.postVersioned(this.http, url, dto).pipe( - map(response => { - const body = response.payload.body; + map(({ version, payload }) => { + const body = payload.body; now = now || DateTime.now(); - return new SchemaDetailsDto( + const schema = new SchemaDetailsDto( body.id, - dto.name, - '', + dto.name, '', dto.properties || new SchemaPropertiesDto(), dto.isSingleton === true, false, now, user, now, user, - response.version, + version, dto.fields || []); + + return schema; }), tap(() => { this.analytics.trackEvent('Schema', 'Created', appName); @@ -401,17 +405,15 @@ export class SchemasService { const url = this.buildUrl(appName, schemaName, parentId, ''); return HTTP.postVersioned(this.http, url, dto, version).pipe( - map(response => { - const body = response.payload.body; - + mapVersioned(({ body }) => { if (parentId) { const field = new NestedFieldDto(body.id, dto.name, dto.properties, parentId); - return new Versioned(response.version, field); + return field; } else { const field = new RootFieldDto(body.id, dto.name, dto.properties, dto.partitioning); - return new Versioned(response.version, field); + return field; } }), tap(() => { diff --git a/src/Squidex/app/shared/services/translations.service.ts b/src/Squidex/app/shared/services/translations.service.ts index b6dd270de..b5b91897d 100644 --- a/src/Squidex/app/shared/services/translations.service.ts +++ b/src/Squidex/app/shared/services/translations.service.ts @@ -38,8 +38,8 @@ export class TranslationsService { const url = this.apiUrl.buildUrl(`api/apps/${appName}/translations`); return this.http.post(url, request).pipe( - map(response => { - return new TranslationDto(response.result, response.text); + map(body => { + return new TranslationDto(body.result, body.text); }), pretifyError('Failed to translate text. Please reload.')); } diff --git a/src/Squidex/app/shared/services/usages.service.ts b/src/Squidex/app/shared/services/usages.service.ts index 2ba97a36f..dbd004aae 100644 --- a/src/Squidex/app/shared/services/usages.service.ts +++ b/src/Squidex/app/shared/services/usages.service.ts @@ -62,8 +62,8 @@ export class UsagesService { const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/log`); return this.http.get(url).pipe( - map(response => { - return response.downloadUrl; + map(body => { + return body.downloadUrl; }), pretifyError('Failed to load monthly api calls. Please reload.')); } @@ -72,8 +72,8 @@ export class UsagesService { const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/calls/month`); return this.http.get(url).pipe( - map(response => { - return new CurrentCallsDto(response.count, response.maxAllowed); + map(body => { + return new CurrentCallsDto(body.count, body.maxAllowed); }), pretifyError('Failed to load monthly api calls. Please reload.')); } @@ -82,8 +82,8 @@ export class UsagesService { const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/storage/today`); return this.http.get(url).pipe( - map(response => { - return new CurrentStorageDto(response.size, response.maxAllowed); + map(body => { + return new CurrentStorageDto(body.size, body.maxAllowed); }), pretifyError('Failed to load todays storage size. Please reload.')); } @@ -92,18 +92,18 @@ export class UsagesService { const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/calls/${fromDate.toUTCStringFormat('YYYY-MM-DD')}/${toDate.toUTCStringFormat('YYYY-MM-DD')}`); return this.http.get(url).pipe( - map(response => { - const result: { [category: string]: CallsUsageDto[] } = {}; + map(body => { + const usages: { [category: string]: CallsUsageDto[] } = {}; - for (let category of Object.keys(response)) { - result[category] = response[category].map((item: any) => { - return new CallsUsageDto( + for (let category of Object.keys(body)) { + usages[category] = body[category].map((item: any) => + new CallsUsageDto( DateTime.parseISO_UTC(item.date), item.count, - item.averageMs); - }); + item.averageMs)); } - return result; + + return usages; }), pretifyError('Failed to load calls usage. Please reload.')); } @@ -112,13 +112,14 @@ export class UsagesService { const url = this.apiUrl.buildUrl(`api/apps/${app}/usages/storage/${fromDate.toUTCStringFormat('YYYY-MM-DD')}/${toDate.toUTCStringFormat('YYYY-MM-DD')}`); return this.http.get(url).pipe( - map(response => { - return response.map(item => { - return new StorageUsageDto( + map(body => { + const usages = body.map(item => + new StorageUsageDto( DateTime.parseISO_UTC(item.date), item.count, - item.size); - }); + item.size)); + + return usages; }), pretifyError('Failed to load storage usage. Please reload.')); } diff --git a/src/Squidex/app/shared/services/users.service.ts b/src/Squidex/app/shared/services/users.service.ts index c11889dde..4a6462eb1 100644 --- a/src/Squidex/app/shared/services/users.service.ts +++ b/src/Squidex/app/shared/services/users.service.ts @@ -32,12 +32,13 @@ export class UsersService { const url = this.apiUrl.buildUrl(`api/users?query=${query || ''}`); return this.http.get(url).pipe( - map(response => { - return response.map(item => { - return new UserDto( + map(body => { + const users = body.map(item => + new UserDto( item.id, - item.displayName); - }); + item.displayName)); + + return users; }), pretifyError('Failed to load users. Please reload.')); } @@ -46,10 +47,12 @@ export class UsersService { const url = this.apiUrl.buildUrl(`api/users/${id}`); return this.http.get(url).pipe( - map(response => { - return new UserDto( - response.id, - response.displayName); + map(body => { + const user = new UserDto( + body.id, + body.displayName); + + return user; }), pretifyError('Failed to load user. Please reload.')); } diff --git a/src/Squidex/app/shared/state/apps.state.spec.ts b/src/Squidex/app/shared/state/apps.state.spec.ts index 42b547fbd..67d7009ed 100644 --- a/src/Squidex/app/shared/state/apps.state.spec.ts +++ b/src/Squidex/app/shared/state/apps.state.spec.ts @@ -6,7 +6,7 @@ */ import { of } from 'rxjs'; -import { IMock, Mock, Times } from 'typemoq'; +import { IMock, Mock } from 'typemoq'; import { AppDto, @@ -95,7 +95,7 @@ describe('AppsState', () => { expect(appsState.snapshot.apps.values).toEqual([newApp, ...oldApps]); }); - it('should remove app from snashot when archived', () => { + it('should remove app from snapshot when archived', () => { const request = { ...newApp }; appsService.setup(x => x.postApp(request)) @@ -115,4 +115,20 @@ describe('AppsState', () => { expect(appsAfterCreate).toEqual([newApp, ...oldApps]); expect(appsAfterDelete).toEqual(oldApps); }); + + it('should selected app from snapshot when archived', () => { + const request = { ...newApp }; + + appsService.setup(x => x.postApp(request)) + .returns(() => of(newApp)).verifiable(); + + appsService.setup(x => x.deleteApp(newApp.name)) + .returns(() => of({})).verifiable(); + + appsState.create(request).subscribe(); + appsState.select(newApp.name).subscribe(); + appsState.delete(newApp.name).subscribe(); + + expect(appsState.snapshot.selectedApp).toBeNull(); + }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/apps.state.ts b/src/Squidex/app/shared/state/apps.state.ts index 4da6f9dcd..451ded8b3 100644 --- a/src/Squidex/app/shared/state/apps.state.ts +++ b/src/Squidex/app/shared/state/apps.state.ts @@ -7,11 +7,12 @@ import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, + shareSubscribed, State } from '@app/framework'; @@ -23,14 +24,12 @@ import { interface Snapshot { // All apps, loaded once. - apps: AppsList; + apps: ImmutableArray; // The selected app. selectedApp: AppDto | null; } -type AppsList = ImmutableArray; - function sameApp(lhs: AppDto, rhs?: AppDto): boolean { return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id); } @@ -57,78 +56,52 @@ export class AppsState extends State { } public select(name: string | null): Observable { - const http$ = - this.loadApp(name) - .pipe(share()); - - http$.subscribe(selectedApp => { - this.next(s => ({ ...s, selectedApp })); - }); - - return http$; - } - - private loadApp(name: string | null) { - return of(name ? this.snapshot.apps.find(x => x.name === name) || null : null); + const observable = + !name ? + of(null) : + of(this.snapshot.apps.find(x => x.name === name) || null); + + return observable.pipe( + tap(selectedApp => { + this.next(s => ({ ...s, selectedApp })); + })); } public load(): Observable { - const http$ = - this.appsService.getApps().pipe( - share()); - - http$.subscribe(response => { - this.next(s => { - const apps = ImmutableArray.of(response).sortByStringAsc(x => x.name); - - return { ...s, apps }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.appsService.getApps().pipe( + tap((dto: AppDto[]) => { + this.next(s => { + const apps = ImmutableArray.of(dto); + + return { ...s, apps }; + }); + }), + shareSubscribed(this.dialogs)); } public create(request: CreateAppDto): Observable { - const http$ = - this.appsService.postApp(request).pipe( - share()); - - http$.subscribe(app => { - this.next(s => { - const apps = s.apps.push(app).sortByStringAsc(x => x.name); - - return { ...s, apps }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.appsService.postApp(request).pipe( + tap(dto => { + this.next(s => { + const apps = s.apps.push(dto).sortByStringAsc(x => x.name); + + return { ...s, apps }; + }); + }), + shareSubscribed(this.dialogs, { silent: true })); } public delete(name: string): Observable { - const http$ = - this.appsService.deleteApp(name).pipe( - share()); - - http$.subscribe(() => { - this.next(s => { - const apps = s.apps.filter(x => x.name !== name); - - const selectedApp = - s.selectedApp && - s.selectedApp.name === name ? - null : - s.selectedApp; - - return { ...s, apps, selectedApp }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.appsService.deleteApp(name).pipe( + tap(() => { + this.next(s => { + const apps = s.apps.filter(x => x.name !== name); + + const selectedApp = s.selectedApp && s.selectedApp.name === name ? null : s.selectedApp; + + return { ...s, apps, selectedApp }; + }); + }), + shareSubscribed(this.dialogs)); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index 702954a2f..6372e02ef 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -14,7 +14,7 @@ import { AssetsService, AssetsState, DialogService, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -98,7 +98,7 @@ describe('AssetsState', () => { it('should remove asset from snapshot when deleted', () => { assetsService.setup(x => x.deleteAsset(app, oldAssets[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(versioned(newVersion))); assetsState.delete(oldAssets[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/assets.state.ts b/src/Squidex/app/shared/state/assets.state.ts index 5c6fb58cd..3beab3093 100644 --- a/src/Squidex/app/shared/state/assets.state.ts +++ b/src/Squidex/app/shared/state/assets.state.ts @@ -12,8 +12,8 @@ import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, Pager, + shareSubscribed, State } from '@app/framework'; @@ -107,7 +107,7 @@ export class AssetsState extends State { return { ...s, assets, assetsPager, isLoaded: true, tags: dtos[1] }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public add(asset: AssetDto) { @@ -138,7 +138,7 @@ export class AssetsState extends State { return { ...s, assets, assetsPager, tags, tagsSelected }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public update(asset: AssetDto) { diff --git a/src/Squidex/app/shared/state/backups.state.ts b/src/Squidex/app/shared/state/backups.state.ts index dedb7054b..90897dabd 100644 --- a/src/Squidex/app/shared/state/backups.state.ts +++ b/src/Squidex/app/shared/state/backups.state.ts @@ -7,11 +7,12 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, + shareSubscribed, State } from '@app/framework'; @@ -56,55 +57,35 @@ export class BackupsState extends State { this.resetState(); } - const http$ = - this.backupsService.getBackups(this.appName).pipe( - share()); + return this.backupsService.getBackups(this.appName).pipe( + tap(payload => { + if (isReload && !silent) { + this.dialogs.notifyInfo('Backups reloaded.'); + } - http$.subscribe(dtos => { - if (isReload && !silent) { - this.dialogs.notifyInfo('Backups reloaded.'); - } + this.next(s => { + const backups = ImmutableArray.of(payload); - this.next(s => { - const backups = ImmutableArray.of(dtos); - - return { ...s, backups, isLoaded: true }; - }); - }, error => { - if (!silent) { - this.dialogs.notifyError(error); - } - }); - - return http$; + return { ...s, backups, isLoaded: true }; + }); + }), + shareSubscribed(this.dialogs, { silent })); } public start(): Observable { - const http$ = - this.backupsService.postBackup(this.appsState.appName).pipe( - share()); - - http$.subscribe(() => { - this.dialogs.notifyInfo('Backup started, it can take several minutes to complete.'); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.backupsService.postBackup(this.appsState.appName).pipe( + tap(() => { + this.dialogs.notifyInfo('Backup started, it can take several minutes to complete.'); + }), + shareSubscribed(this.dialogs)); } public delete(backup: BackupDto): Observable { - const http$ = - this.backupsService.deleteBackup(this.appsState.appName, backup.id).pipe( - share()); - - http$.subscribe(() => { - this.dialogs.notifyInfo('Backup is about to be deleted.'); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.backupsService.deleteBackup(this.appsState.appName, backup.id).pipe( + tap(() => { + this.dialogs.notifyInfo('Backup is about to be deleted.'); + }), + shareSubscribed(this.dialogs)); } private get appName() { diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index b16b78325..8b7e65f58 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -10,11 +10,10 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { ClientDto, - ClientsDto, ClientsService, ClientsState, DialogService, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -50,7 +49,7 @@ describe('ClientsState', () => { describe('Loading', () => { it('should load clients', () => { clientsService.setup(x => x.getClients(app)) - .returns(() => of(new ClientsDto(oldClients, version))).verifiable(); + .returns(() => of(versioned(version, oldClients))).verifiable(); clientsState.load().subscribe(); @@ -63,7 +62,7 @@ describe('ClientsState', () => { it('should show notification on load when reload is true', () => { clientsService.setup(x => x.getClients(app)) - .returns(() => of(new ClientsDto(oldClients, version))).verifiable(); + .returns(() => of(versioned(version, oldClients))).verifiable(); clientsState.load(true).subscribe(); @@ -76,7 +75,7 @@ describe('ClientsState', () => { describe('Updates', () => { beforeEach(() => { clientsService.setup(x => x.getClients(app)) - .returns(() => of(new ClientsDto(oldClients, version))).verifiable(); + .returns(() => of(versioned(version, oldClients))).verifiable(); clientsState.load().subscribe(); }); @@ -87,7 +86,7 @@ describe('ClientsState', () => { const request = { id: 'id3' }; clientsService.setup(x => x.postClient(app, request, version)) - .returns(() => of(new Versioned(newVersion, newClient))).verifiable(); + .returns(() => of(versioned(newVersion, newClient))).verifiable(); clientsState.attach(request).subscribe(); @@ -99,7 +98,7 @@ describe('ClientsState', () => { const request = { name: 'NewName', role: 'NewRole' }; clientsService.setup(x => x.putClient(app, oldClients[0].id, request, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); clientsState.update(oldClients[0], request).subscribe(); @@ -112,7 +111,7 @@ describe('ClientsState', () => { it('should remove client from snapshot when revoked', () => { clientsService.setup(x => x.deleteClient(app, oldClients[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); clientsState.revoke(oldClients[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/clients.state.ts b/src/Squidex/app/shared/state/clients.state.ts index c8f185f80..a9a869c4d 100644 --- a/src/Squidex/app/shared/state/clients.state.ts +++ b/src/Squidex/app/shared/state/clients.state.ts @@ -9,11 +9,13 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, + mapVersioned, + shareSubscribed, State, Version } from '@app/framework'; @@ -63,71 +65,56 @@ export class ClientsState extends State { this.resetState(); } - const http$ = - this.clientsService.getClients(this.appName).pipe( - share()); + return this.clientsService.getClients(this.appName).pipe( + tap(({ version, payload: newClients }) => { + if (isReload) { + this.dialogs.notifyInfo('Clients reloaded.'); + } - http$.subscribe(response => { - if (isReload) { - this.dialogs.notifyInfo('Clients reloaded.'); - } + const clients = ImmutableArray.of(newClients); - const clients = ImmutableArray.of(response.clients); - - this.next(s => { - return { ...s, clients, isLoaded: true, version: response.version }; - }); - }); - - return http$; + this.next(s => { + return { ...s, clients, isLoaded: true, version }; + }); + }), + shareSubscribed(this.dialogs)); } public attach(request: CreateClientDto): Observable { - const http$ = - this.clientsService.postClient(this.appName, request, this.version).pipe( - share()); - - http$.subscribe(({ version, payload }) => { - this.next(s => { - const clients = s.clients.push(payload); - - return { ...s, clients, version: version }; - }); - }); - - return http$.pipe(map(x => x.payload)); + return this.clientsService.postClient(this.appName, request, this.version).pipe( + tap(({ version, payload }) => { + this.next(s => { + const clients = s.clients.push(payload); + + return { ...s, clients, version: version }; + }); + }), + shareSubscribed(this.dialogs, { project: x => x.payload })); } public revoke(client: ClientDto): Observable { - const http$ = - this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( - share()); - - http$.subscribe(({ version }) => { - this.next(s => { - const clients = s.clients.filter(c => c.id !== client.id); - - return { ...s, clients, version }; - }); - }); - - return http$; + return this.clientsService.deleteClient(this.appName, client.id, this.version).pipe( + tap(({ version }) => { + this.next(s => { + const clients = s.clients.filter(c => c.id !== client.id); + + return { ...s, clients, version }; + }); + }), + shareSubscribed(this.dialogs)); } public update(client: ClientDto, request: UpdateClientDto): Observable { - const http$ = - this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( - map(({ version }) => ({ version, client: update(client, request) })), share()); - - http$.subscribe(({ version, client }) => { - this.next(s => { - const clients = s.clients.replaceBy('id', client); - - return { ...s, clients, version }; - }); - }); - - return http$.pipe(map(x => x.client)); + return this.clientsService.putClient(this.appName, client.id, request, this.version).pipe( + mapVersioned(() => update(client, request)), + tap(({ version, payload }) => { + this.next(s => { + const clients = s.clients.replaceBy('id', payload); + + return { ...s, clients, version }; + }); + }), + shareSubscribed(this.dialogs, { project: x => x.payload })); } private get appName() { diff --git a/src/Squidex/app/shared/state/comments.state.ts b/src/Squidex/app/shared/state/comments.state.ts index d0701942c..42bc497c5 100644 --- a/src/Squidex/app/shared/state/comments.state.ts +++ b/src/Squidex/app/shared/state/comments.state.ts @@ -6,12 +6,13 @@ */ import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DateTime, DialogService, ImmutableArray, + shareSubscribed, State, Version } from '@app/framework'; @@ -51,89 +52,66 @@ export class CommentsState extends State { } public load(): Observable { - const http$ = - this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe( - share()); - - http$.subscribe(response => { - this.next(s => { - let comments = s.comments; - - for (let created of response.createdComments) { - if (!comments.find(x => x.id === created.id)) { - comments = comments.push(created); + return this.commentsService.getComments(this.appName, this.commentsId, this.version).pipe( + tap(payload => { + this.next(s => { + let comments = s.comments; + + for (let created of payload.createdComments) { + if (!comments.find(x => x.id === created.id)) { + comments = comments.push(created); + } } - } - - for (let updated of response.updatedComments) { - comments = comments.replaceBy('id', updated); - } - for (let deleted of response.deletedComments) { - comments = comments.filter(x => x.id !== deleted); - } + for (let updated of payload.updatedComments) { + comments = comments.replaceBy('id', updated); + } - return { ...s, comments, isLoaded: true, version: response.version }; - }); - }, error => { - this.dialogs.notifyError(error); - }); + for (let deleted of payload.deletedComments) { + comments = comments.filter(x => x.id !== deleted); + } - return http$; + return { ...s, comments, isLoaded: true, version: payload.version }; + }); + }), + shareSubscribed(this.dialogs)); } public create(text: string): Observable { - const http$ = - this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( - share()); - - http$.subscribe(comment => { - this.next(s => { - const comments = s.comments.push(comment); - - return { ...s, comments }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; - } - - public update(comment: CommentDto, text: string, now?: DateTime): Observable { - const http$ = - this.commentsService.putComment(this.appName, this.commentsId, comment.id, { text }).pipe( - map(() => update(comment, text, now || DateTime.now())), share()); - - http$.subscribe(updated => { - this.next(s => { - const comments = s.comments.replaceBy('id', updated); - - return { ...s, comments }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.commentsService.postComment(this.appName, this.commentsId, { text }).pipe( + tap(comment => { + this.next(s => { + const comments = s.comments.push(comment); + + return { ...s, comments }; + }); + }), + shareSubscribed(this.dialogs)); } public delete(comment: CommentDto): Observable { - const http$ = - this.commentsService.deleteComment(this.appName, this.commentsId, comment.id).pipe( - share()); - - http$.subscribe(() => { - this.next(s => { - const comments = s.comments.removeBy('id', comment); - - return { ...s, comments }; - }); - }, error => { - this.dialogs.notifyError(error); - }); + return this.commentsService.deleteComment(this.appName, this.commentsId, comment.id).pipe( + tap(() => { + this.next(s => { + const comments = s.comments.removeBy('id', comment); + + return { ...s, comments }; + }); + }), + shareSubscribed(this.dialogs)); + } - return http$; + public update(comment: CommentDto, text: string, now?: DateTime): Observable { + return this.commentsService.putComment(this.appName, this.commentsId, comment.id, { text }).pipe( + map(() => update(comment, text, now || DateTime.now())), + tap(updated => { + this.next(s => { + const comments = s.comments.replaceBy('id', updated); + + return { ...s, comments }; + }); + }), + shareSubscribed(this.dialogs)); } private get version() { diff --git a/src/Squidex/app/shared/state/contents.state.ts b/src/Squidex/app/shared/state/contents.state.ts index f93e04e9a..f097ce986 100644 --- a/src/Squidex/app/shared/state/contents.state.ts +++ b/src/Squidex/app/shared/state/contents.state.ts @@ -16,6 +16,7 @@ import { ImmutableArray, notify, Pager, + shareSubscribed, State, Version, Versioned @@ -142,10 +143,10 @@ export abstract class ContentsStateBase extends State { return { ...s, contents, contentsPager, selectedContent, isLoaded: true }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public create(request: any, publish: boolean) { + public create(request: any, publish: boolean): Observable { return this.contentsService.postContent(this.appName, this.schemaName, request, publish).pipe( tap(dto => { this.dialogs.notifyInfo('Contents created successfully.'); @@ -157,7 +158,7 @@ export abstract class ContentsStateBase extends State { return { ...s, contents, contentsPager }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public changeManyStatus(contents: ContentDto[], action: string, dueTime: string | null): Observable { @@ -205,7 +206,7 @@ export abstract class ContentsStateBase extends State { this.replaceContent(confirmChanges(content, this.user, dto.version, now)); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public changeStatus(content: ContentDto, action: string, status: string, dueTime: string | null, now?: DateTime): Observable { @@ -219,7 +220,7 @@ export abstract class ContentsStateBase extends State { this.replaceContent(changeStatus(content, status, this.user, dto.version, now)); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public update(content: ContentDto, request: any, now?: DateTime): Observable { @@ -231,7 +232,7 @@ export abstract class ContentsStateBase extends State { this.replaceContent(updateData(content, dto.payload, this.user, dto.version, now)); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public proposeUpdate(content: ContentDto, request: any, now?: DateTime): Observable { @@ -243,7 +244,7 @@ export abstract class ContentsStateBase extends State { this.replaceContent(updateDataDraft(content, dto.payload, this.user, dto.version, now)); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public discardChanges(content: ContentDto, now?: DateTime): Observable { @@ -255,7 +256,7 @@ export abstract class ContentsStateBase extends State { this.replaceContent(discardChanges(content, this.user, dto.version, now)); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public patch(content: ContentDto, request: any, now?: DateTime): Observable { @@ -267,7 +268,7 @@ export abstract class ContentsStateBase extends State { this.replaceContent(updateData(content, dto.payload, this.user, dto.version, now)); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } private replaceContent(content: ContentDto) { diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index 0633cbc0c..8883ea1b2 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -10,11 +10,10 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { ContributorDto, - ContributorsDto, ContributorsService, ContributorsState, DialogService, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -52,7 +51,7 @@ describe('ContributorsState', () => { describe('Loading', () => { it('should load contributors', () => { contributorsService.setup(x => x.getContributors(app)) - .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(); + .returns(() => of(versioned(version, { contributors: oldContributors, maxContributors: 3 }))).verifiable(); contributorsState.load().subscribe(); @@ -70,7 +69,7 @@ describe('ContributorsState', () => { it('should show notification on load when reload is true', () => { contributorsService.setup(x => x.getContributors(app)) - .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(); + .returns(() => of(versioned(version, { contributors: oldContributors, maxContributors: 3 }))).verifiable(); contributorsState.load(true).subscribe(); @@ -83,7 +82,7 @@ describe('ContributorsState', () => { describe('Updates', () => { beforeEach(() => { contributorsService.setup(x => x.getContributors(app)) - .returns(() => of(new ContributorsDto(oldContributors, 3, version))).verifiable(); + .returns(() => of(versioned(version, { contributors: oldContributors, maxContributors: 3 }))).verifiable(); contributorsState.load().subscribe(); }); @@ -95,7 +94,7 @@ describe('ContributorsState', () => { const response = { contributorId: newContributor.contributorId, isCreated: true }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, response))).verifiable(); + .returns(() => of(versioned(newVersion, response))).verifiable(); contributorsState.assign(request).subscribe(); @@ -116,7 +115,7 @@ describe('ContributorsState', () => { const response = { contributorId: newContributor.contributorId, isCreated: true }; contributorsService.setup(x => x.postContributor(app, request, version)) - .returns(() => of(new Versioned(newVersion, response))).verifiable(); + .returns(() => of(versioned(newVersion, response))).verifiable(); contributorsState.assign(request).subscribe(); @@ -131,7 +130,7 @@ describe('ContributorsState', () => { it('should remove contributor from snapshot when revoked', () => { contributorsService.setup(x => x.deleteContributor(app, oldContributors[0].contributorId, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); contributorsState.revoke(oldContributors[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/contributors.state.ts b/src/Squidex/app/shared/state/contributors.state.ts index 3571bf1ed..0f6326d83 100644 --- a/src/Squidex/app/shared/state/contributors.state.ts +++ b/src/Squidex/app/shared/state/contributors.state.ts @@ -7,12 +7,13 @@ import { Injectable } from '@angular/core'; import { Observable, throwError } from 'rxjs'; -import { catchError, distinctUntilChanged, map, share } from 'rxjs/operators'; +import { catchError, distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ErrorDto, ImmutableArray, + shareSubscribed, State, Types, Version @@ -86,62 +87,44 @@ export class ContributorsState extends State { this.resetState(); } - const http$ = - this.contributorsService.getContributors(this.appName).pipe( - share()); + return this.contributorsService.getContributors(this.appName).pipe( + tap(({ version, payload }) => { + if (isReload) { + this.dialogs.notifyInfo('Contributors reloaded.'); + } - http$.subscribe(response => { - if (isReload) { - this.dialogs.notifyInfo('Contributors reloaded.'); - } + const contributors = ImmutableArray.of(payload.contributors.map(x => this.createContributor(x))); - const contributors = ImmutableArray.of(response.contributors.map(x => this.createContributor(x))); - - this.replaceContributors(contributors, response.version, response.maxContributors); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + this.replaceContributors(contributors, version, payload.maxContributors); + }), + shareSubscribed(this.dialogs)); } public revoke(contributor: ContributorDto): Observable { - const http$ = - this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( - share()); - - http$.subscribe(({ version }) => { - const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId); + return this.contributorsService.deleteContributor(this.appName, contributor.contributorId, this.version).pipe( + tap(({ version }) => { + const contributors = this.snapshot.contributors.filter(x => x.contributor.contributorId !== contributor.contributorId); - this.replaceContributors(contributors, version); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + this.replaceContributors(contributors, version); + }), + shareSubscribed(this.dialogs)); } public assign(request: AssignContributorDto): Observable { - const http$ = - this.contributorsService.postContributor(this.appName, request, this.version).pipe( - catchError(error => { - if (Types.is(error, ErrorDto) && error.statusCode === 404) { - return throwError(new ErrorDto(404, 'The user does not exist.')); - } else { - return throwError(error); - } - }), - share()); - - http$.subscribe(({ payload, version }) => { - const contributors = this.updateContributors(payload.contributorId, request.role); - - this.replaceContributors(contributors, version); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$.pipe(map(x => x.payload.isCreated)); + return this.contributorsService.postContributor(this.appName, request, this.version).pipe( + catchError(error => { + if (Types.is(error, ErrorDto) && error.statusCode === 404) { + return throwError(new ErrorDto(404, 'The user does not exist.')); + } else { + return throwError(error); + } + }), + tap(({ version, payload }) => { + const contributors = this.updateContributors(payload.contributorId, request.role); + + this.replaceContributors(contributors, version); + }), + shareSubscribed(this.dialogs, { project: x => x.payload.isCreated })); } private updateContributors(id: string, role: string) { diff --git a/src/Squidex/app/shared/state/languages.state.spec.ts b/src/Squidex/app/shared/state/languages.state.spec.ts index 4fbf63d6a..a4ab191cd 100644 --- a/src/Squidex/app/shared/state/languages.state.spec.ts +++ b/src/Squidex/app/shared/state/languages.state.spec.ts @@ -10,14 +10,13 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { AppLanguageDto, - AppLanguagesDto, AppLanguagesService, DialogService, ImmutableArray, LanguageDto, LanguagesService, LanguagesState, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -56,7 +55,7 @@ describe('LanguagesState', () => { languagesService = Mock.ofType(); languagesService.setup(x => x.getLanguages(app)) - .returns(() => of(new AppLanguagesDto(oldLanguages, version))).verifiable(); + .returns(() => of({ payload: oldLanguages, version })).verifiable(); languagesState = new LanguagesState(languagesService.object, appsState.object, dialogs.object, allLanguagesService.object); }); @@ -107,7 +106,7 @@ describe('LanguagesState', () => { const newLanguage = new AppLanguageDto(languageIT.iso2Code, languageIT.englishName, false, false, []); languagesService.setup(x => x.postLanguage(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, newLanguage))).verifiable(); + .returns(() => of(versioned(newVersion, newLanguage))).verifiable(); languagesState.add(languageIT).subscribe(); @@ -134,7 +133,7 @@ describe('LanguagesState', () => { const request = { isMaster: true, isOptional: false, fallback: [] }; languagesService.setup(x => x.putLanguage(app, oldLanguages[1].iso2Code, request, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); languagesState.update(oldLanguages[1], request).subscribe(); @@ -158,7 +157,7 @@ describe('LanguagesState', () => { it('should remove language from snapshot when deleted', () => { languagesService.setup(x => x.deleteLanguage(app, oldLanguages[1].iso2Code, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); languagesState.remove(oldLanguages[1]).subscribe(); diff --git a/src/Squidex/app/shared/state/languages.state.ts b/src/Squidex/app/shared/state/languages.state.ts index e414c5e0c..446708c10 100644 --- a/src/Squidex/app/shared/state/languages.state.ts +++ b/src/Squidex/app/shared/state/languages.state.ts @@ -7,12 +7,13 @@ import { Injectable } from '@angular/core'; import { forkJoin, Observable } from 'rxjs'; -import { distinctUntilChanged, map, share, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, + mapVersioned, + shareSubscribed, State, Version } from '@app/framework'; @@ -95,57 +96,51 @@ export class LanguagesState extends State { this.resetState(); } - const http$ = - forkJoin( + return forkJoin( this.languagesService.getLanguages(), this.appLanguagesService.getLanguages(this.appName)).pipe( - map(args => { - return { allLanguages: args[0], languages: args[1] }; - }), - share()); - - http$.subscribe(response => { - if (isReload) { - this.dialogs.notifyInfo('Languages reloaded.'); - } - - const sorted = ImmutableArray.of(response.allLanguages).sortByStringAsc(x => x.englishName); - - this.replaceLanguages(ImmutableArray.of(response.languages.languages), response.languages.version, sorted); + map(args => { + return { allLanguages: args[0], languages: args[1] }; + }), + tap(({ allLanguages, languages }) => { + if (isReload) { + this.dialogs.notifyInfo('Languages reloaded.'); + } - }, error => { - this.dialogs.notifyError(error); - }); + const sorted = ImmutableArray.of(allLanguages).sortByStringAsc(x => x.englishName); - return http$; + this.replaceLanguages(ImmutableArray.of(languages.payload), languages.version, sorted); + }), + shareSubscribed(this.dialogs)); } - public add(language: LanguageDto): Observable { + public add(language: LanguageDto): Observable { return this.appLanguagesService.postLanguage(this.appName, { language: language.iso2Code }, this.version).pipe( - tap(dto => { - const languages = this.snapshot.plainLanguages.push(dto.payload).sortByStringAsc(x => x.englishName); + tap(({ version, payload }) => { + const languages = this.snapshot.plainLanguages.push(payload).sortByStringAsc(x => x.englishName); - this.replaceLanguages(languages, dto.version); + this.replaceLanguages(languages, version); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } public remove(language: AppLanguageDto): Observable { return this.appLanguagesService.deleteLanguage(this.appName, language.iso2Code, this.version).pipe( - tap(dto => { + tap(({ version }) => { const languages = this.snapshot.plainLanguages.filter(x => x.iso2Code !== language.iso2Code); - this.replaceLanguages(languages, dto.version); + this.replaceLanguages(languages, version); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public update(language: AppLanguageDto, request: UpdateAppLanguageDto): Observable { + public update(language: AppLanguageDto, request: UpdateAppLanguageDto): Observable { return this.appLanguagesService.putLanguage(this.appName, language.iso2Code, request, this.version).pipe( - tap(dto => { + mapVersioned(() => update(language, request)), + tap(({ version, payload }) => { const languages = this.snapshot.plainLanguages.map(x => { if (x.iso2Code === language.iso2Code) { - return update(x, request); + return payload; } else if (x.isMaster && request.isMaster) { return update(x, { isMaster: false }); } else { @@ -153,9 +148,9 @@ export class LanguagesState extends State { } }); - this.replaceLanguages(languages, dto.version); + this.replaceLanguages(languages, version); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } private replaceLanguages(languages: AppLanguagesList, version: Version, allLanguages?: LanguageList) { diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index d92a2db72..eb4179837 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -11,10 +11,9 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { DialogService, PatternDto, - PatternsDto, PatternsService, PatternsState, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -50,7 +49,7 @@ describe('PatternsState', () => { describe('Loading', () => { it('should load patterns', () => { patternsService.setup(x => x.getPatterns(app)) - .returns(() => of(new PatternsDto(oldPatterns, version))).verifiable(); + .returns(() => of({ payload: oldPatterns, version })).verifiable(); patternsState.load().subscribe(); @@ -62,7 +61,7 @@ describe('PatternsState', () => { it('should show notification on load when reload is true', () => { patternsService.setup(x => x.getPatterns(app)) - .returns(() => of(new PatternsDto(oldPatterns, version))).verifiable(); + .returns(() => of({ payload: oldPatterns, version })).verifiable(); patternsState.load(true).subscribe(); @@ -75,7 +74,7 @@ describe('PatternsState', () => { describe('Updates', () => { beforeEach(() => { patternsService.setup(x => x.getPatterns(app)) - .returns(() => of(new PatternsDto(oldPatterns, version))).verifiable(); + .returns(() => of({ payload: oldPatterns, version })).verifiable(); patternsState.load().subscribe(); }); @@ -86,7 +85,7 @@ describe('PatternsState', () => { const request = { ...newPattern }; patternsService.setup(x => x.postPattern(app, request, version)) - .returns(() => of(new Versioned(newVersion, newPattern))).verifiable(); + .returns(() => of(versioned(newVersion, newPattern))).verifiable(); patternsState.create(request).subscribe(); @@ -98,7 +97,7 @@ describe('PatternsState', () => { const request = { name: 'name2_1', pattern: 'pattern2_1', message: 'message2_1' }; patternsService.setup(x => x.putPattern(app, oldPatterns[1].id, request, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); patternsState.update(oldPatterns[1], request).subscribe(); @@ -112,7 +111,7 @@ describe('PatternsState', () => { it('should remove pattern from snapshot when deleted', () => { patternsService.setup(x => x.deletePattern(app, oldPatterns[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); patternsState.delete(oldPatterns[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/patterns.state.ts b/src/Squidex/app/shared/state/patterns.state.ts index 7206ec626..bf2c0688f 100644 --- a/src/Squidex/app/shared/state/patterns.state.ts +++ b/src/Squidex/app/shared/state/patterns.state.ts @@ -7,11 +7,13 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, + mapVersioned, + shareSubscribed, State, Version } from '@app/framework'; @@ -60,79 +62,56 @@ export class PatternsState extends State { this.resetState(); } - const update$ = - this.patternsService.getPatterns(this.appName).pipe( - share()); + return this.patternsService.getPatterns(this.appName).pipe( + tap(({ version, payload }) => { + if (isReload) { + this.dialogs.notifyInfo('Patterns reloaded.'); + } - update$.subscribe(({ version, patterns: items }) => { - if (isReload) { - this.dialogs.notifyInfo('Patterns reloaded.'); - } + this.next(s => { + const patterns = ImmutableArray.of(payload).sortByStringAsc(x => x.name); - this.next(s => { - const patterns = ImmutableArray.of(items).sortByStringAsc(x => x.name); - - return { ...s, patterns, isLoaded: true, version: version }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return update$; + return { ...s, patterns, isLoaded: true, version: version }; + }); + }), + shareSubscribed(this.dialogs, { project: x => x.payload })); } public create(request: EditPatternDto): Observable { - const update$ = - this.patternsService.postPattern(this.appName, request, this.version).pipe( - share()); - - update$.subscribe(({ version, payload: pattern }) => { - this.next(s => { - const patterns = s.patterns.push(pattern).sortByStringAsc(x => x.name); - - return { ...s, patterns, version: version }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return update$.pipe(map(x => x.payload)); + return this.patternsService.postPattern(this.appName, request, this.version).pipe( + tap(({ version, payload }) => { + this.next(s => { + const patterns = s.patterns.push(payload).sortByStringAsc(x => x.name); + + return { ...s, patterns, version: version }; + }); + }), + shareSubscribed(this.dialogs, { project: x => x.payload })); } public update(pattern: PatternDto, request: EditPatternDto): Observable { - const update$ = - this.patternsService.putPattern(this.appName, pattern.id, request, this.version).pipe( - map(({ version }) => ({ version, payload: update(pattern, request) })), share()); - - update$.subscribe(({ version, payload }) => { - this.next(s => { - const patterns = s.patterns.replaceBy('id', payload).sortByStringAsc(x => x.name); - - return { ...s, patterns, version: version }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return update$.pipe(map(x => x.payload)); + return this.patternsService.putPattern(this.appName, pattern.id, request, this.version).pipe( + mapVersioned(() => update(pattern, request)), + tap(({ version, payload }) => { + this.next(s => { + const patterns = s.patterns.replaceBy('id', payload).sortByStringAsc(x => x.name); + + return { ...s, patterns, version: version }; + }); + }), + shareSubscribed(this.dialogs, { project: x => x.payload })); } public delete(pattern: PatternDto): Observable { - const update$ = - this.patternsService.deletePattern(this.appName, pattern.id, this.version).pipe( - share()); - - update$.subscribe(({ version }) => { - this.next(s => { - const patterns = s.patterns.filter(c => c.id !== pattern.id); - - return { ...s, patterns, version: version }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return update$; + return this.patternsService.deletePattern(this.appName, pattern.id, this.version).pipe( + tap(({ version }) => { + this.next(s => { + const patterns = s.patterns.filter(c => c.id !== pattern.id); + + return { ...s, patterns, version: version }; + }); + }), + shareSubscribed(this.dialogs)); } private get appName() { diff --git a/src/Squidex/app/shared/state/plans.state.spec.ts b/src/Squidex/app/shared/state/plans.state.spec.ts index 485b32e24..152511812 100644 --- a/src/Squidex/app/shared/state/plans.state.spec.ts +++ b/src/Squidex/app/shared/state/plans.state.spec.ts @@ -12,10 +12,9 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { DialogService, PlanDto, - PlansDto, PlansService, PlansState, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -25,16 +24,20 @@ describe('PlansState', () => { app, appsState, authService, + creator, newVersion, version } = TestValues; - const oldPlans = - new PlansDto('id1', 'id2', true, [ + const oldPlans = { + currentPlanId: 'id1', + planOwner: creator, + plans: [ new PlanDto('id1', 'name1', '100€', 'id1_yearly', '200€', 1, 1, 1), new PlanDto('id2', 'name2', '400€', 'id2_yearly', '800€', 2, 2, 2) ], - version); + hasPortal: true + }; let dialogs: IMock; let plansService: IMock; @@ -44,84 +47,102 @@ describe('PlansState', () => { dialogs = Mock.ofType(); plansService = Mock.ofType(); - - plansService.setup(x => x.getPlans(app)) - .returns(() => of(oldPlans)); - plansState = new PlansState(appsState.object, authService.object, dialogs.object, plansService.object); }); - it('should load plans', () => { - plansState.load().pipe(onErrorResumeNext()).subscribe(); + afterEach(() => { + plansService.verifyAll(); + }); + + describe('Loading', () => { + it('should load plans', () => { + plansService.setup(x => x.getPlans(app)) + .returns(() => of(versioned(version, oldPlans))).verifiable(); - expect(plansState.snapshot.plans.values).toEqual([ - { isSelected: true, isYearlySelected: false, plan: oldPlans.plans[0] }, - { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[1] } - ]); - expect(plansState.snapshot.isOwner).toBeFalsy(); - expect(plansState.snapshot.isLoaded).toBeTruthy(); - expect(plansState.snapshot.hasPortal).toBeTruthy(); - expect(plansState.snapshot.version).toEqual(version); + plansState.load().subscribe(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + expect(plansState.snapshot.plans.values).toEqual([ + { isSelected: true, isYearlySelected: false, plan: oldPlans.plans[0] }, + { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[1] } + ]); + expect(plansState.snapshot.isOwner).toBeFalsy(); + expect(plansState.snapshot.isLoaded).toBeTruthy(); + expect(plansState.snapshot.hasPortal).toBeTruthy(); + expect(plansState.snapshot.version).toEqual(version); - it('should load plans with overriden id', () => { - plansState.load(false, 'id2_yearly').pipe(onErrorResumeNext()).subscribe(); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - expect(plansState.snapshot.plans.values).toEqual([ - { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[0] }, - { isSelected: false, isYearlySelected: true, plan: oldPlans.plans[1] } - ]); - expect(plansState.snapshot.isOwner).toBeFalsy(); - expect(plansState.snapshot.isLoaded).toBeTruthy(); - expect(plansState.snapshot.hasPortal).toBeTruthy(); - expect(plansState.snapshot.version).toEqual(version); + it('should load plans with overriden id', () => { + plansService.setup(x => x.getPlans(app)) + .returns(() => of(versioned(version, oldPlans))).verifiable(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); - }); + plansState.load(false, 'id2_yearly').subscribe(); - it('should show notification on load when reload is true', () => { - plansState.load(true).subscribe(); + expect(plansState.snapshot.plans.values).toEqual([ + { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[0] }, + { isSelected: false, isYearlySelected: true, plan: oldPlans.plans[1] } + ]); + expect(plansState.snapshot.isOwner).toBeFalsy(); + expect(plansState.snapshot.isLoaded).toBeTruthy(); + expect(plansState.snapshot.hasPortal).toBeTruthy(); + expect(plansState.snapshot.version).toEqual(version); - expect().nothing(); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.never()); + }); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + it('should show notification on load when reload is true', () => { + plansService.setup(x => x.getPlans(app)) + .returns(() => of(versioned(version, oldPlans))).verifiable(); + + plansState.load(true).subscribe(); + + expect().nothing(); + + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should redirect when returning url', () => { - plansState.window = { location: {} }; + describe('Updates', () => { + beforeEach(() => { + plansState.window = { location: {} }; - const result = { redirectUri: 'http://url' }; + plansService.setup(x => x.getPlans(app)) + .returns(() => of(versioned(version, oldPlans))).verifiable(); - plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, result))); + plansState.load().subscribe(); + }); - plansState.load().subscribe(); - plansState.change('free').pipe(onErrorResumeNext()).subscribe(); + it('should redirect when returning url', () => { + plansState.window = { location: {} }; - expect(plansState.snapshot.plans.values).toEqual([ - { isSelected: true, isYearlySelected: false, plan: oldPlans.plans[0] }, - { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[1] } - ]); - expect(plansState.window.location.href).toBe(result.redirectUri); - expect(plansState.snapshot.version).toEqual(version); - }); + const result = { redirectUri: 'http://url' }; + + plansService.setup(x => x.putPlan(app, It.isAny(), version)) + .returns(() => of(versioned(newVersion, result))); + + plansState.change('free').pipe(onErrorResumeNext()).subscribe(); - it('should update plans when no returning url', () => { - plansState.window = { location: {} }; + expect(plansState.snapshot.plans.values).toEqual([ + { isSelected: true, isYearlySelected: false, plan: oldPlans.plans[0] }, + { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[1] } + ]); + expect(plansState.window.location.href).toBe(result.redirectUri); + expect(plansState.snapshot.version).toEqual(version); + }); - plansService.setup(x => x.putPlan(app, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, { redirectUri: '' }))); + it('should update plans when no returning url', () => { + plansService.setup(x => x.putPlan(app, It.isAny(), version)) + .returns(() => of(versioned(newVersion, { redirectUri: '' }))); - plansState.load().subscribe(); - plansState.change('id2_yearly').pipe(onErrorResumeNext()).subscribe(); + plansState.change('id2_yearly').pipe(onErrorResumeNext()).subscribe(); - expect(plansState.snapshot.plans.values).toEqual([ - { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[0] }, - { isSelected: false, isYearlySelected: true, plan: oldPlans.plans[1] } - ]); - expect(plansState.snapshot.isOwner).toBeTruthy(); - expect(plansState.snapshot.version).toEqual(newVersion); + expect(plansState.snapshot.plans.values).toEqual([ + { isSelected: false, isYearlySelected: false, plan: oldPlans.plans[0] }, + { isSelected: false, isYearlySelected: true, plan: oldPlans.plans[1] } + ]); + expect(plansState.snapshot.isOwner).toBeTruthy(); + expect(plansState.snapshot.version).toEqual(newVersion); + }); }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/plans.state.ts b/src/Squidex/app/shared/state/plans.state.ts index a0745f2aa..6019c7c90 100644 --- a/src/Squidex/app/shared/state/plans.state.ts +++ b/src/Squidex/app/shared/state/plans.state.ts @@ -12,7 +12,7 @@ import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, + shareSubscribed, State, Version } from '@app/framework'; @@ -88,26 +88,26 @@ export class PlansState extends State { } return this.plansService.getPlans(this.appName).pipe( - tap(dto => { + tap(({ version, payload }) => { if (isReload) { this.dialogs.notifyInfo('Plans reloaded.'); } this.next(s => { - const planId = overridePlanId || dto.currentPlanId; - const plans = ImmutableArray.of(dto.plans.map(x => this.createPlan(x, planId))); + const planId = overridePlanId || payload.currentPlanId; + const plans = ImmutableArray.of(payload.plans.map(x => this.createPlan(x, planId))); return { ...s, plans: plans, - isOwner: !dto.planOwner || dto.planOwner === this.userId, + isOwner: !payload.planOwner || payload.planOwner === this.userId, isLoaded: true, - version: dto.version, - hasPortal: dto.hasPortal + version, + hasPortal: payload.hasPortal }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public change(planId: string): Observable { @@ -123,7 +123,7 @@ export class PlansState extends State { }); } }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } private createPlan(plan: PlanDto, id: string) { diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index f1715c2b7..91680effb 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -11,10 +11,9 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { DialogService, RoleDto, - RolesDto, RolesService, RolesState, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -46,7 +45,7 @@ describe('RolesState', () => { describe('Loading', () => { it('should load roles', () => { rolesService.setup(x => x.getRoles(app)) - .returns(() => of(new RolesDto(oldRoles, version))).verifiable(); + .returns(() => of({ payload: oldRoles, version })).verifiable(); rolesState.load().subscribe(); @@ -59,7 +58,7 @@ describe('RolesState', () => { it('should show notification on load when reload is true', () => { rolesService.setup(x => x.getRoles(app)) - .returns(() => of(new RolesDto(oldRoles, version))).verifiable(); + .returns(() => of(versioned(version, oldRoles))).verifiable(); rolesState.load(true).subscribe(); @@ -72,7 +71,7 @@ describe('RolesState', () => { describe('Updates', () => { beforeEach(() => { rolesService.setup(x => x.getRoles(app)) - .returns(() => of(new RolesDto(oldRoles, version))); + .returns(() => of(versioned(version, oldRoles))).verifiable(); rolesState.load().subscribe(); }); @@ -83,7 +82,7 @@ describe('RolesState', () => { const request = { name: newRole.name }; rolesService.setup(x => x.postRole(app, request, version)) - .returns(() => of(new Versioned(newVersion, newRole))); + .returns(() => of(versioned(newVersion, newRole))); rolesState.add(request).subscribe(); @@ -95,7 +94,7 @@ describe('RolesState', () => { const request = { permissions: ['P4', 'P5'] }; rolesService.setup(x => x.putRole(app, oldRoles[1].name, request, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(versioned(newVersion))); rolesState.update(oldRoles[1], request).subscribe(); @@ -107,7 +106,7 @@ describe('RolesState', () => { it('should remove role from snapshot when deleted', () => { rolesService.setup(x => x.deleteRole(app, oldRoles[0].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(versioned(newVersion))); rolesState.delete(oldRoles[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/roles.state.ts b/src/Squidex/app/shared/state/roles.state.ts index cd3f36e19..2896227e3 100644 --- a/src/Squidex/app/shared/state/roles.state.ts +++ b/src/Squidex/app/shared/state/roles.state.ts @@ -12,7 +12,8 @@ import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, + mapVersioned, + shareSubscribed, State, Version } from '@app/framework'; @@ -62,55 +63,56 @@ export class RolesState extends State { this.resetState(); } - return this.rolesService.getRoles(this.appName).pipe( - tap(dtos => { + return this.rolesService.getRoles(this.appName).pipe( + tap(({ payload, version }) => { if (isReload) { this.dialogs.notifyInfo('Roles reloaded.'); } this.next(s => { - const roles = ImmutableArray.of(dtos.roles).sortByStringAsc(x => x.name); + const roles = ImmutableArray.of(payload).sortByStringAsc(x => x.name); - return { ...s, roles, isLoaded: true, version: dtos.version }; + return { ...s, roles, isLoaded: true, version }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public add(request: CreateRoleDto): Observable { + public add(request: CreateRoleDto): Observable { return this.rolesService.postRole(this.appName, request, this.version).pipe( - tap(dto => { + tap(({ version, payload }) => { this.next(s => { - const roles = s.roles.push(dto.payload).sortByStringAsc(x => x.name); + const roles = s.roles.push(payload).sortByStringAsc(x => x.name); - return { ...s, roles, version: dto.version }; + return { ...s, roles, version }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } public delete(role: RoleDto): Observable { return this.rolesService.deleteRole(this.appName, role.name, this.version).pipe( - tap(dto => { + tap(({ version }) => { this.next(s => { const roles = s.roles.removeBy('name', role); - return { ...s, roles, version: dto.version }; + return { ...s, roles, version }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public update(role: RoleDto, request: UpdateRoleDto): Observable { + public update(role: RoleDto, request: UpdateRoleDto): Observable { return this.rolesService.putRole(this.appName, role.name, request, this.version).pipe( - tap(dto => { + mapVersioned(() => update(role, request)), + tap(({ version, payload }) => { this.next(s => { - const roles = s.roles.replaceBy('name', update(role, request)); + const roles = s.roles.replaceBy('name', payload); - return { ...s, roles, version: dto.version }; + return { ...s, roles, version }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } private get appName() { diff --git a/src/Squidex/app/shared/state/rule-events.state.ts b/src/Squidex/app/shared/state/rule-events.state.ts index e9fb3a7ec..dea86da12 100644 --- a/src/Squidex/app/shared/state/rule-events.state.ts +++ b/src/Squidex/app/shared/state/rule-events.state.ts @@ -12,8 +12,8 @@ import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DialogService, ImmutableArray, - notify, Pager, + shareSubscribed, State } from '@app/framework'; @@ -78,7 +78,7 @@ export class RuleEventsState extends State { return { ...s, ruleEvents, ruleEventsPager, isLoaded: true }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public enqueue(event: RuleEventDto): Observable { @@ -86,7 +86,7 @@ export class RuleEventsState extends State { tap(() => { this.dialogs.notifyInfo('Events enqueued. Will be resend in a few seconds.'); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public cancel(event: RuleEventDto): Observable { @@ -98,7 +98,7 @@ export class RuleEventsState extends State { return { ...s, ruleEvents, isLoaded: true }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public goNext(): Observable { diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index 025e5c4c1..2f0a13dcf 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -14,7 +14,7 @@ import { DialogService, RuleDto, RulesService, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -103,7 +103,7 @@ describe('RulesState', () => { const newAction = {}; rulesService.setup(x => x.putRule(app, oldRules[0].id, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); rulesState.updateAction(oldRules[0], newAction, modified).subscribe(); @@ -117,7 +117,7 @@ describe('RulesState', () => { const newTrigger = {}; rulesService.setup(x => x.putRule(app, oldRules[0].id, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); rulesState.updateTrigger(oldRules[0], newTrigger, modified).subscribe(); @@ -129,7 +129,7 @@ describe('RulesState', () => { it('should mark as enabled and update and user info when enabled', () => { rulesService.setup(x => x.enableRule(app, oldRules[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); rulesState.enable(oldRules[0], modified).subscribe(); @@ -141,7 +141,7 @@ describe('RulesState', () => { it('should mark as disabled and update and user info when disabled', () => { rulesService.setup(x => x.disableRule(app, oldRules[1].id, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); rulesState.disable(oldRules[1], modified).subscribe(); @@ -153,7 +153,7 @@ describe('RulesState', () => { it('should remove rule from snapshot when deleted', () => { rulesService.setup(x => x.deleteRule(app, oldRules[0].id, version)) - .returns(() => of(new Versioned(newVersion, {}))).verifiable(); + .returns(() => of(versioned(newVersion))).verifiable(); rulesState.delete(oldRules[0]).subscribe(); diff --git a/src/Squidex/app/shared/state/rules.state.ts b/src/Squidex/app/shared/state/rules.state.ts index 5288f3c44..e75b71f6c 100644 --- a/src/Squidex/app/shared/state/rules.state.ts +++ b/src/Squidex/app/shared/state/rules.state.ts @@ -7,12 +7,13 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, map, share } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { DateTime, DialogService, ImmutableArray, + shareSubscribed, State, Version } from '@app/framework'; @@ -60,112 +61,86 @@ export class RulesState extends State { this.resetState(); } - const http$ = - this.rulesService.getRules(this.appName).pipe( - share()); + return this.rulesService.getRules(this.appName).pipe( + tap(payload => { + if (isReload) { + this.dialogs.notifyInfo('Rules reloaded.'); + } - http$.subscribe(response => { - if (isReload) { - this.dialogs.notifyInfo('Rules reloaded.'); - } + this.next(s => { + const rules = ImmutableArray.of(payload); - this.next(s => { - const rules = ImmutableArray.of(response); - - return { ...s, rules, isLoaded: true }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return { ...s, rules, isLoaded: true }; + }); + }), + shareSubscribed(this.dialogs)); } public create(request: CreateRuleDto, now?: DateTime): Observable { - const http$ = - this.rulesService.postRule(this.appName, request, this.user, now || DateTime.now()).pipe( - share()); - - http$.subscribe(rule => { - this.next(s => { - const rules = s.rules.push(rule); - - return { ...s, rules }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.rulesService.postRule(this.appName, request, this.user, now || DateTime.now()).pipe( + tap(rule => { + this.next(s => { + const rules = s.rules.push(rule); + + return { ...s, rules }; + }); + }), + shareSubscribed(this.dialogs)); } public delete(rule: RuleDto): Observable { - const http$ = - this.rulesService.deleteRule(this.appName, rule.id, rule.version).pipe( - share()); - - http$.subscribe(() => { - this.next(s => { - const rules = s.rules.removeAll(x => x.id === rule.id); - - return { ...s, rules }; - }); - }, error => { - this.dialogs.notifyError(error); - }); - - return http$; + return this.rulesService.deleteRule(this.appName, rule.id, rule.version).pipe( + tap(() => { + this.next(s => { + const rules = s.rules.removeAll(x => x.id === rule.id); + + return { ...s, rules }; + }); + }), + shareSubscribed(this.dialogs)); } public updateAction(rule: RuleDto, action: any, now?: DateTime): Observable { - const http$ = - this.rulesService.putRule(this.appName, rule.id, { action }, rule.version).pipe( - map(({ version }) => updateAction(rule, action, this.user, version, now)), share()); - - this.replaceRule(http$); - - return http$; + return this.rulesService.putRule(this.appName, rule.id, { action }, rule.version).pipe( + map(({ version }) => updateAction(rule, action, this.user, version, now)), + tap(updated => { + this.replaceRule(updated); + }), + shareSubscribed(this.dialogs)); } public updateTrigger(rule: RuleDto, trigger: any, now?: DateTime): Observable { - const http$ = - this.rulesService.putRule(this.appName, rule.id, { trigger }, rule.version).pipe( - map(({ version }) => updateTrigger(rule, trigger, this.user, version, now)), share()); - - this.replaceRule(http$); - - return http$; + return this.rulesService.putRule(this.appName, rule.id, { trigger }, rule.version).pipe( + map(({ version }) => updateTrigger(rule, trigger, this.user, version, now)), + tap(updated => { + this.replaceRule(updated); + }), + shareSubscribed(this.dialogs)); } public enable(rule: RuleDto, now?: DateTime): Observable { - const http$ = - this.rulesService.enableRule(this.appName, rule.id, rule.version).pipe( - map(({ version }) => setEnabled(rule, true, this.user, version, now)), share()); - - this.replaceRule(http$); - - return http$; + return this.rulesService.enableRule(this.appName, rule.id, rule.version).pipe( + map(({ version }) => setEnabled(rule, true, this.user, version, now)), + tap(updated => { + this.replaceRule(updated); + }), + shareSubscribed(this.dialogs)); } public disable(rule: RuleDto, now?: DateTime): Observable { - const http$ = - this.rulesService.disableRule(this.appName, rule.id, rule.version).pipe( - map(({ version }) => setEnabled(rule, false, this.user, version, now)), share()); - - this.replaceRule(http$); - - return http$; + return this.rulesService.disableRule(this.appName, rule.id, rule.version).pipe( + map(({ version }) => setEnabled(rule, false, this.user, version, now)), + tap(updated => { + this.replaceRule(updated); + }), + shareSubscribed(this.dialogs)); } - private replaceRule(http$: Observable) { - http$.subscribe(rule => { - this.next(s => { - const rules = s.rules.replaceBy('id', rule); + private replaceRule(rule: RuleDto) { + this.next(s => { + const rules = s.rules.replaceBy('id', rule); - return { ...s, rules }; - }); - }, error => { - this.dialogs.notifyError(error); + return { ...s, rules }; }); } diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index d6054d2fa..0b5248a0e 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -21,7 +21,7 @@ import { SchemaDto, SchemasService, UpdateSchemaCategoryDto, - Versioned + versioned } from './../'; import { TestValues } from './_test-helpers'; @@ -65,167 +65,152 @@ describe('SchemasState', () => { dialogs = Mock.ofType(); schemasService = Mock.ofType(); - - schemasService.setup(x => x.getSchemas(app)) - .returns(() => of(oldSchemas)); - - schemasService.setup(x => x.getSchema(app, schema.name)) - .returns(() => of(schema)); - - schemasService.setup(x => x.getSchema(app, schema.name)) - .returns(() => of(schema)); - schemasState = new SchemasState(appsState.object, authService.object, dialogs.object, schemasService.object); - schemasState.load().subscribe(); }); - it('should load schemas', () => { - expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas); - expect(schemasState.snapshot.isLoaded).toBeTruthy(); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false }); - + afterEach(() => { schemasService.verifyAll(); }); - it('should not remove custom category when loading schemas', () => { - schemasState.addCategory('category3'); - schemasState.load(true).subscribe(); + describe('Loading', () => { + it('should load schemas', () => { + schemasService.setup(x => x.getSchemas(app)) + .returns(() => of(oldSchemas)).verifiable(); - expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas); - expect(schemasState.snapshot.isLoaded).toBeTruthy(); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); + schemasState.load().subscribe(); - schemasService.verifyAll(); - }); + expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas); + expect(schemasState.snapshot.isLoaded).toBeTruthy(); + expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false }); - it('should show notification on load when reload is true', () => { - schemasState.load(true).subscribe(); + schemasService.verifyAll(); + }); - expect().nothing(); + it('should not remove custom category when loading schemas', () => { + schemasService.setup(x => x.getSchemas(app)) + .returns(() => of(oldSchemas)).verifiable(); - dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); - }); + schemasState.addCategory('category3'); + schemasState.load(true).subscribe(); - it('should add category', () => { - schemasState.addCategory('category3'); + expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas); + expect(schemasState.snapshot.isLoaded).toBeTruthy(); + expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); - }); + schemasService.verifyAll(); + }); - it('should remove category', () => { - schemasState.removeCategory('category1'); + it('should show notification on load when reload is true', () => { + schemasService.setup(x => x.getSchemas(app)) + .returns(() => of(oldSchemas)).verifiable(); - expect(schemasState.snapshot.categories).toEqual({ 'category2': false }); - }); + schemasState.load(true).subscribe(); - it('should return schema on select and reload when already loaded', () => { - schemasState.select('name2').subscribe(); - schemasState.select('name2').subscribe(); + expect().nothing(); - schemasService.verify(x => x.getSchema(app, 'name2'), Times.exactly(2)); - - expect().nothing(); + dialogs.verify(x => x.notifyInfo(It.isAnyString()), Times.once()); + }); }); - it('should return schema on select and load when not loaded', () => { - let selectedSchema: SchemaDetailsDto; + describe('Updates', () => { + beforeEach(() => { + schemasService.setup(x => x.getSchemas(app)) + .returns(() => of(oldSchemas)).verifiable(); - schemasState.select('name2').subscribe(x => { - selectedSchema = x!; + schemasState.load().subscribe(); }); - expect(selectedSchema!).toBe(schema); - expect(schemasState.snapshot.selectedSchema).toBe(schema); - expect(schemasState.snapshot.selectedSchema).toBe(schemasState.snapshot.schemas.at(1)); - }); + it('should add category', () => { + schemasState.addCategory('category3'); - it('should return null on select when loading failed', () => { - schemasService.setup(x => x.getSchema(app, 'failed')) - .returns(() => throwError({})); + expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); + }); - let selectedSchema: SchemaDetailsDto; + it('should remove category', () => { + schemasState.removeCategory('category1'); - schemasState.select('failed').subscribe(x => { - selectedSchema = x!; + expect(schemasState.snapshot.categories).toEqual({ 'category2': false }); }); - expect(selectedSchema!).toBeNull(); - expect(schemasState.snapshot.selectedSchema).toBeNull(); - }); + it('should return schema on select and reload when already loaded', () => { + schemasService.setup(x => x.getSchema(app, schema.name)) + .returns(() => of(schema)).verifiable(Times.exactly(2)); - it('should return null on select when unselecting schema', () => { - let selectedSchema: SchemaDetailsDto; + schemasState.select('name2').subscribe(); + schemasState.select('name2').subscribe(); - schemasState.select(null).subscribe(x => { - selectedSchema = x!; + expect().nothing(); }); - expect(selectedSchema!).toBeNull(); - expect(schemasState.snapshot.selectedSchema).toBeNull(); + it('should return schema on select and load when not loaded', () => { + schemasService.setup(x => x.getSchema(app, schema.name)) + .returns(() => of(schema)).verifiable(); - schemasService.verify(x => x.getSchema(app, It.isAnyString()), Times.never()); - }); + let selectedSchema: SchemaDetailsDto; - it('should mark published and update user info when published', () => { - schemasService.setup(x => x.publishSchema(app, oldSchemas[0].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.select('name2').subscribe(x => { + selectedSchema = x!; + }); - schemasState.publish(oldSchemas[0], modified).subscribe(); + expect(selectedSchema!).toBe(schema); + expect(schemasState.snapshot.selectedSchema).toBe(schema); + expect(schemasState.snapshot.selectedSchema).toBe(schemasState.snapshot.schemas.at(1)); + }); - const schema_1 = schemasState.snapshot.schemas.at(0); + it('should return null on select when loading failed', () => { + schemasService.setup(x => x.getSchema(app, 'failed')) + .returns(() => throwError({})).verifiable(); - expect(schema_1.isPublished).toBeTruthy(); - expectToBeModified(schema_1); - }); + let selectedSchema: SchemaDetailsDto; - it('should unmark published and update user info when unpublished', () => { - schemasService.setup(x => x.unpublishSchema(app, oldSchemas[1].name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.select('failed').subscribe(x => { + selectedSchema = x!; + }); - schemasState.unpublish(oldSchemas[1], modified).subscribe(); - - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(selectedSchema!).toBeNull(); + expect(schemasState.snapshot.selectedSchema).toBeNull(); + }); - expect(schema_1.isPublished).toBeFalsy(); - expectToBeModified(schema_1); - }); + it('should return null on select when unselecting schema', () => { + let selectedSchema: SchemaDetailsDto; - it('should change category and update user info when category changed', () => { - const category = 'my-new-category'; + schemasState.select(null).subscribe(x => { + selectedSchema = x!; + }); - schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.name === category), version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(selectedSchema!).toBeNull(); + expect(schemasState.snapshot.selectedSchema).toBeNull(); + }); - schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); + it('should mark published and update user info when published', () => { + schemasService.setup(x => x.publishSchema(app, oldSchemas[0].name, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - const schema_1 = schemasState.snapshot.schemas.at(0); + schemasState.publish(oldSchemas[0], modified).subscribe(); - expect(schema_1.category).toEqual(category); - expectToBeModified(schema_1); - }); + const schema_1 = schemasState.snapshot.schemas.at(0); - describe('with selection', () => { - beforeEach(() => { - schemasState.select(schema.name).subscribe(); + expect(schema_1.isPublished).toBeTruthy(); + expectToBeModified(schema_1); }); - it('should nmark published and update user info when published selected schema', () => { - schemasService.setup(x => x.publishSchema(app, schema.name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + it('should unmark published and update user info when unpublished', () => { + schemasService.setup(x => x.unpublishSchema(app, oldSchemas[1].name, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - schemasState.publish(schema, modified).subscribe(); + schemasState.unpublish(oldSchemas[1], modified).subscribe(); - const schema_1 = schemasState.snapshot.schemas.at(1); + const schema_1 = schemasState.snapshot.schemas.at(1); - expect(schema_1.isPublished).toBeTruthy(); + expect(schema_1.isPublished).toBeFalsy(); expectToBeModified(schema_1); }); - it('should change category and update user info when category of selected schema changed', () => { + it('should change category and update user info when category changed', () => { const category = 'my-new-category'; schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.name === category), version)) - .returns(() => of(new Versioned(newVersion, {}))); + .returns(() => of(versioned(newVersion))).verifiable(); schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); @@ -235,305 +220,340 @@ describe('SchemasState', () => { expectToBeModified(schema_1); }); - it('should update properties and update user info when updated', () => { - const request = { label: 'name2_label', hints: 'name2_hints' }; + describe('with selection', () => { + beforeEach(() => { + schemasService.setup(x => x.getSchema(app, schema.name)) + .returns(() => of(schema)).verifiable(); - schemasService.setup(x => x.putSchema(app, schema.name, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.select(schema.name).subscribe(); + }); - schemasState.update(schema, request, modified).subscribe(); + it('should nmark published and update user info when published selected schema', () => { + schemasService.setup(x => x.publishSchema(app, schema.name, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - const schema_1 = schemasState.snapshot.schemas.at(1); + schemasState.publish(schema, modified).subscribe(); - expect(schema_1.properties.label).toEqual(request.label); - expect(schema_1.properties.hints).toEqual(request.hints); - expectToBeModified(schema_1); - }); + const schema_1 = schemasState.snapshot.schemas.at(1); - it('should update script properties and update user info when scripts configured', () => { - const request = { query: '' }; + expect(schema_1.isPublished).toBeTruthy(); + expectToBeModified(schema_1); + }); - schemasService.setup(x => x.putScripts(app, schema.name, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))); + it('should change category and update user info when category of selected schema changed', () => { + const category = 'my-new-category'; - schemasState.configureScripts(schema, request, modified).subscribe(); + schemasService.setup(x => x.putCategory(app, oldSchemas[0].name, It.is(i => i.name === category), version)) + .returns(() => of(versioned(newVersion))).verifiable(); - const schema_1 = schemasState.snapshot.schemas.at(1); + schemasState.changeCategory(oldSchemas[0], category, modified).subscribe(); - expect(schema_1.scripts['query']).toEqual(''); - expectToBeModified(schema_1); - }); + const schema_1 = schemasState.snapshot.schemas.at(0); - it('should update script properties and update user info when preview urls configured', () => { - const request = { web: 'url' }; + expect(schema_1.category).toEqual(category); + expectToBeModified(schema_1); + }); - schemasService.setup(x => x.putPreviewUrls(app, schema.name, It.isAny(), version)) - .returns(() => of(new Versioned(newVersion, {}))); + it('should update properties and update user info when updated', () => { + const request = { label: 'name2_label', hints: 'name2_hints' }; - schemasState.configurePreviewUrls(schema, request, modified).subscribe(); + schemasService.setup(x => x.putSchema(app, schema.name, It.isAny(), version)) + .returns(() => of(versioned(newVersion))).verifiable(); - const schema_1 = schemasState.snapshot.schemas.at(1); + schemasState.update(schema, request, modified).subscribe(); - expect(schema_1.previewUrls).toEqual(request); - expectToBeModified(schema_1); - }); + const schema_1 = schemasState.snapshot.schemas.at(1); - it('should add schema to snapshot when created', () => { - const request = new CreateSchemaDto('newName'); + expect(schema_1.properties.label).toEqual(request.label); + expect(schema_1.properties.hints).toEqual(request.hints); + expectToBeModified(schema_1); + }); - const result = new SchemaDetailsDto('id4', 'newName', '', {}, false, false, modified, modifier, modified, modifier, version); + it('should update script properties and update user info when scripts configured', () => { + const request = { query: '' }; - schemasService.setup(x => x.postSchema(app, request, modifier, modified)) - .returns(() => of(result)); + schemasService.setup(x => x.putScripts(app, schema.name, It.isAny(), version)) + .returns(() => of(versioned(newVersion))).verifiable(); - schemasState.create(request, modified).subscribe(); + schemasState.configureScripts(schema, request, modified).subscribe(); - expect(schemasState.snapshot.schemas.values.length).toBe(3); - expect(schemasState.snapshot.schemas.at(2)).toBe(result); - }); + const schema_1 = schemasState.snapshot.schemas.at(1); - it('should remove schema from snapshot when deleted', () => { - schemasService.setup(x => x.deleteSchema(app, schema.name, version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(schema_1.scripts['query']).toEqual(''); + expectToBeModified(schema_1); + }); - schemasState.delete(schema).subscribe(); + it('should update script properties and update user info when preview urls configured', () => { + const request = { web: 'url' }; - expect(schemasState.snapshot.schemas.values.length).toBe(1); - expect(schemasState.snapshot.selectedSchema).toBeNull(); - }); + schemasService.setup(x => x.putPreviewUrls(app, schema.name, It.isAny(), version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should add field and update user info when field added', () => { - const request = new AddFieldDto(field1.name, field1.partitioning, field1.properties); + schemasState.configurePreviewUrls(schema, request, modified).subscribe(); - const newField = new RootFieldDto(3, '3', createProperties('String'), 'invariant'); + const schema_1 = schemasState.snapshot.schemas.at(1); - schemasService.setup(x => x.postField(app, schema.name, It.isAny(), undefined, version)) - .returns(() => of(new Versioned(newVersion, newField))); + expect(schema_1.previewUrls).toEqual(request); + expectToBeModified(schema_1); + }); - schemasState.addField(schema, request, undefined, modified).subscribe(); + it('should add schema to snapshot when created', () => { + const request = new CreateSchemaDto('newName'); - const schema_1 = schemasState.snapshot.schemas.at(1); + const result = new SchemaDetailsDto('id4', 'newName', '', {}, false, false, modified, modifier, modified, modifier, version); - expect(schema_1.fields).toEqual([field1, field2, newField]); - expectToBeModified(schema_1); - }); + schemasService.setup(x => x.postSchema(app, request, modifier, modified)) + .returns(() => of(result)).verifiable(); - it('should add field and update user info when nested field added', () => { - const request = new AddFieldDto(field1.name, field1.partitioning, field1.properties); + schemasState.create(request, modified).subscribe(); - const newField = new NestedFieldDto(3, '3', createProperties('String'), 2); + expect(schemasState.snapshot.schemas.values.length).toBe(3); + expect(schemasState.snapshot.schemas.at(2)).toBe(result); + }); - schemasService.setup(x => x.postField(app, schema.name, It.isAny(), 2, version)) - .returns(() => of(new Versioned(newVersion, newField))); + it('should remove schema from snapshot when deleted', () => { + schemasService.setup(x => x.deleteSchema(app, schema.name, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - schemasState.addField(schema, request, field2, modified).subscribe(); + schemasState.delete(schema).subscribe(); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schemasState.snapshot.schemas.values.length).toBe(1); + expect(schemasState.snapshot.selectedSchema).toBeNull(); + }); - expect(schema_1.fields[1].nested).toEqual([nested1, nested2, newField]); - expectToBeModified(schema_1); - }); + it('should add field and update user info when field added', () => { + const request = new AddFieldDto(field1.name, field1.partitioning, field1.properties); - it('should remove field and update user info when field removed', () => { - schemasService.setup(x => x.deleteField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + const newField = new RootFieldDto(3, '3', createProperties('String'), 'invariant'); - schemasState.deleteField(schema, field1, modified).subscribe(); + schemasService.setup(x => x.postField(app, schema.name, It.isAny(), undefined, version)) + .returns(() => of(versioned(newVersion, newField))).verifiable(); - const schema_1 = schemasState.snapshot.schemas.at(1); + schemasState.addField(schema, request, undefined, modified).subscribe(); - expect(schema_1.fields).toEqual([field2]); - expectToBeModified(schema_1); - }); + const schema_1 = schemasState.snapshot.schemas.at(1); - it('should remove field and update user info when nested field removed', () => { - schemasService.setup(x => x.deleteField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(schema_1.fields).toEqual([field1, field2, newField]); + expectToBeModified(schema_1); + }); - schemasState.deleteField(schema, nested1, modified).subscribe(); + it('should add field and update user info when nested field added', () => { + const request = new AddFieldDto(field1.name, field1.partitioning, field1.properties); - const schema_1 = schemasState.snapshot.schemas.at(1); + const newField = new NestedFieldDto(3, '3', createProperties('String'), 2); - expect(schema_1.fields[1].nested).toEqual([nested2]); - expectToBeModified(schema_1); - }); + schemasService.setup(x => x.postField(app, schema.name, It.isAny(), 2, version)) + .returns(() => of(versioned(newVersion, newField))).verifiable(); - it('should sort fields and update user info when fields sorted', () => { - schemasService.setup(x => x.putFieldOrdering(app, schema.name, [field2.fieldId, field1.fieldId], undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.addField(schema, request, field2, modified).subscribe(); - schemasState.sortFields(schema, [field2, field1], undefined, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[1].nested).toEqual([nested1, nested2, newField]); + expectToBeModified(schema_1); + }); - expect(schema_1.fields).toEqual([field2, field1]); - expectToBeModified(schema_1); - }); + it('should remove field and update user info when field removed', () => { + schemasService.setup(x => x.deleteField(app, schema.name, field1.fieldId, undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should sort fields and update user info when nested fields sorted', () => { - schemasService.setup(x => x.putFieldOrdering(app, schema.name, [nested2.fieldId, nested1.fieldId], 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.deleteField(schema, field1, modified).subscribe(); - schemasState.sortFields(schema, [nested2, nested1], field2, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields).toEqual([field2]); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].nested).toEqual([nested2, nested1]); - expectToBeModified(schema_1); - }); + it('should remove field and update user info when nested field removed', () => { + schemasService.setup(x => x.deleteField(app, schema.name, nested1.fieldId, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should update field properties and update user info when field updated', () => { - const request = { properties: createProperties('String') }; + schemasState.deleteField(schema, nested1, modified).subscribe(); - schemasService.setup(x => x.putField(app, schema.name, field1.fieldId, request, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + const schema_1 = schemasState.snapshot.schemas.at(1); - schemasState.updateField(schema, field1, request, modified).subscribe(); + expect(schema_1.fields[1].nested).toEqual([nested2]); + expectToBeModified(schema_1); + }); - const schema_1 = schemasState.snapshot.schemas.at(1); + it('should sort fields and update user info when fields sorted', () => { + schemasService.setup(x => x.putFieldOrdering(app, schema.name, [field2.fieldId, field1.fieldId], undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - expect(schema_1.fields[0].properties).toBe(request.properties); - expectToBeModified(schema_1); - }); + schemasState.sortFields(schema, [field2, field1], undefined, modified).subscribe(); - it('should update field properties and update user info when nested field updated', () => { - const request = { properties: createProperties('String') }; + const schema_1 = schemasState.snapshot.schemas.at(1); - schemasService.setup(x => x.putField(app, schema.name, nested1.fieldId, request, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(schema_1.fields).toEqual([field2, field1]); + expectToBeModified(schema_1); + }); - schemasState.updateField(schema, nested1, request, modified).subscribe(); + it('should sort fields and update user info when nested fields sorted', () => { + schemasService.setup(x => x.putFieldOrdering(app, schema.name, [nested2.fieldId, nested1.fieldId], 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - const schema_1 = schemasState.snapshot.schemas.at(1); + schemasState.sortFields(schema, [nested2, nested1], field2, modified).subscribe(); - expect(schema_1.fields[1].nested[0].properties).toBe(request.properties); - expectToBeModified(schema_1); - }); + const schema_1 = schemasState.snapshot.schemas.at(1); - it('should mark field hidden and update user info when field hidden', () => { - schemasService.setup(x => x.hideField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + expect(schema_1.fields[1].nested).toEqual([nested2, nested1]); + expectToBeModified(schema_1); + }); - schemasState.hideField(schema, field1, modified).subscribe(); + it('should update field properties and update user info when field updated', () => { + const request = { properties: createProperties('String') }; - const schema_1 = schemasState.snapshot.schemas.at(1); + schemasService.setup(x => x.putField(app, schema.name, field1.fieldId, request, undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - expect(schema_1.fields[0].isHidden).toBeTruthy(); - expectToBeModified(schema_1); - }); + schemasState.updateField(schema, field1, request, modified).subscribe(); - it('should mark field hidden and update user info when nested field hidden', () => { - schemasService.setup(x => x.hideField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + const schema_1 = schemasState.snapshot.schemas.at(1); - schemasState.hideField(schema, nested1, modified).subscribe(); + expect(schema_1.fields[0].properties).toBe(request.properties); + expectToBeModified(schema_1); + }); - const schema_1 = schemasState.snapshot.schemas.at(1); + it('should update field properties and update user info when nested field updated', () => { + const request = { properties: createProperties('String') }; - expect(schema_1.fields[1].nested[0].isHidden).toBeTruthy(); - expectToBeModified(schema_1); - }); + schemasService.setup(x => x.putField(app, schema.name, nested1.fieldId, request, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should mark field disabled and update user info when field disabled', () => { - schemasService.setup(x => x.disableField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.updateField(schema, nested1, request, modified).subscribe(); - schemasState.disableField(schema, field1, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[1].nested[0].properties).toBe(request.properties); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[0].isDisabled).toBeTruthy(); - expectToBeModified(schema_1); - }); + it('should mark field hidden and update user info when field hidden', () => { + schemasService.setup(x => x.hideField(app, schema.name, field1.fieldId, undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should mark field disabled and update user info when nested disabled', () => { - schemasService.setup(x => x.disableField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.hideField(schema, field1, modified).subscribe(); - schemasState.disableField(schema, nested1, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[0].isHidden).toBeTruthy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].nested[0].isDisabled).toBeTruthy(); - expectToBeModified(schema_1); - }); + it('should mark field hidden and update user info when nested field hidden', () => { + schemasService.setup(x => x.hideField(app, schema.name, nested1.fieldId, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should mark field locked and update user info when field locked', () => { - schemasService.setup(x => x.lockField(app, schema.name, field1.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.hideField(schema, nested1, modified).subscribe(); - schemasState.lockField(schema, field1, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[1].nested[0].isHidden).toBeTruthy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[0].isLocked).toBeTruthy(); - expectToBeModified(schema_1); - }); + it('should mark field disabled and update user info when field disabled', () => { + schemasService.setup(x => x.disableField(app, schema.name, field1.fieldId, undefined, version)) + .returns(() => of(versioned(newVersion))); - it('should mark field locked and update user info when nested field locked', () => { - schemasService.setup(x => x.lockField(app, schema.name, nested1.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.disableField(schema, field1, modified).subscribe(); - schemasState.lockField(schema, nested1, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[0].isDisabled).toBeTruthy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].nested[0].isLocked).toBeTruthy(); - expectToBeModified(schema_1); - }); + it('should mark field disabled and update user info when nested disabled', () => { + schemasService.setup(x => x.disableField(app, schema.name, nested1.fieldId, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should unmark field hidden and update user info when field shown', () => { - schemasService.setup(x => x.showField(app, schema.name, field2.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.disableField(schema, nested1, modified).subscribe(); - schemasState.showField(schema, field2, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[1].nested[0].isDisabled).toBeTruthy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].isHidden).toBeFalsy(); - expectToBeModified(schema_1); - }); + it('should mark field locked and update user info when field locked', () => { + schemasService.setup(x => x.lockField(app, schema.name, field1.fieldId, undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should unmark field hidden and update user info when nested field shown', () => { - schemasService.setup(x => x.showField(app, schema.name, nested2.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.lockField(schema, field1, modified).subscribe(); - schemasState.showField(schema, nested2, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[0].isLocked).toBeTruthy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].nested[1].isHidden).toBeFalsy(); - expectToBeModified(schema_1); - }); + it('should mark field locked and update user info when nested field locked', () => { + schemasService.setup(x => x.lockField(app, schema.name, nested1.fieldId, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should unmark field disabled and update user info when field enabled', () => { - schemasService.setup(x => x.enableField(app, schema.name, field2.fieldId, undefined, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.lockField(schema, nested1, modified).subscribe(); - schemasState.enableField(schema, field2, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[1].nested[0].isLocked).toBeTruthy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].isDisabled).toBeFalsy(); - expectToBeModified(schema_1); - }); + it('should unmark field hidden and update user info when field shown', () => { + schemasService.setup(x => x.showField(app, schema.name, field2.fieldId, undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); - it('should unmark field disabled and update user info when nested field enabled', () => { - schemasService.setup(x => x.enableField(app, schema.name, nested2.fieldId, 2, version)) - .returns(() => of(new Versioned(newVersion, {}))); + schemasState.showField(schema, field2, modified).subscribe(); - schemasState.enableField(schema, nested2, modified).subscribe(); + const schema_1 = schemasState.snapshot.schemas.at(1); - const schema_1 = schemasState.snapshot.schemas.at(1); + expect(schema_1.fields[1].isHidden).toBeFalsy(); + expectToBeModified(schema_1); + }); - expect(schema_1.fields[1].nested[1].isDisabled).toBeFalsy(); - expectToBeModified(schema_1); + it('should unmark field hidden and update user info when nested field shown', () => { + schemasService.setup(x => x.showField(app, schema.name, nested2.fieldId, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); + + schemasState.showField(schema, nested2, modified).subscribe(); + + const schema_1 = schemasState.snapshot.schemas.at(1); + + expect(schema_1.fields[1].nested[1].isHidden).toBeFalsy(); + expectToBeModified(schema_1); + }); + + it('should unmark field disabled and update user info when field enabled', () => { + schemasService.setup(x => x.enableField(app, schema.name, field2.fieldId, undefined, version)) + .returns(() => of(versioned(newVersion))).verifiable(); + + schemasState.enableField(schema, field2, modified).subscribe(); + + const schema_1 = schemasState.snapshot.schemas.at(1); + + expect(schema_1.fields[1].isDisabled).toBeFalsy(); + expectToBeModified(schema_1); + }); + + it('should unmark field disabled and update user info when nested field enabled', () => { + schemasService.setup(x => x.enableField(app, schema.name, nested2.fieldId, 2, version)) + .returns(() => of(versioned(newVersion))).verifiable(); + + schemasState.enableField(schema, nested2, modified).subscribe(); + + const schema_1 = schemasState.snapshot.schemas.at(1); + + expect(schema_1.fields[1].nested[1].isDisabled).toBeFalsy(); + expectToBeModified(schema_1); + }); }); - }); - function expectToBeModified(schema_1: SchemaDto) { - expect(schema_1.lastModified).toEqual(modified); - expect(schema_1.lastModifiedBy).toEqual(modifier); - expect(schema_1.version).toEqual(newVersion); - } + function expectToBeModified(schema_1: SchemaDto) { + expect(schema_1.lastModified).toEqual(modified); + expect(schema_1.lastModifiedBy).toEqual(modifier); + expect(schema_1.version).toEqual(newVersion); + } + }); }); \ No newline at end of file diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index 34784c01a..b75e22de2 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -13,7 +13,8 @@ import { DateTime, DialogService, ImmutableArray, - notify, + mapVersioned, + shareSubscribed, State, Types, Version @@ -45,7 +46,7 @@ interface Snapshot { categories: { [name: string]: boolean }; // The current schemas. - schemas: ImmutableArray; + schemas: SchemasList; // Indicates if the schemas are loaded. isLoaded?: boolean; @@ -54,6 +55,8 @@ interface Snapshot { selectedSchema?: SchemaDetailsDto | null; } +export type SchemasList = ImmutableArray; + function sameSchema(lhs: SchemaDetailsDto | null, rhs?: SchemaDetailsDto | null): boolean { return lhs === rhs || (!!lhs && !!rhs && lhs.id === rhs.id && lhs.version === rhs.version); } @@ -116,44 +119,45 @@ export class SchemasState extends State { } return this.schemasService.getSchemas(this.appName).pipe( - tap(dtos => { + tap(payload => { if (isReload) { this.dialogs.notifyInfo('Schemas reloaded.'); } return this.next(s => { - const schemas = ImmutableArray.of(dtos).sortByStringAsc(x => x.displayName); + const schemas = ImmutableArray.of(payload).sortByStringAsc(x => x.displayName); const categories = buildCategories(s.categories, schemas); return { ...s, schemas, isLoaded: true, categories }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public create(request: CreateSchemaDto, now?: DateTime) { + public create(request: CreateSchemaDto, now?: DateTime): Observable { return this.schemasService.postSchema(this.appName, request, this.user, now || DateTime.now()).pipe( tap(dto => { - return this.next(s => { + this.next(s => { const schemas = s.schemas.push(dto).sortByStringAsc(x => x.displayName); return { ...s, schemas }; }); - })); + }), + shareSubscribed(this.dialogs, { silent: true })); } public delete(schema: SchemaDto): Observable { return this.schemasService.deleteSchema(this.appName, schema.name, schema.version).pipe( tap(() => { - return this.next(s => { + this.next(s => { const schemas = s.schemas.filter(x => x.id !== schema.id); const selectedSchema = s.selectedSchema && s.selectedSchema.id === schema.id ? null : s.selectedSchema; return { ...s, schemas, selectedSchema }; }); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public addCategory(name: string) { @@ -172,138 +176,165 @@ export class SchemasState extends State { }); } - public publish(schema: SchemaDto, now?: DateTime): Observable { + public publish(schema: SchemaDto, now?: DateTime): Observable { return this.schemasService.publishSchema(this.appName, schema.name, schema.version).pipe( - tap(dto => { - this.replaceSchema(setPublished(schema, true, this.user, dto.version, now)); + map(({ version }) => setPublished(schema, true, this.user, version, now)), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public unpublish(schema: SchemaDto, now?: DateTime): Observable { + public unpublish(schema: SchemaDto, now?: DateTime): Observable { return this.schemasService.unpublishSchema(this.appName, schema.name, schema.version).pipe( - tap(dto => { - this.replaceSchema(setPublished(schema, false, this.user, dto.version, now)); + map(({ version }) => setPublished(schema, false, this.user, version, now)), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public changeCategory(schema: SchemaDto, name: string, now?: DateTime): Observable { + public changeCategory(schema: SchemaDto, name: string, now?: DateTime): Observable { return this.schemasService.putCategory(this.appName, schema.name, { name }, schema.version).pipe( - tap(dto => { - this.replaceSchema(changeCategory(schema, name, this.user, dto.version, now)); + map(({ version }) => changeCategory(schema, name, this.user, version, now)), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public configurePreviewUrls(schema: SchemaDetailsDto, request: {}, now?: DateTime): Observable { + public configurePreviewUrls(schema: SchemaDetailsDto, request: {}, now?: DateTime): Observable { return this.schemasService.putPreviewUrls(this.appName, schema.name, request, schema.version).pipe( - tap(dto => { - this.replaceSchema(configurePreviewUrls(schema, request, this.user, dto.version, now)); + map(({ version }) => configurePreviewUrls(schema, request, this.user, version, now)), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public configureScripts(schema: SchemaDetailsDto, request: {}, now?: DateTime): Observable { + public configureScripts(schema: SchemaDetailsDto, request: {}, now?: DateTime): Observable { return this.schemasService.putScripts(this.appName, schema.name, request, schema.version).pipe( - tap(dto => { - this.replaceSchema(configureScripts(schema, request, this.user, dto.version, now)); + map(({ version }) => configureScripts(schema, request, this.user, version, now)), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public update(schema: SchemaDetailsDto, request: UpdateSchemaDto, now?: DateTime): Observable { + public update(schema: SchemaDetailsDto, request: UpdateSchemaDto, now?: DateTime): Observable { return this.schemasService.putSchema(this.appName, schema.name, request, schema.version).pipe( - tap(dto => { - this.replaceSchema(updateProperties(schema, request, this.user, dto.version, now)); + map(({ version }) => updateProperties(schema, request, this.user, version, now)), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } public addField(schema: SchemaDetailsDto, request: AddFieldDto, parent?: RootFieldDto, now?: DateTime): Observable { return this.schemasService.postField(this.appName, schema.name, request, pid(parent), schema.version).pipe( - tap(dto => { - if (Types.is(dto.payload, NestedFieldDto)) { - this.replaceSchema(updateField(schema, addNested(parent!, dto.payload), this.user, dto.version, now)); + map(({ version, payload }) => { + let newSchema: SchemaDto; + + if (Types.is(payload, NestedFieldDto)) { + newSchema = updateField(schema, addNested(parent!, payload), this.user, version, now); } else { - this.replaceSchema(addField(schema, dto.payload, this.user, dto.version, now)); + newSchema = addField(schema, payload, this.user, version, now); } + + return { newSchema, field: payload }; + }), + tap(({ newSchema }) => { + this.replaceSchema(newSchema); }), - map(d => d.payload)); + shareSubscribed(this.dialogs, { silent: true, project: x => x.field })); } - public sortFields(schema: SchemaDetailsDto, fields: any[], parent?: RootFieldDto, now?: DateTime): Observable { + public sortFields(schema: SchemaDetailsDto, fields: any[], parent?: RootFieldDto, now?: DateTime): Observable { return this.schemasService.putFieldOrdering(this.appName, schema.name, fields.map(t => t.fieldId), pid(parent), schema.version).pipe( - tap(dto => { + map(({ version }) => { + let newSchema: SchemaDto; + if (!parent) { - this.replaceSchema(replaceFields(schema, fields, this.user, dto.version, now)); + newSchema = replaceFields(schema, fields, this.user, version, now); } else { - this.replaceSchema(updateField(schema, replaceNested(parent, fields), this.user, dto.version, now)); + newSchema = updateField(schema, replaceNested(parent, fields), this.user, version, now); } + + return newSchema; + }), + tap(newSchema => { + this.replaceSchema(newSchema); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - public lockField(schema: SchemaDetailsDto, field: AnyFieldDto, now?: DateTime): Observable { + public lockField(schema: SchemaDetailsDto, field: T, now?: DateTime): Observable { return this.schemasService.lockField(this.appName, schema.name, field.fieldId, pidof(field), schema.version).pipe( - tap(dto => { - this.replaceField(schema, setLocked(field, true), dto.version, now); + mapVersioned(() => setLocked(field, true)), + tap(({ payload, version }) => { + this.replaceField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } - public enableField(schema: SchemaDetailsDto, field: AnyFieldDto, now?: DateTime): Observable { + public enableField(schema: SchemaDetailsDto, field: T, now?: DateTime): Observable { return this.schemasService.enableField(this.appName, schema.name, field.fieldId, pidof(field), schema.version).pipe( - tap(dto => { - this.replaceField(schema, setDisabled(field, false), dto.version, now); + mapVersioned(() => setDisabled(field, false)), + tap(({ payload, version }) => { + this.replaceField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } - public disableField(schema: SchemaDetailsDto, field: AnyFieldDto, now?: DateTime): Observable { + public disableField(schema: SchemaDetailsDto, field: T, now?: DateTime): Observable { return this.schemasService.disableField(this.appName, schema.name, field.fieldId, pidof(field), schema.version).pipe( - tap(dto => { - this.replaceField(schema, setDisabled(field, true), dto.version, now); + mapVersioned(() => setDisabled(field, true)), + tap(({ payload, version }) => { + this.replaceField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } - public showField(schema: SchemaDetailsDto, field: AnyFieldDto, now?: DateTime): Observable { + public showField(schema: SchemaDetailsDto, field: T, now?: DateTime): Observable { return this.schemasService.showField(this.appName, schema.name, field.fieldId, pidof(field), schema.version).pipe( - tap(dto => { - this.replaceField(schema, setHidden(field, false), dto.version, now); + mapVersioned(() => setHidden(field, false)), + tap(({ payload, version }) => { + this.replaceField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } - public hideField(schema: SchemaDetailsDto, field: AnyFieldDto, now?: DateTime): Observable { + public hideField(schema: SchemaDetailsDto, field: T, now?: DateTime): Observable { return this.schemasService.hideField(this.appName, schema.name, field.fieldId, pidof(field), schema.version).pipe( - tap(dto => { - this.replaceField(schema, setHidden(field, true), dto.version, now); + mapVersioned(() => setHidden(field, true)), + tap(({ payload, version }) => { + this.replaceField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } - public updateField(schema: SchemaDetailsDto, field: AnyFieldDto, request: UpdateFieldDto, now?: DateTime): Observable { + public updateField(schema: SchemaDetailsDto, field: T, request: UpdateFieldDto, now?: DateTime): Observable { return this.schemasService.putField(this.appName, schema.name, field.fieldId, request, pidof(field), schema.version).pipe( - tap(dto => { - this.replaceField(schema, update(field, request.properties), dto.version, now); + mapVersioned(() => update(field, request.properties)), + tap(({ payload, version }) => { + this.replaceField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs, { project: x => x.payload })); } public deleteField(schema: SchemaDetailsDto, field: AnyFieldDto, now?: DateTime): Observable { return this.schemasService.deleteField(this.appName, schema.name, field.fieldId, pidof(field), schema.version).pipe( - tap(dto => { - this.removeField(schema, field, dto.version, now); + mapVersioned(() => field), + tap(({ payload, version }) => { + this.removeField(schema, payload, version, now); }), - notify(this.dialogs)); + shareSubscribed(this.dialogs)); } - private replaceField(schema: SchemaDetailsDto, field: AnyFieldDto, version: Version, now?: DateTime) { + private replaceField(schema: SchemaDetailsDto, field: T, version: Version, now?: DateTime) { if (Types.is(field, RootFieldDto)) { this.replaceSchema(updateField(schema, field, this.user, version, now)); - } else { + } else if (Types.is(field, NestedFieldDto)) { const parent = schema.fields.find(x => x.fieldId === field.parentId); if (parent) { @@ -344,7 +375,7 @@ export class SchemasState extends State { } } -function buildCategories(categories: { [name: string]: boolean }, schemas: ImmutableArray) { +function buildCategories(categories: { [name: string]: boolean }, schemas: SchemasList) { categories = { ...categories }; for (let category in categories) { diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 024dec9f8..2aa19ca66 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -5,12 +5,12 @@ "requires": true, "dependencies": { "@angular-devkit/core": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.0.tgz", - "integrity": "sha512-b0qtAUpgqLpWY8W6vWRv1aj6bXkZCP1rvywl8i8TbGMY67CWRcy5J3fNAMmjiZS+LJixFlIXYf4iOydglyJMfg==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.8.tgz", + "integrity": "sha512-3X9uzaZXFpm5o2TSzhD6wEOtVU32CgeytKjD1Scxj+uMMVo48SWLlKiFh312T+smI9ko7tOT8VqxglwYkWosgg==", "dev": true, "requires": { - "ajv": "6.7.0", + "ajv": "6.9.1", "chokidar": "2.0.4", "fast-json-stable-stringify": "2.0.0", "rxjs": "6.3.3", @@ -18,9 +18,9 @@ }, "dependencies": { "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -315,9 +315,9 @@ "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -409,38 +409,38 @@ } }, "@angular/animations": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.3.tgz", - "integrity": "sha512-5WoiDnVS2OhGgJ1oepFNF2UcfR4sJj97KRnTmLWQ0S4N4WpXX83CoOQVXvXwfotyb8uNtl4zRi2NuvN/MIuFuA==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.14.tgz", + "integrity": "sha512-K+wdq7TslmvDhrbwy65x7owE8wezI0fDdO+8SO9RU4m/w6R6vo4QS3uSdc5I2pxwm4QSXSc5eKhoWJkq0muTbQ==", "requires": { "tslib": "^1.9.0" } }, "@angular/common": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.3.tgz", - "integrity": "sha512-VZOTZdvkitaKEhkxL6daHxPcKqAFwNJm0U4NFB4LRP9KspsFTE60QFVB63o129PTIH9iOQ2D3HRKSRl4o78ZKg==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.14.tgz", + "integrity": "sha512-c2QBhVpbQhg1FDhOQkyVdFvU11mfvYHW5ZaXzxdCpq2rZXCureYiCSnlv++EsIAKqi22+2a6GACHF9Gh8kBmSg==", "requires": { "tslib": "^1.9.0" } }, "@angular/compiler": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.3.tgz", - "integrity": "sha512-UM6n4MyZkR5+VVjlwhLH8IfqdWBkdFcF5at4ckJXOJ/gkIUq97irbis9pGj1b0TO7MAl8uhF4b68xe5lk8b49g==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.14.tgz", + "integrity": "sha512-Idhs+5HIzx+1+hrXIDaRpSqobMB7UvSvPlvCvtb3EDYjmltTNG68TtwMzGM8W2jdayliYuFOjFrnw1wCTkK3Ag==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "@angular/compiler-cli": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.3.tgz", - "integrity": "sha512-31hcfTrU2GW66cvvaS629dNVPfiUrUWPncI28optvmKHBaH0mFqkdYNgabuslsXZV5AeidKMUJvR7GITjtvkQA==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.14.tgz", + "integrity": "sha512-w5qn1nIPjiCP3WdbqicofpKpiRlh6NMYjWhe6mJysSBnVd34aSuGisYW/gVPQrmD46E1gmfpWTnWPeABVnjj6w==", "dev": true, "requires": { "canonical-path": "1.0.0", - "chokidar": "^1.4.2", + "chokidar": "^2.1.1", "convert-source-map": "^1.5.1", "dependency-graph": "^0.7.2", "magic-string": "^0.25.0", @@ -452,305 +452,975 @@ "yargs": "9.0.1" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" }, "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "remove-trailing-separator": "^1.0.1" } } } }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, - "load-json-file": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "p-try": "^1.0.0" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "fsevents": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", + "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", "dev": true, + "optional": true, "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "pify": "^2.0.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" + "kind-of": "^6.0.0" } }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" + "kind-of": "^6.0.0" } }, - "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, - "string-width": { + "is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "kind-of": "^3.0.2" }, "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "is-buffer": "^1.1.5" } } } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, - "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "read-pkg-up": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } } } }, "@angular/core": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.3.tgz", - "integrity": "sha512-6Ql+sJJnrsxh8O0/IgIP1GgT4eLOHk+dlBs7zBbjstmLuhaQdY+awO9WKoQow+TiD1Go7FW1J3vZ2PTWXKxqjQ==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.14.tgz", + "integrity": "sha512-XeZZJCyBKSKo0E/7Ef0SfJejmn+E7uBXa5cR1QapafS0Hnrq/hZu/NI039IDU/51NoycMDH2vTV19SmKu9Mkow==", "requires": { "tslib": "^1.9.0" } }, "@angular/forms": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.3.tgz", - "integrity": "sha512-mZpyonfSmRwSvM6efvwFwkLJkK6wHQrm7X4OhVVu3s9i7BI253eLDY7WIRXFvoxJ/5jWIIarVnd/9UA7GINZGw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.14.tgz", + "integrity": "sha512-jL5YbTk7VZmz4l0++iFVUNa1vGM+nnALjHKi1Ub8VWioRDRboYUsHyxzlgWW9gZRbHpnLEXFiUz1td+v7TouJw==", "requires": { "tslib": "^1.9.0" } }, "@angular/http": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.3.tgz", - "integrity": "sha512-wzvBKbO/TcSR3U8AQbsGftH8x1OdAgVGHlfXQPmZL1KjIDHrM1VpnkSvgqIt8coG+4OPfWcNklUCrTdEGwqMqw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.14.tgz", + "integrity": "sha512-rSdH2JojApDU83qVm7RabIlNo3Ni3yr2gwsmQWs4XZ7SC8jLNnDkzdUbQ6T0vfuVX3v/FtAuMJl0yaVcG3EUJg==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.3.tgz", - "integrity": "sha512-DH0Y2lgEgcrP1I/DUQB/krL7Ob7yL685fu4sRapW17SndTQa2pqSFMBVf+mN3FupTXp7nJHSvlIktzedIk04+g==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.14.tgz", + "integrity": "sha512-yAq2+3W4J4B48HEmZYQucdEb9AHwRnv72q9CC/SxU7g59vaLhl1nv7cAWGJ4XFaJTbB7aB4Y4rLffuR+Gxkn7A==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser-dynamic": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.3.tgz", - "integrity": "sha512-M8Kiz5FUhnFybJuk/mgOhBjVbRgKDC4bGWKWH9Z9SXBR2dS/FL3QOJsLIthQcWlHOzSoJdEoPBRhn0R4pyLBSw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.14.tgz", + "integrity": "sha512-lmTCBiDRbOPtniIqBjm1n5jl1TdyQM0qWQdBcoCsKpMNS/6/RacRcQsJZApAMdWm6gIVuLgmRQzaCLkSoekfYA==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-server": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-7.2.3.tgz", - "integrity": "sha512-RXTFuuTlvy02YOtjWsrs8q+wnmXNW1JHueEseb8cWrgJz46ezhjuW3vwquDv1PwO5KZD2wlamZcrlbkwsdyzZw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-7.2.14.tgz", + "integrity": "sha512-ijFqRrxpbPQiAlbRtw0uKX8Qf+wWZhY5vNwV8wfP5oVziJdO7Vdtcmmw2NQxHAIHUrK7FQ5yklUxfglKa2G7SQ==", "requires": { "domino": "^2.1.0", "tslib": "^1.9.0", @@ -758,9 +1428,9 @@ } }, "@angular/router": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.3.tgz", - "integrity": "sha512-SH7H2I9WTj1puei4m4g5n0/Cp28HS14q4r8lOgW0gLWuT6Ls7MqH/nDjOMiW924iRR6zjQQs7G+WbhL1jmZc2A==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.14.tgz", + "integrity": "sha512-uqg0SKy79voEOIOvzVbCzFDD9XOAfZWkYt01ca2qLFXMx+6jWeVQIDuXc8Dmz5udIXNK5Ae//9R+nt5UZUZrSA==", "requires": { "tslib": "^1.9.0" } @@ -775,14 +1445,14 @@ } }, "@babel/generator": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", - "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", "dev": true, "requires": { - "@babel/types": "^7.2.2", + "@babel/types": "^7.4.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" }, @@ -793,6 +1463,12 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -822,12 +1498,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.4.4" } }, "@babel/highlight": { @@ -842,52 +1518,58 @@ } }, "@babel/parser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", - "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz", + "integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==", "dev": true }, "@babel/template": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", - "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.2.2", - "@babel/types": "^7.2.2" + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" } }, "@babel/traverse": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", - "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz", + "integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.2.2", + "@babel/generator": "^7.4.4", "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.2.3", - "@babel/types": "^7.2.2", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" }, "dependencies": { "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" } }, "globals": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", - "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "ms": { @@ -899,16 +1581,22 @@ } }, "@babel/types": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz", - "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" }, "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -918,12 +1606,12 @@ } }, "@ngtools/webpack": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.0.tgz", - "integrity": "sha512-U/By0Jlwy7nYwrGNtFirTg1aAsEHBL/9DhfFxPI0iu27FWiMttROuN6hmKbbnOmpbiYAVl5qTy3WXPXUIJjG1A==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.8.tgz", + "integrity": "sha512-gfjSKz+F/2T4tZHpnQ1XqelKP/CIfI87XdoHsOI53ceTUrAkVKsOb3ULmEfkcdsdQZ/HhmCiLivcutHcW8xkhQ==", "dev": true, "requires": { - "@angular-devkit/core": "7.3.0", + "@angular-devkit/core": "7.3.8", "enhanced-resolve": "4.1.0", "rxjs": "6.3.3", "tree-kill": "1.2.1", @@ -958,9 +1646,9 @@ "dev": true }, "@types/jasmine": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.8.tgz", - "integrity": "sha512-BaOFpaddRVV8qykJoWHrHtamml880oh0+DIZWbtJgx0pu+KhDF1gER5hSfCIfzyMrbjMuYFnLUfyo1l0JUVU3Q==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.12.tgz", + "integrity": "sha512-lXvr2xFQEVQLkIhuGaR3GC1L9lMU1IxeWnAF/wNY5ZWpC4p9dgxkKkzMp7pntpAdv9pZSnYqgsBkCg32MXSZMg==", "dev": true }, "@types/json5": { @@ -970,9 +1658,9 @@ "dev": true }, "@types/marked": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.6.0.tgz", - "integrity": "sha512-TxwhgR9VsIfRDJ3WwFokG8Xu+ea0nYGDRHdI783WJ983uffatz0ytIeUEIBOwPvRy241KRSNVyywQltuTqDh0w==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.6.5.tgz", + "integrity": "sha512-6kBKf64aVfx93UJrcyEZ+OBM5nGv4RLsI6sR1Ar34bpgvGVRoyTgpxn4ZmtxOM5aDTAaaznYuYUH8bUX3Nk3YA==", "dev": true }, "@types/mousetrap": { @@ -982,15 +1670,15 @@ "dev": true }, "@types/node": { - "version": "10.12.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.21.tgz", - "integrity": "sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ==", + "version": "11.13.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz", + "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==", "dev": true }, "@types/prop-types": { - "version": "15.5.8", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.8.tgz", - "integrity": "sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==", + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", + "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==", "dev": true }, "@types/q": { @@ -1000,9 +1688,9 @@ "dev": true }, "@types/react": { - "version": "16.8.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.1.tgz", - "integrity": "sha512-tD1ETKJcuhANOejRc/p7OgQ16DKnbGi0M3LccelKlPnUCDp2a5koVxZFoRN9HN+A+m84HB5VGN7I+r3nNhS3PA==", + "version": "16.8.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.14.tgz", + "integrity": "sha512-26tFVJ1omGmzIdFTFmnC5zhz1GTaqCjxgUxV4KzWvsybF42P7/j4RBn6UeO3KbHPXqKWZszMXMoI65xIWm954A==", "dev": true, "requires": { "@types/prop-types": "*", @@ -1010,9 +1698,9 @@ } }, "@types/react-dom": { - "version": "16.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.0.11.tgz", - "integrity": "sha512-x6zUx9/42B5Kl2Vl9HlopV8JF64wLpX3c+Pst9kc1HgzrsH+mkehe/zmHMQTplIrR48H2gpU7ZqurQolYu8XBA==", + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.4.tgz", + "integrity": "sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==", "dev": true, "requires": { "@types/react": "*" @@ -1025,175 +1713,179 @@ "dev": true }, "@webassemblyjs/ast": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", - "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11" + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", - "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", - "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", - "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", - "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.7.11" + "@webassemblyjs/wast-printer": "1.8.5" } }, "@webassemblyjs/helper-fsm": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", - "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", - "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", - "dev": true + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", - "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", - "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" } }, "@webassemblyjs/ieee754": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", - "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", - "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", "dev": true, "requires": { - "@xtuc/long": "4.2.1" + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", - "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", - "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/helper-wasm-section": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-opt": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "@webassemblyjs/wast-printer": "1.7.11" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" } }, "@webassemblyjs/wasm-gen": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", - "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" } }, "@webassemblyjs/wasm-opt": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", - "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" } }, "@webassemblyjs/wasm-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", - "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" } }, "@webassemblyjs/wast-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", - "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/floating-point-hex-parser": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-code-frame": "1.7.11", - "@webassemblyjs/helper-fsm": "1.7.11", - "@xtuc/long": "4.2.1" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", - "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11", - "@xtuc/long": "4.2.1" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" } }, "@xtuc/ieee754": { @@ -1203,15 +1895,15 @@ "dev": true }, "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "accepts": { @@ -1225,9 +1917,9 @@ } }, "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "dev": true }, "acorn-dynamic-import": { @@ -1283,17 +1975,6 @@ "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "dev": true }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, "alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", @@ -1347,9 +2028,9 @@ } }, "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", "dev": true }, "ansi-escapes": { @@ -1407,9 +2088,9 @@ } }, "app-root-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", - "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", + "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==", "dev": true }, "append-transform": { @@ -1445,6 +2126,16 @@ "sprintf-js": "~1.0.2" } }, + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -1496,12 +2187,6 @@ "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", "dev": true }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -1529,12 +2214,6 @@ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -1599,12 +2278,29 @@ "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", "dev": true }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", @@ -1939,6 +2635,15 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, + "axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -2075,6 +2780,13 @@ "babel-runtime": "^6.26.0", "core-js": "^2.5.0", "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" + } } }, "babel-register": { @@ -2092,6 +2804,12 @@ "source-map-support": "^0.4.15" }, "dependencies": { + "core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -2118,6 +2836,11 @@ "regenerator-runtime": "^0.11.0" }, "dependencies": { + "core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==" + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -2321,9 +3044,9 @@ } }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", + "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", "dev": true }, "bn.js": { @@ -2333,21 +3056,21 @@ "dev": true }, "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { - "bytes": "3.0.0", + "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" } }, "bonjour": { @@ -2371,9 +3094,9 @@ "dev": true }, "bootstrap": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.2.1.tgz", - "integrity": "sha512-tt/7vIv3Gm2mnd/WeDx36nfGGHleil0Wg8IeB7eMrVkY0fZ5iTaBisSh8oNANc2IBsCc6vCgCNTIM/IEN0+50Q==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", + "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==" }, "brace-expansion": { "version": "1.1.11", @@ -2547,9 +3270,9 @@ "dev": true }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "cacache": { @@ -2574,12 +3297,6 @@ "y18n": "^4.0.0" }, "dependencies": { - "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", - "dev": true - }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -2697,11 +3414,10 @@ } }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true }, "camelcase-keys": { "version": "2.1.0", @@ -2751,17 +3467,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -2842,9 +3547,9 @@ } }, "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, "class-utils": { @@ -2909,23 +3614,26 @@ "dev": true }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, - "optional": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" }, "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, - "optional": true + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } } } }, @@ -2982,17 +3690,20 @@ "dev": true }, "codelyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz", - "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.0.1.tgz", + "integrity": "sha512-UVV76+/y1RwaxzCeGPFE3G4GFtfV42r3x8EmRd7XMNFLlLC0ewdtCqWTbvhwPQMxFZZ+OTLEOJNWfyPPn3QFWg==", "dev": true, "requires": { "app-root-path": "^2.1.0", - "css-selector-tokenizer": "^0.7.0", + "aria-query": "^3.0.0", + "axobject-query": "^2.0.2", + "css-selector-tokenizer": "^0.7.1", "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", "semver-dsl": "^1.0.1", "source-map": "^0.5.7", - "sprintf-js": "^1.1.1" + "sprintf-js": "^1.1.2" }, "dependencies": { "source-map": { @@ -3002,17 +3713,17 @@ "dev": true }, "sprintf-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "dev": true } } }, "codemirror": { - "version": "5.42.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.42.0.tgz", - "integrity": "sha512-pbApC8zDzItP3HRphD6kQVwS976qB5Qi0hU3MZMixLk+AyugOW1RF+8XJEjeyl5yWsHNe88tDUxzeRh5AOxPRw==" + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.46.0.tgz", + "integrity": "sha512-3QpMge0vg4QEhHW3hBAtCipJEWjTJrqLLXdIaWptJOblf1vHFeXLNtFhPai/uX2lnFCehWNk4yOdaMR853Z02w==" }, "codemirror-graphql": { "version": "0.7.1", @@ -3080,15 +3791,6 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -3135,27 +3837,35 @@ "dev": true }, "compressible": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", - "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", + "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", "dev": true, "requires": { - "mime-db": ">= 1.36.0 < 2" + "mime-db": ">= 1.40.0 < 2" } }, "compression": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", - "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, "requires": { "accepts": "~1.3.5", "bytes": "3.0.0", - "compressible": "~2.0.14", + "compressible": "~2.0.16", "debug": "2.6.9", - "on-headers": "~1.0.1", + "on-headers": "~1.0.2", "safe-buffer": "5.1.2", "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + } } }, "concat-map": { @@ -3188,9 +3898,9 @@ } }, "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "dev": true }, "console-browserify": { @@ -3368,12 +4078,13 @@ } }, "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", "which": "^1.2.9" } }, @@ -3435,18 +4146,19 @@ } }, "css-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.0.tgz", - "integrity": "sha512-MoOu+CStsGrSt5K2OeZ89q3Snf+IkxRfAIt9aAKg4piioTrhtP1iEFPu+OVn3Ohz24FO6L+rw9UJxBILiSBw5Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", + "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", "dev": true, "requires": { - "icss-utils": "^4.0.0", - "loader-utils": "^1.2.1", - "lodash": "^4.17.11", - "postcss": "^7.0.6", + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.3", - "postcss-modules-scope": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", "postcss-modules-values": "^2.0.0", "postcss-value-parser": "^3.3.0", "schema-utils": "^1.0.0" @@ -3458,9 +4170,15 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "json5": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { @@ -3478,10 +4196,10 @@ "json5": "^1.0.1" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true } } @@ -3505,9 +4223,9 @@ "dev": true }, "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", "dev": true, "requires": { "cssesc": "^0.1.0", @@ -3737,9 +4455,9 @@ } }, "csstype": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.2.tgz", - "integrity": "sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz", + "integrity": "sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==", "dev": true }, "currently-unhandled": { @@ -3772,6 +4490,12 @@ "es5-ext": "^0.10.9" } }, + "damerau-levenshtein": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -3782,9 +4506,9 @@ } }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", + "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", "dev": true }, "date-now": { @@ -3833,13 +4557,52 @@ "dev": true }, "default-gateway": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", - "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "ip-regex": "^2.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } } }, "default-require-extensions": { @@ -3849,14 +4612,6 @@ "dev": true, "requires": { "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } } }, "define-properties": { @@ -3922,18 +4677,25 @@ } }, "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.0.tgz", + "integrity": "sha512-C4kvKNlYrwXhKxz97BuohF8YoGgQ23Xm9lvoHmgT7JaPGprSEjk3+XFled74Yt/x0ZABUHg2D67covzAPUKx5Q==", "dev": true, "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, "delayed-stream": { @@ -4124,9 +4886,9 @@ } }, "domino": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.1.tgz", - "integrity": "sha512-fqoTi6oQ881wYRENIEmz78hKVoc3X9HqVpklo419yxzebys6dtU5c83iVh3UYvvexPFdAuwlDYCsUM9//CrMMg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.3.tgz", + "integrity": "sha512-EwjTbUv1Q/RLQOdn9k7ClHutrQcWGsfXaRQNOnM/KgK4xDBoLFEcIRFuBSxAx13Vfa63X029gXYrNFrSy+DOSg==" }, "domutils": { "version": "1.5.1", @@ -4154,9 +4916,9 @@ "dev": true }, "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -4458,14 +5220,6 @@ "es6-weak-map": "^2.0.1", "esrecurse": "^4.1.0", "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "eslint": { @@ -4528,10 +5282,10 @@ "supports-color": "^2.0.0" } }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "shelljs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", + "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=", "dev": true }, "supports-color": { @@ -4543,9 +5297,9 @@ } }, "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -4574,14 +5328,6 @@ "dev": true, "requires": { "estraverse": "^4.1.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "estraverse": { @@ -4644,33 +5390,18 @@ } }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "^6.0.0", + "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } } }, "exit-hook": { @@ -4679,50 +5410,6 @@ "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", "dev": true }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - } - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -4794,6 +5481,30 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, "finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", @@ -4809,6 +5520,51 @@ "unpipe": "~1.0.0" } }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -4981,13 +5737,13 @@ } }, "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^1.0.0", + "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" } }, @@ -4998,13 +5754,12 @@ "dev": true }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "locate-path": "^2.0.0" } }, "findup-sync": { @@ -5311,23 +6066,15 @@ } }, "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, "requires": { "circular-json": "^0.3.1", - "del": "^2.0.2", "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", "write": "^0.2.1" - }, - "dependencies": { - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - } } }, "flatted": { @@ -5337,32 +6084,38 @@ "dev": true }, "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" } }, "follow-redirects": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", - "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, "requires": { - "debug": "=3.1.0" + "debug": "^3.2.6" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -5448,13 +6201,13 @@ } }, "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", + "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, @@ -5496,7 +6249,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5911,7 +6665,8 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -5967,6 +6722,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6010,12 +6766,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -6051,6 +6809,19 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "gaze": { @@ -6063,10 +6834,13 @@ } }, "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } }, "generate-object-property": { "version": "1.2.0", @@ -6163,12 +6937,6 @@ "resolve-dir": "^1.0.0" } }, - "global-modules-path": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.1.tgz", - "integrity": "sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==", - "dev": true - }, "global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", @@ -6189,13 +6957,12 @@ "dev": true }, "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { "array-union": "^1.0.1", - "arrify": "^1.0.0", "glob": "^7.0.3", "object-assign": "^4.0.1", "pify": "^2.0.0", @@ -6237,9 +7004,9 @@ "dev": true }, "graphiql": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-0.12.0.tgz", - "integrity": "sha512-OM5dpcONLK1B2prez2WVTfohQlQKe4Fwv1YwNQYQhN+fFGEW87D5v5fN2M8ZebzxbZHqP12KkHicO3sv8k30TQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-0.13.0.tgz", + "integrity": "sha512-m2RBtSY1CQLz4XqCftQC0V9ZcbUXEx2Uwvuok3L/TJtsN5HOHUmPxGhOAZs7mESaAsg7Z8Tgy04BmYirDyfWug==", "requires": { "codemirror": "^5.26.0", "codemirror-graphql": "^0.7.1", @@ -6247,9 +7014,9 @@ } }, "graphql": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.1.1.tgz", - "integrity": "sha512-C5zDzLqvfPAgTtP8AUPIt9keDabrdRAqSWjj2OPRKrKxI9Fb65I36s1uCs1UUBFnSWTdO7hyHi7z1ZbwKMKF6Q==", + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.2.1.tgz", + "integrity": "sha512-2PL1UbvKeSjy/lUeJqHk+eR9CvuErXoCNwJI4jm3oNFEeY+9ELqHNKO1ZuSxAkasPkpWbmT/iMRMFxd3cEL3tQ==", "requires": { "iterall": "^1.2.2" } @@ -6326,46 +7093,22 @@ "dev": true }, "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { - "async": "^1.4.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" }, "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true } } }, @@ -6386,9 +7129,9 @@ }, "dependencies": { "ajv": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", - "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -6593,9 +7336,9 @@ } }, "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "requires": { "parse-passwd": "^1.0.0" @@ -6754,15 +7497,16 @@ "dev": true }, "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } }, "http-parser-js": { @@ -6783,15 +7527,15 @@ } }, "http-proxy-middleware": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", - "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", "dev": true, "requires": { - "http-proxy": "^1.16.2", + "http-proxy": "^1.17.0", "is-glob": "^4.0.0", - "lodash": "^4.17.5", - "micromatch": "^3.1.9" + "lodash": "^4.17.11", + "micromatch": "^3.1.10" }, "dependencies": { "arr-diff": { @@ -7022,9 +7766,9 @@ "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -7062,6 +7806,12 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -7103,9 +7853,9 @@ "dev": true }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -7118,18 +7868,18 @@ "dev": true }, "icss-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.0.0.tgz", - "integrity": "sha512-bA/xGiwWM17qjllIs9X/y0EjsB7e0AV08F3OL8UPsoNkNRibIuu8f1eKTnQ8QO1DteKKTxTUAn+IEWUToIwGOA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", + "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", "dev": true, "requires": { - "postcss": "^7.0.5" + "postcss": "^7.0.14" } }, "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, "iferr": { @@ -7282,6 +8032,17 @@ "supports-color": "^2.0.0" } }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -7291,13 +8052,13 @@ } }, "internal-ip": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz", - "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", "dev": true, "requires": { - "default-gateway": "^2.6.0", - "ipaddr.js": "^1.5.2" + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" } }, "interpret": { @@ -7334,9 +8095,9 @@ "dev": true }, "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", "dev": true }, "is-absolute-url": { @@ -7375,15 +8136,6 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", @@ -7533,29 +8285,35 @@ "dev": true }, "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.1.0.tgz", + "integrity": "sha512-Sc5j3/YnM8tDeyCsVeKlm/0p95075DyLmDEIkSgQ7mXkrOX+uTCtmQFm0CYzVyJwcCCmO3k8qfJt17SxQwB5Zw==", "dev": true }, "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "^2.1.0" } }, "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "^1.0.2" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -7688,44 +8446,36 @@ "dev": true }, "istanbul-api": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.0.6.tgz", - "integrity": "sha512-8W5oeAGWXhtTJjAyVfvavOLVyZCTNCKsyF6GON/INKlBdO7uJ/bv3qnPj5M6ERKzmMCJS1kntnjjGuJ86fn3rQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.5.tgz", + "integrity": "sha512-meYk1BwDp59Pfse1TvPrkKYgVqAufbdBLEVoqvu/hLLKSaQ054ZTksbNepyc223tMnWdm6AdK2URIJJRqdP87g==", "dev": true, "requires": { "async": "^2.6.1", "compare-versions": "^3.2.1", "fileset": "^2.0.3", - "istanbul-lib-coverage": "^2.0.1", - "istanbul-lib-hook": "^2.0.1", - "istanbul-lib-instrument": "^3.0.0", - "istanbul-lib-report": "^2.0.2", - "istanbul-lib-source-maps": "^2.0.1", - "istanbul-reports": "^2.0.1", - "js-yaml": "^3.12.0", - "make-dir": "^1.3.0", + "istanbul-lib-coverage": "^2.0.4", + "istanbul-lib-hook": "^2.0.6", + "istanbul-lib-instrument": "^3.2.0", + "istanbul-lib-report": "^2.0.7", + "istanbul-lib-source-maps": "^3.0.5", + "istanbul-reports": "^2.2.3", + "js-yaml": "^3.13.0", + "make-dir": "^2.1.0", + "minimatch": "^3.0.4", "once": "^1.4.0" }, "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, "istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-LXTBICkMARVgo579kWDm8SqfB6nvSDKNqIOBEjmJRnL04JvoMHCYGWaMddQnseJYtkEuEvO/sIcOxPLk9gERug==", "dev": true }, "istanbul-lib-instrument": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.0.0.tgz", - "integrity": "sha512-eQY9vN9elYjdgN9Iv6NS/00bptm02EBBk70lRMaVjeA6QYocQgenVrSgC28TJurdnZa80AGO3ASdFN+w/njGiQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.2.0.tgz", + "integrity": "sha512-06IM3xShbNW4NgZv5AP4QH0oHqf1/ivFo8eFys0ZjPXHGldHJQWb3riYOKXqmOqfxXBfxu4B+g/iuhOPZH0RJg==", "dev": true, "requires": { "@babel/generator": "^7.0.0", @@ -7733,9 +8483,25 @@ "@babel/template": "^7.0.0", "@babel/traverse": "^7.0.0", "@babel/types": "^7.0.0", - "istanbul-lib-coverage": "^2.0.1", - "semver": "^5.5.0" + "istanbul-lib-coverage": "^2.0.4", + "semver": "^6.0.0" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" } + }, + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true } } }, @@ -7781,9 +8547,9 @@ "dev": true }, "istanbul-lib-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.1.tgz", - "integrity": "sha512-ufiZoiJ8CxY577JJWEeFuxXZoMqiKpq/RqZtOAYuQLvlkbJWscq9n3gc4xrCGH9n4pW0qnTxOz1oyMmVtk8E1w==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.6.tgz", + "integrity": "sha512-829DKONApZ7UCiPXcOYWSgkFXa4+vNYoNOt3F+4uDJLKL1OotAoVwvThoEj1i8jmOj7odbYcR3rnaHu+QroaXg==", "dev": true, "requires": { "append-transform": "^1.0.0" @@ -7805,50 +8571,59 @@ } }, "istanbul-lib-report": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.2.tgz", - "integrity": "sha512-rJ8uR3peeIrwAxoDEbK4dJ7cqqtxBisZKCuwkMtMv0xYzaAnsAi3AHrHPAAtNXzG/bcCgZZ3OJVqm1DTi9ap2Q==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.7.tgz", + "integrity": "sha512-wLH6beJBFbRBLiTlMOBxmb85cnVM1Vyl36N48e4e/aTKSM3WbOx7zbVIH1SQ537fhhsPbX0/C5JB4qsmyRXXyA==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.1", - "make-dir": "^1.3.0", - "supports-color": "^5.4.0" + "istanbul-lib-coverage": "^2.0.4", + "make-dir": "^2.1.0", + "supports-color": "^6.0.0" }, "dependencies": { "istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-LXTBICkMARVgo579kWDm8SqfB6nvSDKNqIOBEjmJRnL04JvoMHCYGWaMddQnseJYtkEuEvO/sIcOxPLk9gERug==", "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, "istanbul-lib-source-maps": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.1.tgz", - "integrity": "sha512-30l40ySg+gvBLcxTrLzR4Z2XTRj3HgRCA/p2rnbs/3OiTaoj054gAbuP5DcLOtwqmy4XW8qXBHzrmP2/bQ9i3A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.5.tgz", + "integrity": "sha512-eDhZ7r6r1d1zQPVZehLc3D0K14vRba/eBYkz3rw16DLOrrTzve9RmnkcwrrkWVgO1FL3EK5knujVe5S8QHE9xw==", "dev": true, "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^2.0.1", - "make-dir": "^1.3.0", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.4", + "make-dir": "^2.1.0", "rimraf": "^2.6.2", "source-map": "^0.6.1" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" } }, "istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-LXTBICkMARVgo579kWDm8SqfB6nvSDKNqIOBEjmJRnL04JvoMHCYGWaMddQnseJYtkEuEvO/sIcOxPLk9gERug==", "dev": true }, "ms": { @@ -7860,12 +8635,12 @@ } }, "istanbul-reports": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.0.1.tgz", - "integrity": "sha512-CT0QgMBJqs6NJLF678ZHcquUAZIoBIUNzdJrRJfpkI9OnzG6MkUfHxbJC3ln981dMswC7/B1mfX3LNkhgJxsuw==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.3.tgz", + "integrity": "sha512-T6EbPuc8Cb620LWAYyZ4D8SSn06dY9i1+IgUX2lTH8gbwflMc9Obd33zHTyNX653ybjpamAHS9toKS3E6cGhTw==", "dev": true, "requires": { - "handlebars": "^4.0.11" + "handlebars": "^4.1.0" } }, "iterall": { @@ -7874,15 +8649,15 @@ "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" }, "jasmine-core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.3.0.tgz", - "integrity": "sha512-3/xSmG/d35hf80BEN66Y6g9Ca5l/Isdeg/j6zvbTYlTzeKinzmaTM4p9am5kYqOmE05D7s1t8FGjzdSnbUbceA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz", + "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==", "dev": true }, "js-base64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz", - "integrity": "sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", "dev": true }, "js-tokens": { @@ -7957,9 +8732,9 @@ "dev": true }, "jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "^4.1.6" @@ -7989,34 +8764,28 @@ "verror": "1.10.0" } }, - "jsrsasign": { - "version": "8.0.12", - "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.12.tgz", - "integrity": "sha1-Iqu5ZW00owuVMENnIINeicLlwxY=" - }, "karma": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.0.0.tgz", - "integrity": "sha512-EFoFs3F6G0BcUGPNOn/YloGOb3h09hzTguyXlg6loHlKY76qbJikkcyPk43m2kfRF65TUGda/mig29QQtyhm1g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", + "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", + "braces": "^2.3.2", "chokidar": "^2.0.3", "colors": "^1.1.0", - "combine-lists": "^1.0.0", "connect": "^3.6.0", "core-js": "^2.2.0", "di": "^0.0.1", "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", + "lodash": "^4.17.11", + "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -8036,220 +8805,753 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", "to-regex": "^3.0.1" }, "dependencies": { - "extend-shallow": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", + "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-descriptor": "^0.1.0" + "minipass": "^2.2.1" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "mkdirp": { + "version": "0.5.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "minimist": "0.0.8" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "kind-of": "^3.0.2" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "minimist": { + "version": "1.2.0", + "bundled": true, "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "optional": true } } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "readable-stream": { + "version": "2.3.6", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "rimraf": { + "version": "2.6.3", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-descriptor": "^1.0.0" + "glob": "^7.1.3" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "bundled": true, "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true } } }, @@ -8281,6 +9583,14 @@ "dev": true, "requires": { "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "is-data-descriptor": { @@ -8290,6 +9600,14 @@ "dev": true, "requires": { "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "is-descriptor": { @@ -8301,6 +9619,14 @@ "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "is-extglob": { @@ -8310,9 +9636,9 @@ "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -8325,17 +9651,6 @@ "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "isobject": { @@ -8344,10 +9659,10 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "micromatch": { @@ -8369,6 +9684,57 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } } } @@ -8393,12 +9759,12 @@ } }, "karma-coverage-istanbul-reporter": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.4.tgz", - "integrity": "sha512-xJS7QSQIVU6VK9HuJ/ieE5yynxKhjCCkd96NLY/BX/HXsx0CskU9JJiMQbd4cHALiddMwI4OWh1IIzeWrsavJw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.5.tgz", + "integrity": "sha512-yPvAlKtY3y+rKKWbOo0CzBMVTvJEeMOgbMXuVv3yWvS8YtYKC98AU9vFF0mVBZ2RP1E9SgS90+PT6Kf14P3S4w==", "dev": true, "requires": { - "istanbul-api": "^2.0.5", + "istanbul-api": "^2.1.1", "minimatch": "^3.0.4" } }, @@ -8421,9 +9787,9 @@ } }, "karma-jasmine-html-reporter": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.0.tgz", - "integrity": "sha512-0wxhwA8PLPpICZ4o2GRnPi67hf3JhfQm5WCB8nElh4qsE6wRNOTtrqooyBPNqI087Xr2SBhxLg5fU+BJ/qxRrw==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.2.tgz", + "integrity": "sha512-7g0gPj8+9JepCNJR9WjDyQ2RkZ375jpdurYQyAYv8PorUCadepl8vrD6LmMqOGcM17cnrynBawQYZHaumgDjBw==", "dev": true }, "karma-mocha-reporter": { @@ -8525,13 +9891,6 @@ "webpack-sources": "^1.1.0" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -8551,12 +9910,6 @@ "type-check": "~0.3.2" } }, - "lightercollective": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lightercollective/-/lightercollective-0.1.0.tgz", - "integrity": "sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==", - "dev": true - }, "linkify-it": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.1.0.tgz", @@ -8566,16 +9919,15 @@ } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "strip-bom": "^3.0.0" } }, "loader-runner": { @@ -8596,21 +9948,13 @@ } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "p-locate": "^3.0.0", + "p-locate": "^2.0.0", "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } } }, "lodash": { @@ -8618,24 +9962,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, "lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", "dev": true }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -8654,12 +9986,6 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, "lodash.tail": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", @@ -8682,22 +10008,22 @@ } }, "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.1.0.tgz", + "integrity": "sha512-eDa+zZPeVEeK6QGJAePyXM6pg4P3n3TO5rX9iZMVY48JshsTyLJZLIL5HipI1kQ2qLsSyOpUqNND/C5H4WhhiA==", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", "rfdc": "^1.1.2", - "streamroller": "0.7.0" + "streamroller": "^1.0.4" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -8727,12 +10053,6 @@ "object.assign": "^4.1.0" } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -8768,35 +10088,48 @@ } }, "magic-string": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", - "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz", + "integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==", "dev": true, "requires": { - "sourcemap-codec": "^1.4.1" + "sourcemap-codec": "^1.4.4" } }, "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "dependencies": { "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true } } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz", - "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { "p-defer": "^1.0.0" @@ -8836,9 +10169,9 @@ } }, "marked": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.0.tgz", - "integrity": "sha512-HduzIW2xApSXKXJSpCipSxKyvMbwRRa/TwMbepmlZziKdH8548WSoDP4SxzulEKjlo8BE39l+2fwJZuRKOln6g==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.2.tgz", + "integrity": "sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA==" }, "math-random": { "version": "1.0.1", @@ -8875,14 +10208,12 @@ "dev": true }, "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" + "mimic-fn": "^1.0.0" } }, "memory-fs": { @@ -8911,6 +10242,81 @@ "read-pkg-up": "^1.0.1", "redent": "^1.0.0", "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } } }, "merge": { @@ -8969,18 +10375,18 @@ "dev": true }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", "dev": true }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "dev": true, "requires": { - "mime-db": "~1.37.0" + "mime-db": "1.40.0" } }, "mimic-fn": { @@ -8990,14 +10396,28 @@ "dev": true }, "mini-css-extract-plugin": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", - "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", + "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==", "dev": true, "requires": { "loader-utils": "^1.1.0", + "normalize-url": "^2.0.1", "schema-utils": "^1.0.0", "webpack-sources": "^1.1.0" + }, + "dependencies": { + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + } } }, "minimalistic-assert": { @@ -9106,9 +10526,9 @@ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, "mousetrap": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.2.tgz", - "integrity": "sha512-jDjhi7wlHwdO6q6DS7YRmSHcuI+RVxadBkLt3KHrhd3C2b+w5pKefg3oj5beTcHZyVFA9Aksf+yEE1y5jxUjVA==" + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.3.tgz", + "integrity": "sha512-bd+nzwhhs9ifsUrC2tWaSgm24/oo2c83zaRyZQF06hYA6sANfsXHtnZ19AbbbDXCDzeH5nZBSQ4NvCjgD62tJA==" }, "move-concurrently": { "version": "1.0.1", @@ -9156,7 +10576,8 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -9221,9 +10642,9 @@ "integrity": "sha512-5mWWBePwvEPsNd/HkdbD543Q9mPyJofL6zkNydl8/Ah3qrrvZT2DaEPbknY08OgkXpI2qUGksc01OzzVlRQ9dQ==" }, "ngx-color-picker": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-7.3.0.tgz", - "integrity": "sha512-ICFR+bGfDFqiXadv8EuKylQGKn8JwkRxor0Grx6hVQVsmvLve/Z2mCDtCMItRQXjLI+4yO3iBDf9Oi1pGuBraQ==" + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-7.5.0.tgz", + "integrity": "sha512-bTW16A3IitWUNGc3kZtE+N1r3FpmUj7uJTG80eym2nQLvsROkMntalKJDo1SQVQhh9Nh4N9C88UezdMg8fjR5Q==" }, "nice-try": { "version": "1.0.5", @@ -9337,9 +10758,9 @@ } }, "node-sass": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", - "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz", + "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -9349,12 +10770,10 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "in-publish": "^2.0.0", - "lodash.assign": "^4.2.0", - "lodash.clonedeep": "^4.3.2", - "lodash.mergewith": "^4.6.0", + "lodash": "^4.17.11", "meow": "^3.7.0", "mkdirp": "^0.5.1", - "nan": "^2.10.0", + "nan": "^2.13.2", "node-gyp": "^3.8.0", "npmlog": "^4.0.0", "request": "^2.88.0", @@ -9382,6 +10801,28 @@ "supports-color": "^2.0.0" } }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -9400,15 +10841,26 @@ } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", + "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", + "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "normalize-path": { @@ -9598,13 +11050,9 @@ "dev": true }, "oidc-client": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.6.1.tgz", - "integrity": "sha512-buA9G0hlFjUwxoL/xuHunBtTgoICtJSojnZtATqMliUTKxPYAzHprOQ85Lj0hgF+Zv8lI/ViqaNFDG0Z5KCUKA==", - "requires": { - "babel-polyfill": ">=6.9.1", - "jsrsasign": "^8.0.12" - } + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.7.1.tgz", + "integrity": "sha512-qsPBQVa/BY6AmdY89erANJbfDXrX1dqu9lKgvYZzkVDzIj5mmw6wGjFeQuV2HDm4TiJA0VT5HSTWOWnXZUYu0g==" }, "on-finished": { "version": "2.3.0", @@ -9616,9 +11064,9 @@ } }, "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true }, "once": { @@ -9632,14 +11080,14 @@ }, "onetime": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, "opn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -9660,12 +11108,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true } } }, @@ -9691,6 +11133,14 @@ "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } } }, "original": { @@ -9715,12 +11165,14 @@ "dev": true }, "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "lcid": "^1.0.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "os-tmpdir": { @@ -9752,45 +11204,45 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { - "p-try": "^2.0.0" + "p-try": "^1.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^1.1.0" } }, "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true }, "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "pako": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", - "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, "parallel-transform": { @@ -9814,9 +11266,9 @@ } }, "parse-asn1": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", - "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { "asn1.js": "^4.0.0", @@ -9873,9 +11325,9 @@ } }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "pascalcase": { @@ -9897,13 +11349,10 @@ "dev": true }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -9936,14 +11385,12 @@ "dev": true }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "pify": "^2.0.0" } }, "pbkdf2": { @@ -10008,6 +11455,40 @@ "requires": { "locate-path": "^3.0.0" } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true } } }, @@ -10026,6 +11507,14 @@ "async": "^1.5.2", "debug": "^2.2.0", "mkdirp": "0.5.x" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } } }, "posix-character-classes": { @@ -10035,20 +11524,42 @@ "dev": true }, "postcss": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz", - "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -10525,16 +12036,33 @@ } }, "postcss-modules-local-by-default": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.3.tgz", - "integrity": "sha512-jv4CQ8IQ0+TkaAIP7H4kgu/jQbrjte8xU61SYJAIOby+o3H0MGWX6eN1WXUKHccK6/EEjcAERjyIP8MXzAWAbQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", "postcss-value-parser": "^3.3.1" }, "dependencies": { + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, "postcss-value-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", @@ -10544,13 +12072,32 @@ } }, "postcss-modules-scope": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.0.1.tgz", - "integrity": "sha512-7+6k9c3/AuZ5c596LJx9n923A/j3nF3ormewYBF1RrIQvjvjXe1xE8V8A1KFyFwXbvnshT6FBZFX0k/F1igneg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", + "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^7.0.6" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "dependencies": { + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } } }, "postcss-modules-values": { @@ -11014,1431 +12561,1931 @@ } } }, - "postcss-unique-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", + "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "dev": true + }, + "postinstall-build": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.1.tgz", + "integrity": "sha1-uRepB5smF42aJK9aXNjLSpkdEbk=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "progressbar.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/progressbar.js/-/progressbar.js-1.0.1.tgz", + "integrity": "sha1-9/v8GVJA/guzL2972y5/9ADqcfk=", + "requires": { + "shifty": "^1.5.2" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "proxy-addr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "requires": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" }, "dependencies": { - "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.5.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } } } }, - "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "postinstall-build": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.1.tgz", - "integrity": "sha1-uRepB5smF42aJK9aXNjLSpkdEbk=", + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "dev": true, "requires": { - "renderkid": "^2.0.1", - "utila": "~0.4" + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", "dev": true }, - "progressbar.js": { + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "raw-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-2.0.0.tgz", + "integrity": "sha512-kZnO5MoIyrojfrPWqrhFNLZemIAX8edMOCp++yC5RKxzFB3m92DqKNhKlU6+FvpOhWtvyh3jOaD7J6/9tpdIKg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + } + }, + "react": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz", + "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.13.6" + } + }, + "react-dom": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", + "integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.13.6" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + } + }, + "readline2": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/progressbar.js/-/progressbar.js-1.0.1.tgz", - "integrity": "sha1-9/v8GVJA/guzL2972y5/9ADqcfk=", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, "requires": { - "shifty": "^1.5.2" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" + "resolve": "^1.1.6" } }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", - "dev": true + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "is-equal-shallow": "^0.1.3" } }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", "dev": true, "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" } }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "renderkid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", + "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", + "dev": true, + "requires": { + "css-select": "^1.1.0", + "dom-converter": "~0.1", + "htmlparser2": "~3.3.0", + "strip-ansi": "^3.0.0", + "utila": "~0.3" + }, + "dependencies": { + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true + } + } }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "dev": true }, - "querystringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", - "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" }, "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true } } }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" } }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" + "path-parse": "^1.0.5" } }, - "raw-loader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-1.0.0.tgz", - "integrity": "sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==", + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } } }, - "react": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.7.0.tgz", - "integrity": "sha512-StCz3QY8lxTb5cl2HJxjwLFOXPIFQp+p+hxQfc8WE0QiLfCtIlKj8/+5tjjKm8uSTlAW+fCPaavGFS06V9Ar3A==", + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.12.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" } }, - "react-dom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.7.0.tgz", - "integrity": "sha512-D0Ufv1ExCAmF38P2Uh1lwpminZFRXEINJe53zRAbm4KPwSyd6DY/uDoS0Blj9jvPpn1+wivKpZYc8aAAN/nAkg==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.12.0" - } + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, - "read-pkg-up": { + "restore-cursor": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" } }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" - } + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true }, - "readline2": { + "rgb-regex": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true }, - "recast": { - "version": "0.11.23", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", - "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "rgba-regex": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "ast-types": "0.9.6", - "esprima": "~3.1.0", - "private": "~0.1.5", - "source-map": "~0.5.0" + "glob": "^7.1.3" }, "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } } } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "resolve": "^1.1.6" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "once": "^1.3.0" } }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3" + "aproba": "^1.1.1" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "rxjs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz", + "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==", "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "tslib": "^1.9.0" } }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "rxjs-tslint": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/rxjs-tslint/-/rxjs-tslint-0.1.7.tgz", + "integrity": "sha512-NnOfqutNfdT7VQnQm32JLYh2gDZjc0gdWZFtrxf/czNGkLKJ1nOO6jbKAFI09W0f9lCtv6P2ozxjbQH8TSPPFQ==", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "chalk": "^2.4.0", + "optimist": "^0.6.1", + "tslint": "^5.9.1", + "tsutils": "^2.25.0", + "typescript": ">=2.8.3" } }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "jsesc": "~0.5.0" + "ret": "~0.1.10" } }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "renderkid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", - "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", "dev": true, "requires": { - "css-select": "^1.1.0", - "dom-converter": "~0.1", - "htmlparser2": "~3.3.0", - "strip-ansi": "^3.0.0", - "utila": "~0.3" + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" }, "dependencies": { - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } } } }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "sass-lint": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sass-lint/-/sass-lint-1.13.1.tgz", + "integrity": "sha512-DSyah8/MyjzW2BWYmQWekYEKir44BpLqrCFsgs9iaWiVTcwZfwXHF586hh3D1n+/9ihUNMfd8iHAyb9KkGgs7Q==", "dev": true, "requires": { - "is-finite": "^1.0.0" + "commander": "^2.8.1", + "eslint": "^2.7.0", + "front-matter": "2.1.2", + "fs-extra": "^3.0.1", + "glob": "^7.0.0", + "globule": "^1.0.0", + "gonzales-pe-sl": "^4.2.3", + "js-yaml": "^3.5.4", + "known-css-properties": "^0.3.0", + "lodash.capitalize": "^4.1.0", + "lodash.kebabcase": "^4.0.0", + "merge": "^1.2.0", + "path-is-absolute": "^1.0.0", + "util": "^0.10.3" + }, + "dependencies": { + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } } }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "sass-loader": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", + "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", "dev": true, "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0", + "semver": "^5.5.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", "dev": true, "requires": { - "resolve-from": "^3.0.0" + "js-base64": "^2.1.8", + "source-map": "^0.4.2" }, "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } } } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", "dev": true }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "node-forge": "0.7.5" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rfdc": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, - "rgb-regex": { + "semver-dsl": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", - "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", - "dev": true - }, - "rgba-regex": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", - "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", "dev": true, - "optional": true, "requires": { - "align-text": "^0.1.1" + "semver": "^5.3.0" } }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, "requires": { - "glob": "^7.1.3" + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true } } }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "serialize-javascript": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } } }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "once": "^1.3.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" } }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "aproba": "^1.1.1" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "rxjs-tslint": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/rxjs-tslint/-/rxjs-tslint-0.1.6.tgz", - "integrity": "sha512-AxP+/o2NduL7bVijrAJztZXhVk9AFzEj/ouyROnIqLb9gnLp6YB11QzSvIrKbnq2Mb+mF294EsOuoyMiRnFtlA==", + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", "dev": true, "requires": { - "chalk": "^2.4.0", - "optimist": "^0.6.1", - "tslint": "^5.9.1", - "tsutils": "^2.25.0", - "typescript": "^2.8.3" + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" }, "dependencies": { - "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "ret": "~0.1.10" + "shebang-regex": "^1.0.0" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", "dev": true, "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - } - } + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" } }, - "sass-lint": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/sass-lint/-/sass-lint-1.12.1.tgz", - "integrity": "sha1-Yw9pwhaqIGuCMvsqqQe98zNrbYM=", + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", "dev": true, "requires": { - "commander": "^2.8.1", - "eslint": "^2.7.0", - "front-matter": "2.1.2", - "fs-extra": "^3.0.1", "glob": "^7.0.0", - "globule": "^1.0.0", - "gonzales-pe-sl": "^4.2.3", - "js-yaml": "^3.5.4", - "known-css-properties": "^0.3.0", - "lodash.capitalize": "^4.1.0", - "lodash.kebabcase": "^4.0.0", - "merge": "^1.2.0", - "path-is-absolute": "^1.0.0", - "util": "^0.10.3" + "interpret": "^1.0.0", + "rechoir": "^0.6.2" } }, - "sass-loader": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", - "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "shifty": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/shifty/-/shifty-1.5.4.tgz", + "integrity": "sha1-1DYvyRTdKA3fblIr5AiyEgMgg0Y=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "dev": true, "requires": { - "clone-deep": "^2.0.1", - "loader-utils": "^1.0.1", - "lodash.tail": "^4.1.1", - "neo-async": "^2.5.0", - "pify": "^3.0.0", - "semver": "^5.5.0" + "is-arrayish": "^0.3.1" }, "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "dev": true } } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, - "scheduler": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.12.0.tgz", - "integrity": "sha512-t7MBR28Akcp4Jm+QoR63XgAi9YgCUmgvDHqf5otgAj4QvdoBE4ImCX0ffehefePPG+aitiYHp0g/mW6s4Tp+dw==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "slugify": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.3.4.tgz", + "integrity": "sha512-KP0ZYk5hJNBS8/eIjGkFDCzGQIoZ1mnfQRYS5WM3273z+fxGWXeN0fkwf2ebEweydv9tioZIHGZKoF21U07/nw==" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selfsigned": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", - "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", - "dev": true, - "requires": { - "node-forge": "0.7.5" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - }, - "semver-dsl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", - "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "semver": "^5.3.0" + "kind-of": "^3.2.0" } }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" }, "dependencies": { - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } } } }, - "serialize-javascript": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", - "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", "dev": true }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "ms": "2.0.0" } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true } } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" } }, - "shallow-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", - "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "sockjs-client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", + "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", "dev": true, "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^5.0.0", - "mixin-object": "^2.0.1" + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "is-plain-obj": "^1.0.0" } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "sortablejs": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.9.0.tgz", + "integrity": "sha512-Ot6bYJ6PoqPmpsqQYXjn1+RKrY2NWQvQt/o4jfd/UYwVWndyO5EPO8YHbnm5HIykf8ENsm4JUrdAvolPT86yYA==" + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", "dev": true }, - "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, - "shelljs": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", - "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=", - "dev": true + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } }, - "shifty": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/shifty/-/shifty-1.5.4.tgz", - "integrity": "sha1-1DYvyRTdKA3fblIr5AiyEgMgg0Y=" + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "sourcemap-codec": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz", + "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==", "dev": true }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - } + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } }, - "slugify": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.3.4.tgz", - "integrity": "sha512-KP0ZYk5hJNBS8/eIjGkFDCzGQIoZ1mnfQRYS5WM3273z+fxGWXeN0fkwf2ebEweydv9tioZIHGZKoF21U07/nw==" + "spdx-license-ids": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "dev": true }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "spdy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "ms": "^2.1.1" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "ms": "^2.1.1" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "readable-stream": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "figgy-pudding": "^3.5.1" } }, - "socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "ms": "2.0.0" + "is-descriptor": "^0.1.0" } } } }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, - "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", "dev": true, "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "readable-stream": "^2.0.1" } }, - "socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, - "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", "dev": true, "requires": { - "faye-websocket": "^0.10.0", - "uuid": "^3.0.1" + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" } }, - "sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.4.tgz", + "integrity": "sha512-Wc2Gm5ygjSX8ZpW9J7Y9FwiSzTlKSvcl0FTTMd3rn7RoxDXpBW+xD9TY5sWL2n0UR61COB0LG1BQvN6nTUQbLQ==", + "dev": true, + "requires": { + "async": "^2.6.1", + "date-format": "^2.0.0", + "debug": "^3.1.0", + "fs-extra": "^7.0.0", + "lodash": "^4.17.10" }, "dependencies": { "debug": { @@ -12450,15 +14497,6 @@ "ms": "^2.1.1" } }, - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -12467,753 +14505,751 @@ } } }, - "sortablejs": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.8.1.tgz", - "integrity": "sha512-r0bKxZYGUFgv/6DQSWW8TVJBBtupUn6TPnDABd4rlqNq+u94ct5+barZmYauPAQNCKwy56C1kg9Y9msAN7UPag==" - }, - "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "safe-buffer": "~5.1.0" } }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "ansi-regex": "^2.0.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, - "sourcemap-codec": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz", - "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==", + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "get-stdin": "^4.0.1" } }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", "dev": true }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" } }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "spdy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", - "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", + "stylehacks": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.1.tgz", + "integrity": "sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w==", "dev": true, "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "postcss": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", + "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", "dev": true, "requires": { - "ms": "^2.1.1" + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.5.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", "dev": true, "requires": { - "ms": "^2.1.1" + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "readable-stream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", - "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "has-flag": "^3.0.0" } } } }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "minimist": "^1.1.0" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "has-flag": "^3.0.0" } }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "svgo": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz", + "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", "dev": true, "requires": { - "figgy-pudding": "^3.5.1" + "coa": "~2.0.1", + "colors": "~1.1.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "~0.1.0", + "css-tree": "1.0.0-alpha.28", + "css-url-regex": "^1.1.0", + "csso": "^3.5.0", + "js-yaml": "^3.12.0", + "mkdirp": "~0.5.1", + "object.values": "^1.0.4", + "sax": "~1.2.4", + "stable": "~0.1.6", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "css-select": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", + "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^2.1.2", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz", + "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + } } }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "terser": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true } } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "terser-webpack-plugin": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", + "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "cacache": "^11.0.2", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "terser": "^3.16.1", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "setimmediate": "^1.0.4" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "os-tmpdir": "~1.0.2" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, - "strip-indent": { + "to-arraybuffer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "kind-of": "^3.0.2" } }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - }, - "style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, - "stylehacks": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.1.tgz", - "integrity": "sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w==", + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" }, "dependencies": { - "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.5.0" - } - }, - "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", - "dev": true, - "requires": { - "dot-prop": "^4.1.1", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "has-flag": "^3.0.0" + "kind-of": "^3.0.2" } } } }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { - "minimist": "^1.1.0" + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "glob": "^7.1.2" } }, - "svgo": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz", - "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", + "ts-loader": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.4.tgz", + "integrity": "sha512-haLwWMts/tCruBFbLUWOR9hZezZ89TMW3EntrAEtYARDnPZSQt6dPA5tN3fvlsmUIYXVWDHO5SUhw8ndAomVlw==", "dev": true, "requires": { - "coa": "~2.0.1", - "colors": "~1.1.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "~0.1.0", - "css-tree": "1.0.0-alpha.28", - "css-url-regex": "^1.1.0", - "csso": "^3.5.0", - "js-yaml": "^3.12.0", - "mkdirp": "~0.5.1", - "object.values": "^1.0.4", - "sax": "~1.2.4", - "stable": "~0.1.6", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^3.1.4", + "semver": "^5.0.1" }, "dependencies": { - "colors": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, - "css-select": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", - "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^2.1.2", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "css-what": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz", - "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==", + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "requires": { - "boolbase": "~1.0.0" - } - } - } - }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "is-extendable": "^0.1.0" } } } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } - }, - "terser": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.14.1.tgz", - "integrity": "sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw==", - "dev": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1", - "source-map-support": "~0.5.6" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz", - "integrity": "sha512-GGSt+gbT0oKcMDmPx4SRSfJPE1XaN3kQRWG4ghxKQw9cn5G9x6aCKSsgYdvyM0na9NJ4Drv0RG6jbBByZ5CMjw==", - "dev": true, - "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.8.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", - "dev": true - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -13221,61 +15257,54 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } - } - } - }, - "toposort": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", - "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } } } }, - "tree-kill": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", - "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", - "dev": true - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - } - }, "tsconfig-paths": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.5.0.tgz", @@ -13323,29 +15352,42 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tslint": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", - "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz", + "integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==", "dev": true, "requires": { - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", "builtin-modules": "^1.1.1", "chalk": "^2.3.0", "commander": "^2.12.1", "diff": "^3.2.0", "glob": "^7.1.1", - "js-yaml": "^3.7.0", + "js-yaml": "^3.13.0", "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", "resolve": "^1.3.2", "semver": "^5.3.0", "tslib": "^1.8.0", - "tsutils": "^2.27.2" + "tsutils": "^2.29.0" + }, + "dependencies": { + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } } }, "tslint-webpack-plugin": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tslint-webpack-plugin/-/tslint-webpack-plugin-2.0.2.tgz", - "integrity": "sha512-FpwMuFHzW3ylsgt0q7sApKFb486wl25drHoIV3PXrNGRQal5veUd8l8S3eMv/I1Qv+1xel2BkYGd3upyQJUfYg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/tslint-webpack-plugin/-/tslint-webpack-plugin-2.0.4.tgz", + "integrity": "sha512-fAPLOV1g/lxEOuObNZrAeL3eGWW4Ey7wmIUV1LCOCCUfijRH1KfvcynNh6JCABM44b23N7AeniM3+ncvRVa4JQ==", "dev": true, "requires": { "chalk": "^2.1.0" @@ -13391,13 +15433,13 @@ } }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "~2.1.24" } }, "typedarray": { @@ -13432,9 +15474,9 @@ "dev": true }, "uc.micro": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", - "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "uglify-js": { "version": "3.4.7", @@ -13446,17 +15488,10 @@ "source-map": "~0.6.1" } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, "uglifyjs-webpack-plugin": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.1.1.tgz", - "integrity": "sha512-TQEcyMNkObX/H+FfcKjiDgs5RcXX8vW2UUUrDTOfQgg3lrafztfeM5WAwXo+AzqozJK6NP9w98xNpG/dutzSsg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.1.2.tgz", + "integrity": "sha512-G1fJx2uOAAfvdZ77SVCzmFo6mv8uKaHoZBL9Qq/ciC8r6p0ANOL1uY85fIUiyWXKw5RzAaJYZfNSL58Or2hQ0A==", "dev": true, "requires": { "cacache": "^11.2.0", @@ -13611,9 +15646,9 @@ } }, "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", "dev": true }, "upper-case": { @@ -13662,12 +15697,12 @@ "dev": true }, "url-parse": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", - "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", "dev": true, "requires": { - "querystringify": "^2.0.0", + "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, @@ -13812,37 +15847,219 @@ "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", "to-regex": "^3.0.1" }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, "dependencies": { "extend-shallow": { "version": "2.0.1", @@ -13850,180 +16067,556 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", + "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-descriptor": "^0.1.0" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "npmlog": { + "version": "4.1.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "wrappy": "1" } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, "dev": true, + "optional": true, "requires": { - "kind-of": "^3.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "minimist": { + "version": "1.2.0", + "bundled": true, "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "optional": true } } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "readable-stream": { + "version": "2.3.6", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "rimraf": { + "version": "2.6.3", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-descriptor": "^1.0.0" + "glob": "^7.1.3" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true } } }, @@ -14084,9 +16677,9 @@ "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -14144,6 +16737,30 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } } } }, @@ -14157,15 +16774,15 @@ } }, "webpack": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.0.tgz", - "integrity": "sha512-pxdGG0keDBtamE1mNvT5zyBdx+7wkh6mh7uzMOo/uRQ/fhsdj5FXkh/j5mapzs060forql1oXqXN9HJGju+y7w==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.30.0.tgz", + "integrity": "sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/wasm-edit": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", "acorn": "^6.0.5", "acorn-dynamic-import": "^4.0.0", "ajv": "^6.1.0", @@ -14181,7 +16798,7 @@ "mkdirp": "~0.5.0", "neo-async": "^2.5.0", "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", + "schema-utils": "^1.0.0", "tapable": "^1.1.0", "terser-webpack-plugin": "^1.1.0", "watchpack": "^1.5.0", @@ -14189,9 +16806,9 @@ }, "dependencies": { "acorn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz", - "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, "arr-diff": { @@ -14468,20 +17085,10 @@ "to-regex": "^3.0.2" } }, - "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - } - }, "tapable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", - "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, "webpack-sources": { @@ -14497,9 +17104,9 @@ } }, "webpack-cli": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.2.1.tgz", - "integrity": "sha512-jeJveHwz/vwpJ3B8bxEL5a/rVKIpRNJDsKggfKnxuYeohNDW4Y/wB9N/XHJA093qZyS0r6mYL+/crLsIol4WKA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.1.tgz", + "integrity": "sha512-c2inFU7SM0IttEgF7fK6AaUsbBnORRzminvbyRKS+NlbQHVZdCtzKBlavRL5359bFsywXGRAItA5di/IruC8mg==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -14507,14 +17114,261 @@ "enhanced-resolve": "^4.1.0", "findup-sync": "^2.0.0", "global-modules": "^1.0.0", - "global-modules-path": "^2.3.0", "import-local": "^2.0.0", "interpret": "^1.1.0", - "lightercollective": "^0.1.0", "loader-utils": "^1.1.0", "supports-color": "^5.5.0", "v8-compile-cache": "^2.0.2", - "yargs": "^12.0.4" + "yargs": "^12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", + "dev": true, + "requires": { + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" + } + }, + "webpack-dev-server": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.3.1.tgz", + "integrity": "sha512-jY09LikOyGZrxVTXK0mgIq9y2IhCoJ05848dKZqX1gAGLU1YDqgpOT71+W53JH/wI4v6ky4hm+KvSyW14JEs5A==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.5", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.0", + "express": "^4.16.4", + "html-entities": "^1.2.1", + "http-proxy-middleware": "^0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.2.0", + "ip": "^1.1.5", + "killable": "^1.0.1", + "loglevel": "^1.6.1", + "opn": "^5.5.0", + "portfinder": "^1.0.20", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.4", + "semver": "^6.0.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.3.0", + "spdy": "^4.0.0", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.6.2", + "webpack-log": "^2.0.0", + "yargs": "12.0.5" }, "dependencies": { "ansi-regex": { @@ -14523,12 +17377,94 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -14538,6 +17474,17 @@ "string-width": "^2.1.1", "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "cross-spawn": { @@ -14551,6 +17498,31 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } } }, "execa": { @@ -14568,219 +17540,153 @@ "strip-eof": "^1.0.0" } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } - } - } - }, - "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", - "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" - } - }, - "webpack-dev-server": { - "version": "3.1.14", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz", - "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.0.0", - "compression": "^1.5.2", - "connect-history-api-fallback": "^1.3.0", - "debug": "^3.1.0", - "del": "^3.0.0", - "express": "^4.16.2", - "html-entities": "^1.2.0", - "http-proxy-middleware": "~0.18.0", - "import-local": "^2.0.0", - "internal-ip": "^3.0.1", - "ip": "^1.1.5", - "killable": "^1.0.0", - "loglevel": "^1.4.1", - "opn": "^5.1.0", - "portfinder": "^1.0.9", - "schema-utils": "^1.0.0", - "selfsigned": "^1.9.1", - "semver": "^5.6.0", - "serve-index": "^1.7.2", - "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^5.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "3.4.0", - "webpack-log": "^2.0.0", - "yargs": "12.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "arr-diff": { + "fill-range": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -14789,297 +17695,568 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", + "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" } - } - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, "dev": true, + "optional": true, "requires": { - "ansi-regex": "^3.0.0" + "brace-expansion": "^1.1.7" } - } - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - }, - "dependencies": { + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, "ms": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "ms": "2.0.0" + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-descriptor": "^0.1.0" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "nopt": { + "version": "4.0.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "abbrev": "1", + "osenv": "^0.1.4" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "npm-bundled": { + "version": "1.0.6", + "bundled": true, "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "kind-of": "^3.0.2" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "minimist": { + "version": "1.2.0", + "bundled": true, "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "optional": true } } }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "string_decoder": { + "version": "1.1.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "safe-buffer": "~5.1.0" } }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "strip-ansi": { + "version": "3.0.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-descriptor": "^1.0.0" + "ansi-regex": "^2.0.0" } }, - "extend-shallow": { + "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extendable": "^0.1.0" + "string-width": "^1.0.2 || 2" } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true } } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -15110,27 +18287,6 @@ } } }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -15172,16 +18328,10 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -15228,6 +18378,27 @@ "invert-kv": "^2.0.0" } }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -15249,6 +18420,25 @@ "to-regex": "^3.0.2" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "os-locale": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", @@ -15260,46 +18450,63 @@ "mem": "^4.0.0" } }, - "pify": { + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", "dev": true }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "has-flag": "^3.0.0" } }, "webpack-dev-middleware": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz", - "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz", + "integrity": "sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg==", "dev": true, "requires": { - "memory-fs": "~0.4.1", + "memory-fs": "^0.4.1", "mime": "^2.3.1", "range-parser": "^1.0.3", "webpack-log": "^2.0.0" @@ -15315,20 +18522,14 @@ "uuid": "^3.3.2" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^2.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^1.0.1", "os-locale": "^3.0.0", @@ -15338,16 +18539,17 @@ "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" + "yargs-parser": "^11.1.1" } }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -15414,9 +18616,9 @@ } }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "wide-align": { @@ -15428,17 +18630,10 @@ "string-width": "^1.0.2 || 2" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, "worker-farm": { @@ -15458,6 +18653,19 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "wrappy": { @@ -15503,12 +18711,6 @@ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -15528,33 +18730,33 @@ "dev": true }, "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" } }, "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "dev": true, "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } + "camelcase": "^4.1.0" } }, "yeast": { @@ -15564,9 +18766,9 @@ "dev": true }, "zone.js": { - "version": "0.8.29", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz", - "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.9.0.tgz", + "integrity": "sha512-EfygvVnLxPSCMSgJ4h7SoY+XNr7ybdwvvwEQ70lvMFl9coNnciXSyWi8Kg6znK1ubyUSffkCKvleSQpLuUKw0Q==" } } } diff --git a/src/Squidex/package.json b/src/Squidex/package.json index ba12d0ca3..cb7a6c5f8 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -15,91 +15,92 @@ "build:clean": "rimraf wwwroot/build" }, "dependencies": { - "@angular/animations": "7.2.3", - "@angular/common": "7.2.3", - "@angular/core": "7.2.3", - "@angular/forms": "7.2.3", - "@angular/http": "7.2.3", - "@angular/platform-browser": "7.2.3", - "@angular/platform-browser-dynamic": "7.2.3", - "@angular/platform-server": "7.2.3", - "@angular/router": "7.2.3", + "@angular/animations": "7.2.14", + "@angular/common": "7.2.14", + "@angular/core": "7.2.14", + "@angular/forms": "7.2.14", + "@angular/http": "7.2.14", + "@angular/platform-browser": "7.2.14", + "@angular/platform-browser-dynamic": "7.2.14", + "@angular/platform-server": "7.2.14", + "@angular/router": "7.2.14", "angular2-chartjs": "0.5.1", "babel-polyfill": "6.26.0", - "bootstrap": "4.2.1", + "bootstrap": "4.3.1", "core-js": "2.6.3", - "graphiql": "0.12.0", - "graphql": "14.1.1", - "marked": "0.6.0", + "graphiql": "0.13.0", + "graphql": "14.2.1", + "marked": "0.6.2", "moment": "2.24.0", - "mousetrap": "1.6.2", + "mousetrap": "1.6.3", "ng2-dnd": "5.0.2", - "ngx-color-picker": "7.3.0", - "oidc-client": "1.6.1", + "ngx-color-picker": "7.5.0", + "oidc-client": "1.7.1", "pikaday": "1.8.0", "progressbar.js": "1.0.1", - "react": "16.7.0", - "react-dom": "16.7.0", - "rxjs": "6.3.3", + "react": "16.8.6", + "react-dom": "16.8.6", + "rxjs": "6.5.1", "slugify": "1.3.4", - "sortablejs": "1.8.1", + "sortablejs": "1.9.0", "tslib": "1.9.3", - "zone.js": "0.8.29" + "zone.js": "0.9.0" }, "devDependencies": { - "@angular/compiler": "7.2.3", - "@angular/compiler-cli": "7.2.3", - "@ngtools/webpack": "7.3.0", + "@angular/compiler": "7.2.14", + "@angular/compiler-cli": "7.2.14", + "@ngtools/webpack": "7.3.8", "@types/core-js": "2.5.0", - "@types/jasmine": "3.3.8", - "@types/marked": "0.6.0", + "@types/jasmine": "3.3.12", + "@types/marked": "0.6.5", "@types/mousetrap": "1.6", - "@types/node": "10.12.21", - "@types/react": "16.8.1", - "@types/react-dom": "16.0.11", + "@types/node": "11.13.8", + "@types/react": "16.8.14", + "@types/react-dom": "16.8.4", "@types/sortablejs": "1.7.2", "angular-router-loader": "0.8.5", "angular2-template-loader": "0.6.2", "awesome-typescript-loader": "5.2.1", "babel-core": "6.26.3", - "codelyzer": "4.5.0", + "codelyzer": "5.0.1", "cpx": "1.5.0", - "css-loader": "2.1.0", + "css-loader": "2.1.1", "file-loader": "3.0.1", "html-loader": "0.5.5", "html-webpack-plugin": "3.2.0", "ignore-loader": "0.1.2", "istanbul-instrumenter-loader": "3.0.1", - "jasmine-core": "3.3.0", - "karma": "4.0.0", + "jasmine-core": "3.4.0", + "karma": "4.1.0", "karma-chrome-launcher": "2.2.0", "karma-cli": "2.0.0", - "karma-coverage-istanbul-reporter": "2.0.4", + "karma-coverage-istanbul-reporter": "2.0.5", "karma-htmlfile-reporter": "0.3.8", "karma-jasmine": "2.0.1", - "karma-jasmine-html-reporter": "1.4.0", + "karma-jasmine-html-reporter": "1.4.2", "karma-mocha-reporter": "2.2.5", "karma-sourcemap-loader": "0.3.7", "karma-webpack": "3.0.5", - "mini-css-extract-plugin": "0.5.0", - "node-sass": "4.11.0", + "mini-css-extract-plugin": "0.6.0", + "node-sass": "4.12.0", "optimize-css-assets-webpack-plugin": "5.0.1", - "raw-loader": "1.0.0", + "raw-loader": "2.0.0", "rimraf": "2.6.3", - "rxjs-tslint": "0.1.6", - "sass-lint": "1.12.1", + "rxjs-tslint": "0.1.7", + "sass-lint": "1.13.1", "sass-loader": "7.1.0", "style-loader": "0.23.1", + "ts-loader": "^5.4.4", "tsconfig-paths-webpack-plugin": "3.2.0", - "tslint": "5.12.1", - "tslint-webpack-plugin": "2.0.2", + "tslint": "5.16.0", + "tslint-webpack-plugin": "2.0.4", "typemoq": "2.1.0", "typescript": "3.2.4", - "uglifyjs-webpack-plugin": "2.1.1", + "uglifyjs-webpack-plugin": "2.1.2", "underscore": "1.9.1", - "webpack": "4.29.0", - "webpack-cli": "3.2.1", - "webpack-dev-server": "3.1.14", + "webpack": "4.30.0", + "webpack-cli": "3.3.1", + "webpack-dev-server": "3.3.1", "webpack-merge": "4.2.1" } } diff --git a/src/Squidex/tsconfig.json b/src/Squidex/tsconfig.json index 16e9320a9..9bb19bd05 100644 --- a/src/Squidex/tsconfig.json +++ b/src/Squidex/tsconfig.json @@ -21,8 +21,12 @@ ] } }, + "awesomeTypescriptLoaderOptions": { + "useBabel": true, + "useCache": true, + "emitRequireType": false + }, "angularCompilerOptions": { - "fullTemplateTypeCheck": true, - "strictInjectionParameters": true + "fullTemplateTypeCheck": true } } \ No newline at end of file From 4b99c96fa77fb3eac71905c17eb95cc333f6c313 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 28 Apr 2019 19:29:45 +0200 Subject: [PATCH 11/20] Using uploader --- .../app/framework/utils/rxjs-extensions.ts | 14 +- .../components/asset-uploader.component.html | 2 +- .../components/asset-uploader.component.ts | 17 +- .../app/shared/components/asset.component.ts | 14 +- .../components/markdown-editor.component.ts | 11 +- .../components/rich-editor.component.ts | 23 +-- src/Squidex/app/shared/internal.ts | 1 + src/Squidex/app/shared/module.ts | 6 + .../app/shared/state/asset-uploader.state.ts | 181 ++++++++++++++++++ .../app/shared/state/assets.state.spec.ts | 180 +++++++++-------- .../app/shared/state/clients.state.spec.ts | 21 +- .../app/shared/state/contents.state.ts | 3 +- .../app/shared/state/contributors.state.ts | 12 +- 13 files changed, 348 insertions(+), 137 deletions(-) create mode 100644 src/Squidex/app/shared/state/asset-uploader.state.ts diff --git a/src/Squidex/app/framework/utils/rxjs-extensions.ts b/src/Squidex/app/framework/utils/rxjs-extensions.ts index 4e54b9f2c..b93664ec6 100644 --- a/src/Squidex/app/framework/utils/rxjs-extensions.ts +++ b/src/Squidex/app/framework/utils/rxjs-extensions.ts @@ -7,8 +7,8 @@ // tslint:disable: only-arrow-functions -import { Observable, throwError } from 'rxjs'; -import { catchError, map, onErrorResumeNext, shareReplay, switchMap } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { map, onErrorResumeNext, shareReplay, switchMap } from 'rxjs/operators'; import { DialogService } from './../services/dialog.service'; @@ -26,16 +26,6 @@ export function mapVersioned(project: (value: T, version: Vers }; } -export function notify(dialogs: DialogService) { - return function mapOperation(source: Observable) { - return source.pipe(catchError(error => { - dialogs.notifyError(error); - - return throwError(error); - })); - }; -} - type Options = { silent?: boolean, project?: ((value: T) => R) }; export function shareSubscribed(dialogs: DialogService, options?: Options) { diff --git a/src/Squidex/app/shared/components/asset-uploader.component.html b/src/Squidex/app/shared/components/asset-uploader.component.html index 11d8cd704..abb338d95 100644 --- a/src/Squidex/app/shared/components/asset-uploader.component.html +++ b/src/Squidex/app/shared/components/asset-uploader.component.html @@ -1,4 +1,4 @@ -
-
- - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset-uploader.component.ts b/src/Squidex/app/shared/components/asset-uploader.component.ts index df6b81565..7160ba9e0 100644 --- a/src/Squidex/app/shared/components/asset-uploader.component.ts +++ b/src/Squidex/app/shared/components/asset-uploader.component.ts @@ -8,6 +8,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { + AppsState, AssetsState, AssetUploaderState, DialogModel, @@ -25,9 +26,10 @@ import { changeDetection: ChangeDetectionStrategy.OnPush }) export class AssetUploaderComponent { - public modalMenu = new DialogModel(true); + public modalMenu = new DialogModel(); constructor( + public readonly appsState: AppsState, public readonly assetUploader: AssetUploaderState, public readonly assetsState: AssetsState ) { diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 2f6d989ce..253d111a8 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -15,7 +15,7 @@ import { StatefulComponent, Types } from '@app/shared/internal'; -import { AssetUploaderState } from '../state/asset-uploader.state'; +import { AssetUploaderState, UploadCanceled } from '../state/asset-uploader.state'; interface State { progress: number; @@ -101,7 +101,9 @@ export class AssetComponent extends StatefulComponent implements OnInit { this.emitLoad(dto); } }, error => { - this.dialogs.notifyError(error); + if (!Types.is(error, UploadCanceled)) { + this.dialogs.notifyError(error); + } this.emitLoadError(error); }); diff --git a/src/Squidex/app/shared/components/markdown-editor.component.ts b/src/Squidex/app/shared/components/markdown-editor.component.ts index 86400b285..237f33a6c 100644 --- a/src/Squidex/app/shared/components/markdown-editor.component.ts +++ b/src/Squidex/app/shared/components/markdown-editor.component.ts @@ -10,12 +10,13 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { AssetDto, + AssetUploaderState, DialogModel, ResourceLoaderService, StatefulControlComponent, - Types + Types, + UploadCanceled } from '@app/shared/internal'; -import { AssetUploaderState } from '../state/asset-uploader.state'; declare var SimpleMDE: any; @@ -245,8 +246,10 @@ export class MarkdownEditorComponent extends StatefulControlComponent { - replaceText('FAILED'); + }, error => { + if (!Types.is(error, UploadCanceled)) { + replaceText('FAILED'); + } }); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/components/rich-editor.component.ts b/src/Squidex/app/shared/components/rich-editor.component.ts index 8612dd002..1f9ea859d 100644 --- a/src/Squidex/app/shared/components/rich-editor.component.ts +++ b/src/Squidex/app/shared/components/rich-editor.component.ts @@ -12,12 +12,13 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { AssetDto, + AssetUploaderState, DialogModel, ResourceLoaderService, StatefulControlComponent, - Types + Types, + UploadCanceled } from '@app/shared/internal'; -import { AssetUploaderState } from '../state/asset-uploader.state'; declare var tinymce: any; @@ -99,8 +100,10 @@ export class RichEditorComponent extends StatefulControlComponent i if (Types.is(asset, AssetDto)) { success(asset.url); } - }, () => { - failed(); + }, error => { + if (!Types.is(error, UploadCanceled)) { + failed(); + } }); }, @@ -215,8 +218,10 @@ export class RichEditorComponent extends StatefulControlComponent i if (Types.is(asset, AssetDto)) { replaceText(`${asset.fileName}`); } - }, () => { - replaceText('FAILED'); + }, error => { + if (!Types.is(error, UploadCanceled)) { + replaceText('FAILED'); + } }); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/state/apps.state.ts b/src/Squidex/app/shared/state/apps.state.ts index 451ded8b3..2a97377cd 100644 --- a/src/Squidex/app/shared/state/apps.state.ts +++ b/src/Squidex/app/shared/state/apps.state.ts @@ -69,9 +69,9 @@ export class AppsState extends State { public load(): Observable { return this.appsService.getApps().pipe( - tap((dto: AppDto[]) => { + tap(payload => { this.next(s => { - const apps = ImmutableArray.of(dto); + const apps = ImmutableArray.of(payload); return { ...s, apps }; }); @@ -81,9 +81,9 @@ export class AppsState extends State { public create(request: CreateAppDto): Observable { return this.appsService.postApp(request).pipe( - tap(dto => { + tap(payload => { this.next(s => { - const apps = s.apps.push(dto).sortByStringAsc(x => x.name); + const apps = s.apps.push(payload).sortByStringAsc(x => x.name); return { ...s, apps }; }); diff --git a/src/Squidex/app/shared/state/asset-uploader.state.ts b/src/Squidex/app/shared/state/asset-uploader.state.ts index 4d2dece60..58c8ac741 100644 --- a/src/Squidex/app/shared/state/asset-uploader.state.ts +++ b/src/Squidex/app/shared/state/asset-uploader.state.ts @@ -6,8 +6,8 @@ */ import { Injectable } from '@angular/core'; -import { Observable, ReplaySubject, Subject, Subscription } from 'rxjs'; -import { distinctUntilChanged, map, shareReplay } from 'rxjs/operators'; +import { Observable, Subject } from 'rxjs'; +import { distinctUntilChanged, map, publishReplay, refCount, takeUntil } from 'rxjs/operators'; import { DateTime, @@ -31,10 +31,7 @@ export interface Upload { name: string; // The upload subscription. - subscription?: Subscription; - - // The subject to notify subscribers. - subject: ReplaySubject; + cancel: Subject; // The progress. progress: number; @@ -48,6 +45,8 @@ interface Snapshot { uploads: UploadList; } +export class UploadCanceled { } + type UploadList = ImmutableArray; type UploadResult = AssetDto | number; @@ -67,10 +66,7 @@ export class AssetUploaderState extends State { } public stopUpload(upload: Upload) { - if (upload.subscription) { - upload.subscription.unsubscribe(); - upload.subject.complete(); - } + upload.cancel.error(new UploadCanceled()); this.next(s => { const uploads = s.uploads.removeBy('id', upload); @@ -82,55 +78,49 @@ export class AssetUploaderState extends State { public uploadFile(file: File, target?: AssetsState, now?: DateTime): Observable { const stream = this.assetsService.uploadFile(this.appName, file, this.user, now || DateTime.now()); - return this.upload(stream, MathHelper.guid(), file, (asset, subject) => { + return this.upload(stream, MathHelper.guid(), file, asset => { if (asset.isDuplicate) { this.dialogs.notifyError('Asset has already been uploaded.'); } else if (target) { target.add(asset); } - subject.next(asset); + return asset; }); } public uploadAsset(asset: AssetDto, file: File, now?: DateTime): Observable { const stream = this.assetsService.replaceFile(this.appName, asset.id, file, asset.version); - return this.upload(stream, asset.id, file, ({ version, payload }, subject) => { - subject.next(asset.update(payload, this.user, version, now)); - }); + return this.upload(stream, asset.id, file, ({ version, payload }) => asset.update(payload, this.user, version, now)); } - private upload(stream: Observable, id: string, file: File, complete: (completion: R, subject: Subject) => void) { - const subject = new ReplaySubject(); - - let upload = { id, name: file.name, progress: 1, status: 'Running', subject }; + private upload(source: Observable, id: string, file: File, complete: ((completion: T) => AssetDto)) { + let upload = { id, name: file.name, progress: 1, status: 'Running', cancel: new Subject() }; this.addUpload(upload); - const subscription = stream.subscribe(event => { + const stream = source.pipe(takeUntil(upload.cancel), + map(event => { + if (Types.isNumber(event)) { + return event; + } else { + return complete(event); + } + }), + publishReplay(), refCount()); + + stream.subscribe(event => { if (Types.isNumber(event)) { upload = this.update(upload, { progress: event }); - - subject.next(event); - } else { - complete(event, subject); } - }, error => { - subject.error(error); - + }, () => { upload = this.remove(upload, { status: 'Failed' }); }, () => { - if (!subject.isStopped) { - subject.complete(); - } - upload = this.remove(upload, { status: 'Completed', progress: 100 }); }); - upload = this.update(upload, { subscription }); - - return subject.pipe(shareReplay()); + return stream; } private remove(upload: Upload, update: Partial) { diff --git a/src/Squidex/app/shared/state/assets.state.ts b/src/Squidex/app/shared/state/assets.state.ts index 3beab3093..66d726c6b 100644 --- a/src/Squidex/app/shared/state/assets.state.ts +++ b/src/Squidex/app/shared/state/assets.state.ts @@ -95,16 +95,16 @@ export class AssetsState extends State { Object.keys(this.snapshot.tagsSelected)), this.assetsService.getTags(this.appName) ).pipe( - tap(dtos => { + tap(([ { items, total }, tags ]) => { if (isReload) { this.dialogs.notifyInfo('Assets reloaded.'); } this.next(s => { - const assets = ImmutableArray.of(dtos[0].items); - const assetsPager = s.assetsPager.setCount(dtos[0].total); + const assets = ImmutableArray.of(items); + const assetsPager = s.assetsPager.setCount(total); - return { ...s, assets, assetsPager, isLoaded: true, tags: dtos[1] }; + return { ...s, assets, assetsPager, isLoaded: true, tags }; }); }), shareSubscribed(this.dialogs)); diff --git a/src/Squidex/app/shared/state/contents.state.ts b/src/Squidex/app/shared/state/contents.state.ts index 8f0461f10..787c27962 100644 --- a/src/Squidex/app/shared/state/contents.state.ts +++ b/src/Squidex/app/shared/state/contents.state.ts @@ -14,6 +14,7 @@ import { DialogService, ErrorDto, ImmutableArray, + mapVersioned, Pager, shareSubscribed, State, @@ -118,20 +119,24 @@ export abstract class ContentsStateBase extends State { return this.loadInternal(isReload); } - private loadInternal(isReload = false): Observable { + private loadInternal(isReload = false) { + return this.loadInternalCore(isReload).pipe(shareSubscribed(this.dialogs)); + } + + private loadInternalCore(isReload = false) { return this.contentsService.getContents(this.appName, this.schemaName, this.snapshot.contentsPager.pageSize, this.snapshot.contentsPager.skip, this.snapshot.contentsQuery, undefined, this.snapshot.isArchive).pipe( - tap(dtos => { + tap(({ total, items }) => { if (isReload) { this.dialogs.notifyInfo('Contents reloaded.'); } return this.next(s => { - const contents = ImmutableArray.of(dtos.items); - const contentsPager = s.contentsPager.setCount(dtos.total); + const contents = ImmutableArray.of(items); + const contentsPager = s.contentsPager.setCount(total); let selectedContent = s.selectedContent; @@ -141,17 +146,16 @@ export abstract class ContentsStateBase extends State { return { ...s, contents, contentsPager, selectedContent, isLoaded: true }; }); - }), - shareSubscribed(this.dialogs)); + })); } public create(request: any, publish: boolean): Observable { return this.contentsService.postContent(this.appName, this.schemaName, request, publish).pipe( - tap(dto => { + tap(payload => { this.dialogs.notifyInfo('Contents created successfully.'); return this.next(s => { - const contents = s.contents.pushFront(dto); + const contents = s.contents.pushFront(payload); const contentsPager = s.contentsPager.incrementCount(); return { ...s, contents, contentsPager }; @@ -174,7 +178,8 @@ export abstract class ContentsStateBase extends State { return of(error); }), - switchMap(() => this.loadInternal())); + switchMap(() => this.loadInternalCore()), + shareSubscribed(this.dialogs, { silent: true })); } public deleteMany(contents: ContentDto[]): Observable { @@ -191,92 +196,97 @@ export abstract class ContentsStateBase extends State { return of(error); }), - switchMap(() => this.loadInternal())); + switchMap(() => this.loadInternal()), + shareSubscribed(this.dialogs, { silent: true })); } - public publishChanges(content: ContentDto, dueTime: string | null, now?: DateTime): Observable { + public publishChanges(content: ContentDto, dueTime: string | null, now?: DateTime): Observable { return this.contentsService.changeContentStatus(this.appName, this.schemaName, content.id, 'Publish', dueTime, content.version).pipe( - tap(dto => { - this.dialogs.notifyInfo('Content updated successfully.'); - + mapVersioned(({ version }) => { if (dueTime) { - this.replaceContent(changeScheduleStatus(content, 'Published', dueTime, this.user, dto.version, now)); + return changeScheduleStatus(content, 'Published', dueTime, this.user, version, now); } else { - this.replaceContent(confirmChanges(content, this.user, dto.version, now)); + return confirmChanges(content, this.user, version, now); } }), + tap(({ payload }) => { + this.dialogs.notifyInfo('Content updated successfully.'); + + this.replaceContent(payload); + }), shareSubscribed(this.dialogs)); } - public changeStatus(content: ContentDto, action: string, status: string, dueTime: string | null, now?: DateTime): Observable { + public changeStatus(content: ContentDto, action: string, status: string, dueTime: string | null, now?: DateTime): Observable { return this.contentsService.changeContentStatus(this.appName, this.schemaName, content.id, action, dueTime, content.version).pipe( - tap(dto => { - this.dialogs.notifyInfo('Content updated successfully.'); - + mapVersioned(({ version }) => { if (dueTime) { - this.replaceContent(changeScheduleStatus(content, status, dueTime, this.user, dto.version, now)); + return changeScheduleStatus(content, status, dueTime, this.user, version, now); } else { - this.replaceContent(changeStatus(content, status, this.user, dto.version, now)); + return changeStatus(content, status, this.user, version, now); } }), + tap(({ payload }) => { + this.dialogs.notifyInfo('Content updated successfully.'); + + this.replaceContent(payload); + }), shareSubscribed(this.dialogs)); } - public update(content: ContentDto, request: any, now?: DateTime): Observable { + public update(content: ContentDto, request: any, now?: DateTime): Observable { return this.contentsService.putContent(this.appName, this.schemaName, content.id, request, false, content.version).pipe( - tap(dto => { + mapVersioned((payload, version) => updateData(content, payload, this.user, version, now)), + tap(({ payload }) => { this.dialogs.notifyInfo('Content updated successfully.'); - if (dto.version.value !== content.version.value) { - this.replaceContent(updateData(content, dto.payload, this.user, dto.version, now)); - } + this.replaceContent(payload, content.version); }), shareSubscribed(this.dialogs)); } - public proposeUpdate(content: ContentDto, request: any, now?: DateTime): Observable { + public proposeUpdate(content: ContentDto, request: any, now?: DateTime): Observable { return this.contentsService.putContent(this.appName, this.schemaName, content.id, request, true, content.version).pipe( - tap(dto => { + mapVersioned((payload, version) => updateDataDraft(content, payload, this.user, version, now)), + tap(({ payload }) => { this.dialogs.notifyInfo('Content updated successfully.'); - if (dto.version.value !== content.version.value) { - this.replaceContent(updateDataDraft(content, dto.payload, this.user, dto.version, now)); - } + this.replaceContent(payload, content.version); }), shareSubscribed(this.dialogs)); } - public discardChanges(content: ContentDto, now?: DateTime): Observable { + public discardChanges(content: ContentDto, now?: DateTime): Observable { return this.contentsService.discardChanges(this.appName, this.schemaName, content.id, content.version).pipe( - tap(dto => { + mapVersioned((_, version) => discardChanges(content, this.user, version, now)), + tap(({ payload }) => { this.dialogs.notifyInfo('Content updated successfully.'); - if (dto.version.value !== content.version.value) { - this.replaceContent(discardChanges(content, this.user, dto.version, now)); - } + this.replaceContent(payload, content.version); }), shareSubscribed(this.dialogs)); } - public patch(content: ContentDto, request: any, now?: DateTime): Observable { + public patch(content: ContentDto, request: any, now?: DateTime): Observable { return this.contentsService.patchContent(this.appName, this.schemaName, content.id, request, content.version).pipe( - tap(dto => { + mapVersioned((data, version) => updateData(content, data, this.user, version, now)), + tap(({ payload }) => { this.dialogs.notifyInfo('Content updated successfully.'); - if (dto.version.value !== content.version.value) { - this.replaceContent(updateData(content, dto.payload, this.user, dto.version, now)); - } + this.replaceContent(payload, content.version); }), shareSubscribed(this.dialogs)); } - private replaceContent(content: ContentDto) { - return this.next(s => { - const contents = s.contents.replaceBy('id', content); - const selectedContent = s.selectedContent && s.selectedContent.id === content.id ? content : s.selectedContent; + private replaceContent(content: ContentDto, oldVersion?: Version) { + if (!oldVersion || oldVersion.eq(content.version)) { + return this.next(s => { + const contents = s.contents.replaceBy('id', content); + const selectedContent = s.selectedContent && s.selectedContent.id === content.id ? content : s.selectedContent; - return { ...s, contents, selectedContent }; - }); + return { ...s, contents, selectedContent }; + }); + } } public goArchive(isArchive: boolean): Observable { diff --git a/src/Squidex/app/shared/state/plans.state.ts b/src/Squidex/app/shared/state/plans.state.ts index 6019c7c90..d1fcb0ba9 100644 --- a/src/Squidex/app/shared/state/plans.state.ts +++ b/src/Squidex/app/shared/state/plans.state.ts @@ -112,14 +112,14 @@ export class PlansState extends State { public change(planId: string): Observable { return this.plansService.putPlan(this.appName, { planId }, this.version).pipe( - tap(dto => { - if (dto.payload.redirectUri && dto.payload.redirectUri.length > 0) { - this.window.location.href = dto.payload.redirectUri; + tap(({ payload, version }) => { + if (payload.redirectUri && payload.redirectUri.length > 0) { + this.window.location.href = payload.redirectUri; } else { this.next(s => { const plans = s.plans.map(x => this.createPlan(x.plan, planId)); - return { ...s, plans, isOwner: true, version: dto.version }; + return { ...s, plans, isOwner: true, version }; }); } }), diff --git a/src/Squidex/app/shared/state/rule-events.state.ts b/src/Squidex/app/shared/state/rule-events.state.ts index dea86da12..b9bf61996 100644 --- a/src/Squidex/app/shared/state/rule-events.state.ts +++ b/src/Squidex/app/shared/state/rule-events.state.ts @@ -66,14 +66,14 @@ export class RuleEventsState extends State { return this.rulesService.getEvents(this.appName, this.snapshot.ruleEventsPager.pageSize, this.snapshot.ruleEventsPager.skip).pipe( - tap(dtos => { + tap(({ total, items }) => { if (isReload) { this.dialogs.notifyInfo('RuleEvents reloaded.'); } return this.next(s => { - const ruleEvents = ImmutableArray.of(dtos.items); - const ruleEventsPager = s.ruleEventsPager.setCount(dtos.total); + const ruleEvents = ImmutableArray.of(items); + const ruleEventsPager = s.ruleEventsPager.setCount(total); return { ...s, ruleEvents, ruleEventsPager, isLoaded: true }; }); diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index f4bb90346..6e2928ed5 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -93,7 +93,7 @@ export class SchemasState extends State { private readonly dialogs: DialogService, private readonly schemasService: SchemasService ) { - super({ schemas: ImmutableArray.empty(), categories: {} }); + super({ schemas: ImmutableArray.empty(), categories: buildCategories({}) }); } public select(idOrName: string | null): Observable { @@ -137,9 +137,9 @@ export class SchemasState extends State { public create(request: CreateSchemaDto, now?: DateTime): Observable { return this.schemasService.postSchema(this.appName, request, this.user, now || DateTime.now()).pipe( - tap(dto => { + tap(payload => { this.next(s => { - const schemas = s.schemas.push(dto).sortByStringAsc(x => x.displayName); + const schemas = s.schemas.push(payload).sortByStringAsc(x => x.displayName); return { ...s, schemas }; }); @@ -375,7 +375,7 @@ export class SchemasState extends State { } } -function buildCategories(categories: { [name: string]: boolean }, schemas: SchemasList) { +function buildCategories(categories: { [name: string]: boolean }, schemas?: SchemasList) { categories = { ...categories }; for (let category in categories) { @@ -385,10 +385,15 @@ function buildCategories(categories: { [name: string]: boolean }, schemas: Schem } } } - for (let schema of schemas.values) { - categories[schema.category || ''] = false; + + if (schemas) { + for (let schema of schemas.values) { + categories[schema.category || ''] = false; + } } + categories[''] = true; + return categories; } diff --git a/src/Squidex/app/shared/state/ui.state.ts b/src/Squidex/app/shared/state/ui.state.ts index 27c7ed597..b9e1402c8 100644 --- a/src/Squidex/app/shared/state/ui.state.ts +++ b/src/Squidex/app/shared/state/ui.state.ts @@ -55,15 +55,15 @@ export class UIState extends State { this.next(s => updateAppSettings(s, {})); this.uiService.getSettings(this.appName) - .subscribe(dtos => { - this.next(s => updateAppSettings(s, dtos)); + .subscribe(payload => { + this.next(s => updateAppSettings(s, payload)); }); } private loadCommon() { this.uiService.getCommonSettings() - .subscribe(dtos => { - this.next(s => updateCommonSettings(s, dtos)); + .subscribe(payload => { + this.next(s => updateCommonSettings(s, payload)); }); } From ba4be11ad2974cc82f068c1640fd416c12e9ba06 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 29 Apr 2019 18:01:13 +0200 Subject: [PATCH 14/20] Tests fixed. --- src/Squidex/app/shared/state/schemas.state.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 0b5248a0e..ece6fddae 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -81,7 +81,7 @@ describe('SchemasState', () => { expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas); expect(schemasState.snapshot.isLoaded).toBeTruthy(); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false }); + expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, '': true }); schemasService.verifyAll(); }); @@ -95,7 +95,7 @@ describe('SchemasState', () => { expect(schemasState.snapshot.schemas.values).toEqual(oldSchemas); expect(schemasState.snapshot.isLoaded).toBeTruthy(); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); + expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true, '': true }); schemasService.verifyAll(); }); @@ -123,13 +123,13 @@ describe('SchemasState', () => { it('should add category', () => { schemasState.addCategory('category3'); - expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true }); + expect(schemasState.snapshot.categories).toEqual({ 'category1': false, 'category2': false, 'category3': true, '': true }); }); it('should remove category', () => { schemasState.removeCategory('category1'); - expect(schemasState.snapshot.categories).toEqual({ 'category2': false }); + expect(schemasState.snapshot.categories).toEqual({ 'category2': false, '': true }); }); it('should return schema on select and reload when already loaded', () => { From bd39b8d6a307f86798f808f62c6021e2e5f323f1 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 29 Apr 2019 22:22:47 +0200 Subject: [PATCH 15/20] Packages updated. --- src/Squidex/package-lock.json | 1021 +++++++++++++++++++++++++++++++-- src/Squidex/package.json | 26 +- 2 files changed, 986 insertions(+), 61 deletions(-) diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 12d349d08..47045544d 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -5,12 +5,12 @@ "requires": true, "dependencies": { "@angular-devkit/core": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.0.tgz", - "integrity": "sha512-b0qtAUpgqLpWY8W6vWRv1aj6bXkZCP1rvywl8i8TbGMY67CWRcy5J3fNAMmjiZS+LJixFlIXYf4iOydglyJMfg==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.8.tgz", + "integrity": "sha512-3X9uzaZXFpm5o2TSzhD6wEOtVU32CgeytKjD1Scxj+uMMVo48SWLlKiFh312T+smI9ko7tOT8VqxglwYkWosgg==", "dev": true, "requires": { - "ajv": "6.7.0", + "ajv": "6.9.1", "chokidar": "2.0.4", "fast-json-stable-stringify": "2.0.0", "rxjs": "6.3.3", @@ -18,9 +18,9 @@ }, "dependencies": { "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -409,38 +409,38 @@ } }, "@angular/animations": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.3.tgz", - "integrity": "sha512-5WoiDnVS2OhGgJ1oepFNF2UcfR4sJj97KRnTmLWQ0S4N4WpXX83CoOQVXvXwfotyb8uNtl4zRi2NuvN/MIuFuA==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.14.tgz", + "integrity": "sha512-K+wdq7TslmvDhrbwy65x7owE8wezI0fDdO+8SO9RU4m/w6R6vo4QS3uSdc5I2pxwm4QSXSc5eKhoWJkq0muTbQ==", "requires": { "tslib": "^1.9.0" } }, "@angular/common": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.3.tgz", - "integrity": "sha512-VZOTZdvkitaKEhkxL6daHxPcKqAFwNJm0U4NFB4LRP9KspsFTE60QFVB63o129PTIH9iOQ2D3HRKSRl4o78ZKg==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.14.tgz", + "integrity": "sha512-c2QBhVpbQhg1FDhOQkyVdFvU11mfvYHW5ZaXzxdCpq2rZXCureYiCSnlv++EsIAKqi22+2a6GACHF9Gh8kBmSg==", "requires": { "tslib": "^1.9.0" } }, "@angular/compiler": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.3.tgz", - "integrity": "sha512-UM6n4MyZkR5+VVjlwhLH8IfqdWBkdFcF5at4ckJXOJ/gkIUq97irbis9pGj1b0TO7MAl8uhF4b68xe5lk8b49g==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.14.tgz", + "integrity": "sha512-Idhs+5HIzx+1+hrXIDaRpSqobMB7UvSvPlvCvtb3EDYjmltTNG68TtwMzGM8W2jdayliYuFOjFrnw1wCTkK3Ag==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "@angular/compiler-cli": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.3.tgz", - "integrity": "sha512-31hcfTrU2GW66cvvaS629dNVPfiUrUWPncI28optvmKHBaH0mFqkdYNgabuslsXZV5AeidKMUJvR7GITjtvkQA==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.14.tgz", + "integrity": "sha512-w5qn1nIPjiCP3WdbqicofpKpiRlh6NMYjWhe6mJysSBnVd34aSuGisYW/gVPQrmD46E1gmfpWTnWPeABVnjj6w==", "dev": true, "requires": { "canonical-path": "1.0.0", - "chokidar": "^1.4.2", + "chokidar": "^2.1.1", "convert-source-map": "^1.5.1", "dependency-graph": "^0.7.2", "magic-string": "^0.25.0", @@ -450,52 +450,977 @@ "source-map": "^0.6.1", "tslib": "^1.9.0", "yargs": "9.0.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz", + "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + } } }, "@angular/core": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.3.tgz", - "integrity": "sha512-6Ql+sJJnrsxh8O0/IgIP1GgT4eLOHk+dlBs7zBbjstmLuhaQdY+awO9WKoQow+TiD1Go7FW1J3vZ2PTWXKxqjQ==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.14.tgz", + "integrity": "sha512-XeZZJCyBKSKo0E/7Ef0SfJejmn+E7uBXa5cR1QapafS0Hnrq/hZu/NI039IDU/51NoycMDH2vTV19SmKu9Mkow==", "requires": { "tslib": "^1.9.0" } }, "@angular/forms": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.3.tgz", - "integrity": "sha512-mZpyonfSmRwSvM6efvwFwkLJkK6wHQrm7X4OhVVu3s9i7BI253eLDY7WIRXFvoxJ/5jWIIarVnd/9UA7GINZGw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.14.tgz", + "integrity": "sha512-jL5YbTk7VZmz4l0++iFVUNa1vGM+nnALjHKi1Ub8VWioRDRboYUsHyxzlgWW9gZRbHpnLEXFiUz1td+v7TouJw==", "requires": { "tslib": "^1.9.0" } }, "@angular/http": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.3.tgz", - "integrity": "sha512-wzvBKbO/TcSR3U8AQbsGftH8x1OdAgVGHlfXQPmZL1KjIDHrM1VpnkSvgqIt8coG+4OPfWcNklUCrTdEGwqMqw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.14.tgz", + "integrity": "sha512-rSdH2JojApDU83qVm7RabIlNo3Ni3yr2gwsmQWs4XZ7SC8jLNnDkzdUbQ6T0vfuVX3v/FtAuMJl0yaVcG3EUJg==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.3.tgz", - "integrity": "sha512-DH0Y2lgEgcrP1I/DUQB/krL7Ob7yL685fu4sRapW17SndTQa2pqSFMBVf+mN3FupTXp7nJHSvlIktzedIk04+g==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.14.tgz", + "integrity": "sha512-yAq2+3W4J4B48HEmZYQucdEb9AHwRnv72q9CC/SxU7g59vaLhl1nv7cAWGJ4XFaJTbB7aB4Y4rLffuR+Gxkn7A==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser-dynamic": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.3.tgz", - "integrity": "sha512-M8Kiz5FUhnFybJuk/mgOhBjVbRgKDC4bGWKWH9Z9SXBR2dS/FL3QOJsLIthQcWlHOzSoJdEoPBRhn0R4pyLBSw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.14.tgz", + "integrity": "sha512-lmTCBiDRbOPtniIqBjm1n5jl1TdyQM0qWQdBcoCsKpMNS/6/RacRcQsJZApAMdWm6gIVuLgmRQzaCLkSoekfYA==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-server": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-7.2.3.tgz", - "integrity": "sha512-RXTFuuTlvy02YOtjWsrs8q+wnmXNW1JHueEseb8cWrgJz46ezhjuW3vwquDv1PwO5KZD2wlamZcrlbkwsdyzZw==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-7.2.14.tgz", + "integrity": "sha512-ijFqRrxpbPQiAlbRtw0uKX8Qf+wWZhY5vNwV8wfP5oVziJdO7Vdtcmmw2NQxHAIHUrK7FQ5yklUxfglKa2G7SQ==", "requires": { "domino": "^2.1.0", "tslib": "^1.9.0", @@ -503,9 +1428,9 @@ } }, "@angular/router": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.3.tgz", - "integrity": "sha512-SH7H2I9WTj1puei4m4g5n0/Cp28HS14q4r8lOgW0gLWuT6Ls7MqH/nDjOMiW924iRR6zjQQs7G+WbhL1jmZc2A==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.14.tgz", + "integrity": "sha512-uqg0SKy79voEOIOvzVbCzFDD9XOAfZWkYt01ca2qLFXMx+6jWeVQIDuXc8Dmz5udIXNK5Ae//9R+nt5UZUZrSA==", "requires": { "tslib": "^1.9.0" } @@ -681,12 +1606,12 @@ } }, "@ngtools/webpack": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.0.tgz", - "integrity": "sha512-U/By0Jlwy7nYwrGNtFirTg1aAsEHBL/9DhfFxPI0iu27FWiMttROuN6hmKbbnOmpbiYAVl5qTy3WXPXUIJjG1A==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.8.tgz", + "integrity": "sha512-gfjSKz+F/2T4tZHpnQ1XqelKP/CIfI87XdoHsOI53ceTUrAkVKsOb3ULmEfkcdsdQZ/HhmCiLivcutHcW8xkhQ==", "dev": true, "requires": { - "@angular-devkit/core": "7.3.0", + "@angular-devkit/core": "7.3.8", "enhanced-resolve": "4.1.0", "rxjs": "6.3.3", "tree-kill": "1.2.1", @@ -9717,9 +10642,9 @@ "integrity": "sha512-5mWWBePwvEPsNd/HkdbD543Q9mPyJofL6zkNydl8/Ah3qrrvZT2DaEPbknY08OgkXpI2qUGksc01OzzVlRQ9dQ==" }, "ngx-color-picker": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-7.3.0.tgz", - "integrity": "sha512-ICFR+bGfDFqiXadv8EuKylQGKn8JwkRxor0Grx6hVQVsmvLve/Z2mCDtCMItRQXjLI+4yO3iBDf9Oi1pGuBraQ==" + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-7.5.0.tgz", + "integrity": "sha512-bTW16A3IitWUNGc3kZtE+N1r3FpmUj7uJTG80eym2nQLvsROkMntalKJDo1SQVQhh9Nh4N9C88UezdMg8fjR5Q==" }, "nice-try": { "version": "1.0.5", diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 6f0c1c166..baf455083 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -15,15 +15,15 @@ "build:clean": "rimraf wwwroot/build" }, "dependencies": { - "@angular/animations": "7.2.3", - "@angular/common": "7.2.3", - "@angular/core": "7.2.3", - "@angular/forms": "7.2.3", - "@angular/http": "7.2.3", - "@angular/platform-browser": "7.2.3", - "@angular/platform-browser-dynamic": "7.2.3", - "@angular/platform-server": "7.2.3", - "@angular/router": "7.2.3", + "@angular/animations": "7.2.14", + "@angular/common": "7.2.14", + "@angular/core": "7.2.14", + "@angular/forms": "7.2.14", + "@angular/http": "7.2.14", + "@angular/platform-browser": "7.2.14", + "@angular/platform-browser-dynamic": "7.2.14", + "@angular/platform-server": "7.2.14", + "@angular/router": "7.2.14", "angular2-chartjs": "0.5.1", "babel-polyfill": "6.26.0", "bootstrap": "4.3.1", @@ -34,7 +34,7 @@ "moment": "2.24.0", "mousetrap": "1.6.3", "ng2-dnd": "5.0.2", - "ngx-color-picker": "7.3.0", + "ngx-color-picker": "7.5.0", "oidc-client": "1.7.1", "pikaday": "1.8.0", "progressbar.js": "1.0.1", @@ -47,9 +47,9 @@ "zone.js": "0.9.0" }, "devDependencies": { - "@angular/compiler": "7.2.3", - "@angular/compiler-cli": "7.2.3", - "@ngtools/webpack": "7.3.0", + "@angular/compiler": "7.2.14", + "@angular/compiler-cli": "7.2.14", + "@ngtools/webpack": "7.3.8", "@types/core-js": "2.5.0", "@types/jasmine": "3.3.12", "@types/marked": "0.6.5", From 1c02122130061f8306cd9aae13c2bebc99f37546 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 4 May 2019 12:15:19 +0200 Subject: [PATCH 16/20] Imports improved. --- src/Squidex/app-config/webpack.config.js | 10 +++++++++- src/Squidex/app-config/webpack.run.base.js | 1 + .../features/administration/declarations.ts | 7 +------ .../guards/unset-user.guard.spec.ts | 3 ++- .../administration/guards/unset-user.guard.ts | 2 +- .../guards/user-must-exist.guard.spec.ts | 3 ++- .../guards/user-must-exist.guard.ts | 2 +- .../app/features/administration/internal.ts | 13 +++++++++++++ .../event-consumers-page.component.ts | 2 +- .../pages/users/user-page.component.ts | 2 +- .../pages/users/users-page.component.ts | 2 +- .../state/event-consumers.state.spec.ts | 4 ++-- .../administration/state/users.state.spec.ts | 6 +++--- .../angular/forms/error-formatting.ts | 2 +- .../angular/forms/file-drop.directive.ts | 2 +- .../framework/angular/forms/forms-helper.ts | 2 +- .../framework/angular/forms/validators.spec.ts | 2 +- .../angular/http/caching.interceptor.ts | 2 +- .../framework/angular/http/http-extensions.ts | 9 ++++++--- .../modals/dialog-renderer.component.ts | 4 ++-- .../angular/modals/modal-target.directive.ts | 3 +-- .../angular/modals/tooltip.directive.ts | 3 +-- .../angular/pipes/date-time.pipes.spec.ts | 2 +- .../framework/angular/pipes/money.pipe.spec.ts | 2 +- .../angular/shortcut.component.spec.ts | 2 +- .../framework/angular/stateful.component.ts | 2 +- .../framework/services/analytics.service.ts | 2 +- src/Squidex/app/framework/state.ts | 1 + .../app/shared/components/asset.component.ts | 2 +- src/Squidex/app/shared/declarations.ts | 12 ++++++++++++ .../guards/content-must-exist.guard.spec.ts | 3 +-- .../schema-must-exist-published.guard.spec.ts | 3 +-- .../guards/schema-must-exist.guard.spec.ts | 3 +-- .../schema-must-not-be-singleton.guard.spec.ts | 3 +-- .../app/shared/guards/unset-app.guard.spec.ts | 2 +- .../shared/guards/unset-content.guard.spec.ts | 2 +- .../interceptors/auth.interceptor.spec.ts | 7 ++----- src/Squidex/app/shared/internal.ts | 12 ------------ .../services/app-languages.service.spec.ts | 2 +- .../app/shared/services/apps.service.spec.ts | 2 +- .../app/shared/services/assets.service.spec.ts | 2 +- .../shared/services/backups.service.spec.ts | 2 +- .../shared/services/clients.service.spec.ts | 2 +- .../shared/services/comments.service.spec.ts | 2 +- .../shared/services/contents.service.spec.ts | 2 +- .../services/contributors.service.spec.ts | 2 +- .../shared/services/graphql.service.spec.ts | 2 +- .../app/shared/services/help.service.spec.ts | 2 +- .../shared/services/history.service.spec.ts | 5 ++--- .../shared/services/languages.service.spec.ts | 2 +- .../app/shared/services/news.service.spec.ts | 2 +- .../shared/services/patterns.service.spec.ts | 2 +- .../app/shared/services/plans.service.spec.ts | 2 +- .../app/shared/services/roles.service.spec.ts | 2 +- .../app/shared/services/rules.service.spec.ts | 2 +- .../shared/services/schemas.service.spec.ts | 2 +- .../services/translations.service.spec.ts | 2 +- .../app/shared/services/ui.service.spec.ts | 2 +- .../app/shared/services/usages.service.spec.ts | 2 +- .../services/users-provider.service.spec.ts | 2 +- .../app/shared/services/users.service.spec.ts | 2 +- .../app/shared/state/apps.state.spec.ts | 2 +- .../shared/state/asset-uploader.state.spec.ts | 6 ++++-- .../app/shared/state/asset-uploader.state.ts | 2 +- .../app/shared/state/assets.state.spec.ts | 2 +- .../app/shared/state/backups.state.spec.ts | 2 +- .../app/shared/state/clients.state.spec.ts | 2 +- .../app/shared/state/comments.state.spec.ts | 2 +- .../app/shared/state/contents.forms.spec.ts | 5 ++--- .../shared/state/contributors.state.spec.ts | 2 +- .../app/shared/state/filter.state.spec.ts | 2 +- src/Squidex/app/shared/state/filter.state.ts | 4 ++-- .../app/shared/state/languages.forms.ts | 2 +- .../app/shared/state/languages.state.spec.ts | 2 +- .../app/shared/state/patterns.state.spec.ts | 2 +- .../app/shared/state/plans.state.spec.ts | 2 +- src/Squidex/app/shared/state/queries.spec.ts | 2 +- .../app/shared/state/roles.state.spec.ts | 2 +- .../app/shared/state/rule-events.state.spec.ts | 2 +- .../app/shared/state/rules.state.spec.ts | 2 +- src/Squidex/app/shared/state/schemas.forms.ts | 2 +- .../app/shared/state/schemas.state.spec.ts | 2 +- src/Squidex/app/shared/state/ui.state.spec.ts | 2 +- src/Squidex/package-lock.json | 18 ++++++++++++------ src/Squidex/package.json | 1 + 85 files changed, 144 insertions(+), 123 deletions(-) create mode 100644 src/Squidex/app/features/administration/internal.ts diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js index 588d04e85..5ff10d725 100644 --- a/src/Squidex/app-config/webpack.config.js +++ b/src/Squidex/app-config/webpack.config.js @@ -6,7 +6,9 @@ const plugins = { // https://github.com/webpack-contrib/mini-css-extract-plugin MiniCssExtractPlugin: require('mini-css-extract-plugin'), // https://github.com/dividab/tsconfig-paths-webpack-plugin - TsconfigPathsPlugin: require('tsconfig-paths-webpack-plugin') + TsconfigPathsPlugin: require('tsconfig-paths-webpack-plugin'), + // https://github.com/aackerman/circular-dependency-plugin + CircularDependencyPlugin: require('circular-dependency-plugin') }; const isDevServer = path.basename(require.main.filename) === 'webpack-dev-server.js'; @@ -140,6 +142,12 @@ module.exports = { context: '/' } }), + + new plugins.CircularDependencyPlugin({ + exclude: /([\\\/]node_modules[\\\/])|(ngfactory\.js$)/, + // Add errors to webpack instead of warnings + failOnError: true + }), new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/) ] diff --git a/src/Squidex/app-config/webpack.run.base.js b/src/Squidex/app-config/webpack.run.base.js index 3fd8ea67c..06012fa60 100644 --- a/src/Squidex/app-config/webpack.run.base.js +++ b/src/Squidex/app-config/webpack.run.base.js @@ -5,6 +5,7 @@ commonConfig = require('./webpack.config.js'); const plugins = { + // https://github.com/jantimon/html-webpack-plugin HtmlWebpackPlugin: require('html-webpack-plugin') }; diff --git a/src/Squidex/app/features/administration/declarations.ts b/src/Squidex/app/features/administration/declarations.ts index 2a3b2198d..5c8cac3a6 100644 --- a/src/Squidex/app/features/administration/declarations.ts +++ b/src/Squidex/app/features/administration/declarations.ts @@ -15,9 +15,4 @@ export * from './pages/restore/restore-page.component'; export * from './pages/users/user-page.component'; export * from './pages/users/users-page.component'; -export * from './services/event-consumers.service'; -export * from './services/users.service'; - -export * from './state/event-consumers.state'; -export * from './state/users.forms'; -export * from './state/users.state'; \ No newline at end of file +export * from './internal'; \ No newline at end of file diff --git a/src/Squidex/app/features/administration/guards/unset-user.guard.spec.ts b/src/Squidex/app/features/administration/guards/unset-user.guard.spec.ts index 15414e732..d4dad973f 100644 --- a/src/Squidex/app/features/administration/guards/unset-user.guard.spec.ts +++ b/src/Squidex/app/features/administration/guards/unset-user.guard.spec.ts @@ -8,7 +8,8 @@ import { of } from 'rxjs'; import { IMock, Mock, Times } from 'typemoq'; -import { UsersState } from './../state/users.state'; +import { UsersState } from '@app/features/administration/internal'; + import { UnsetUserGuard } from './unset-user.guard'; describe('UnsetUserGuard', () => { diff --git a/src/Squidex/app/features/administration/guards/unset-user.guard.ts b/src/Squidex/app/features/administration/guards/unset-user.guard.ts index 1a8d42be2..bec813ee2 100644 --- a/src/Squidex/app/features/administration/guards/unset-user.guard.ts +++ b/src/Squidex/app/features/administration/guards/unset-user.guard.ts @@ -10,7 +10,7 @@ import { CanActivate } from '@angular/router'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { UsersState } from './../state/users.state'; +import { UsersState } from '@app/features/administration/internal'; @Injectable() export class UnsetUserGuard implements CanActivate { diff --git a/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts b/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts index 8070a5f30..a5c03338f 100644 --- a/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts +++ b/src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts @@ -9,7 +9,8 @@ import { Router } from '@angular/router'; import { of } from 'rxjs'; import { IMock, Mock, Times } from 'typemoq'; -import { SnapshotUser, UsersState } from './../state/users.state'; +import { SnapshotUser, UsersState } from '@app/features/administration/internal'; + import { UserMustExistGuard } from './user-must-exist.guard'; describe('UserMustExistGuard', () => { diff --git a/src/Squidex/app/features/administration/guards/user-must-exist.guard.ts b/src/Squidex/app/features/administration/guards/user-must-exist.guard.ts index 63fc2bba1..22b120ff3 100644 --- a/src/Squidex/app/features/administration/guards/user-must-exist.guard.ts +++ b/src/Squidex/app/features/administration/guards/user-must-exist.guard.ts @@ -12,7 +12,7 @@ import { map, tap } from 'rxjs/operators'; import { allParams } from '@app/framework'; -import { UsersState } from './../state/users.state'; +import { UsersState } from '@app/features/administration/internal'; @Injectable() export class UserMustExistGuard implements CanActivate { diff --git a/src/Squidex/app/features/administration/internal.ts b/src/Squidex/app/features/administration/internal.ts new file mode 100644 index 000000000..5a182a4dc --- /dev/null +++ b/src/Squidex/app/features/administration/internal.ts @@ -0,0 +1,13 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +export * from './services/event-consumers.service'; +export * from './services/users.service'; + +export * from './state/event-consumers.state'; +export * from './state/users.forms'; +export * from './state/users.state'; \ No newline at end of file diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts index da06f82c7..f4b0b97fd 100644 --- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts +++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts @@ -11,7 +11,7 @@ import { onErrorResumeNext, switchMap } from 'rxjs/operators'; import { DialogModel, ResourceOwner } from '@app/shared'; -import { EventConsumerDto, EventConsumersState } from '../../declarations'; +import { EventConsumerDto, EventConsumersState } from '@app/features/administration/internal'; @Component({ selector: 'sqx-event-consumers-page', diff --git a/src/Squidex/app/features/administration/pages/users/user-page.component.ts b/src/Squidex/app/features/administration/pages/users/user-page.component.ts index fa4f43c82..0c7e1efc2 100644 --- a/src/Squidex/app/features/administration/pages/users/user-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/user-page.component.ts @@ -16,7 +16,7 @@ import { UserDto, UserForm, UsersState -} from '../../declarations'; +} from '@app/features/administration/internal'; @Component({ selector: 'sqx-user-page', diff --git a/src/Squidex/app/features/administration/pages/users/users-page.component.ts b/src/Squidex/app/features/administration/pages/users/users-page.component.ts index b0137f171..065b20858 100644 --- a/src/Squidex/app/features/administration/pages/users/users-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/users-page.component.ts @@ -8,7 +8,7 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; -import { UserDto, UsersState } from '../../declarations'; +import { UserDto, UsersState } from '@app/features/administration/internal'; @Component({ selector: 'sqx-users-page', diff --git a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts index 9020ad510..4a69ffbeb 100644 --- a/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts +++ b/src/Squidex/app/features/administration/state/event-consumers.state.spec.ts @@ -9,9 +9,9 @@ import { of, throwError } from 'rxjs'; import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, It, Mock, Times } from 'typemoq'; -import { DialogService } from '@app/shared'; +import { DialogService } from '@app/framework'; -import { EventConsumerDto, EventConsumersService } from './../services/event-consumers.service'; +import { EventConsumerDto, EventConsumersService } from '@app/features/administration/internal'; import { EventConsumersState } from './event-consumers.state'; describe('EventConsumersState', () => { diff --git a/src/Squidex/app/features/administration/state/users.state.spec.ts b/src/Squidex/app/features/administration/state/users.state.spec.ts index 235108d73..c2a912ecd 100644 --- a/src/Squidex/app/features/administration/state/users.state.spec.ts +++ b/src/Squidex/app/features/administration/state/users.state.spec.ts @@ -10,13 +10,13 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { AuthService, DialogService } from '@app/shared'; -import { SnapshotUser, UsersState } from './users.state'; - import { UserDto, UsersDto, UsersService -} from './../services/users.service'; +} from '@app/features/administration/internal'; + +import { SnapshotUser, UsersState } from './users.state'; describe('UsersState', () => { const oldUsers = [ diff --git a/src/Squidex/app/framework/angular/forms/error-formatting.ts b/src/Squidex/app/framework/angular/forms/error-formatting.ts index a54d23941..abdff3007 100644 --- a/src/Squidex/app/framework/angular/forms/error-formatting.ts +++ b/src/Squidex/app/framework/angular/forms/error-formatting.ts @@ -5,7 +5,7 @@ * Copyright (c) Sebastian Stehle. All rights r vbeserved */ -import { Types } from './../../utils/types'; +import { Types } from '@app/framework/internal'; const DEFAULT_ERRORS: { [key: string]: string } = { between: '{field} must be between \'{min}\' and \'{max}\'.', diff --git a/src/Squidex/app/framework/angular/forms/file-drop.directive.ts b/src/Squidex/app/framework/angular/forms/file-drop.directive.ts index 7b572d106..027413c90 100644 --- a/src/Squidex/app/framework/angular/forms/file-drop.directive.ts +++ b/src/Squidex/app/framework/angular/forms/file-drop.directive.ts @@ -9,7 +9,7 @@ import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2 } from '@angular/core'; -import { Types } from './../../utils/types'; +import { Types } from '@app/framework/internal'; const ImageTypes = [ 'image/jpeg', diff --git a/src/Squidex/app/framework/angular/forms/forms-helper.ts b/src/Squidex/app/framework/angular/forms/forms-helper.ts index 91b4100b3..0f4b23d27 100644 --- a/src/Squidex/app/framework/angular/forms/forms-helper.ts +++ b/src/Squidex/app/framework/angular/forms/forms-helper.ts @@ -9,7 +9,7 @@ import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; -import { Types } from '@app/framework/internal'; +import { Types } from './../../utils/types'; export function formControls(form: AbstractControl): AbstractControl[] { if (Types.is(form, FormGroup)) { diff --git a/src/Squidex/app/framework/angular/forms/validators.spec.ts b/src/Squidex/app/framework/angular/forms/validators.spec.ts index 1e0911720..cbc5173d3 100644 --- a/src/Squidex/app/framework/angular/forms/validators.spec.ts +++ b/src/Squidex/app/framework/angular/forms/validators.spec.ts @@ -7,7 +7,7 @@ import { FormControl, FormGroup, Validators } from '@angular/forms'; -import { DateTime } from './../../utils/date-time'; +import { DateTime } from '@app/framework/internal'; import { ValidatorsEx } from './validators'; diff --git a/src/Squidex/app/framework/angular/http/caching.interceptor.ts b/src/Squidex/app/framework/angular/http/caching.interceptor.ts index 111bc2aad..3058f13cd 100644 --- a/src/Squidex/app/framework/angular/http/caching.interceptor.ts +++ b/src/Squidex/app/framework/angular/http/caching.interceptor.ts @@ -10,7 +10,7 @@ import { Injectable} from '@angular/core'; import { Observable, of, throwError } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; -import { Types } from '@app/shared/internal'; +import { Types } from '@app/framework/internal'; @Injectable() export class CachingInterceptor implements HttpInterceptor { diff --git a/src/Squidex/app/framework/angular/http/http-extensions.ts b/src/Squidex/app/framework/angular/http/http-extensions.ts index 3566c63a3..0745c8227 100644 --- a/src/Squidex/app/framework/angular/http/http-extensions.ts +++ b/src/Squidex/app/framework/angular/http/http-extensions.ts @@ -9,9 +9,12 @@ import { HttpClient, HttpErrorResponse, HttpHeaders, HttpResponse } from '@angul import { Observable, throwError } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; -import { ErrorDto } from './../../utils/error'; -import { Types} from './../../utils/types'; -import { Version, Versioned } from './../../utils/version'; +import { + ErrorDto, + Types, + Version, + Versioned +} from '@app/framework/internal'; export module HTTP { export function getVersioned(http: HttpClient, url: string, version?: Version): Observable>> { diff --git a/src/Squidex/app/framework/angular/modals/dialog-renderer.component.ts b/src/Squidex/app/framework/angular/modals/dialog-renderer.component.ts index 873f4ced7..a1ff94145 100644 --- a/src/Squidex/app/framework/angular/modals/dialog-renderer.component.ts +++ b/src/Squidex/app/framework/angular/modals/dialog-renderer.component.ts @@ -14,9 +14,9 @@ import { DialogService, fadeAnimation, Notification, - StatefulComponent + StatefulComponent, + Tooltip } from '@app/framework/internal'; -import { Tooltip } from '@app/shared'; interface State { dialogRequest?: DialogRequest | null; diff --git a/src/Squidex/app/framework/angular/modals/modal-target.directive.ts b/src/Squidex/app/framework/angular/modals/modal-target.directive.ts index 65692dd30..2b1431a8d 100644 --- a/src/Squidex/app/framework/angular/modals/modal-target.directive.ts +++ b/src/Squidex/app/framework/angular/modals/modal-target.directive.ts @@ -8,8 +8,7 @@ import { AfterViewInit, Directive, ElementRef, Input, OnDestroy, Renderer2 } from '@angular/core'; import { timer } from 'rxjs'; -import { ResourceOwner } from '@app/framework/internal'; -import { positionModal } from '@app/shared'; +import { positionModal, ResourceOwner } from '@app/framework/internal'; @Directive({ selector: '[sqxModalTarget]' diff --git a/src/Squidex/app/framework/angular/modals/tooltip.directive.ts b/src/Squidex/app/framework/angular/modals/tooltip.directive.ts index c6c5afc73..6e835cee2 100644 --- a/src/Squidex/app/framework/angular/modals/tooltip.directive.ts +++ b/src/Squidex/app/framework/angular/modals/tooltip.directive.ts @@ -9,8 +9,7 @@ import { Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core'; -import { DialogService } from '@app/framework/internal'; -import { Tooltip } from '@app/shared'; +import { DialogService, Tooltip } from '@app/framework/internal'; @Directive({ selector: '[title]' diff --git a/src/Squidex/app/framework/angular/pipes/date-time.pipes.spec.ts b/src/Squidex/app/framework/angular/pipes/date-time.pipes.spec.ts index 00da0249c..d5dc34f54 100644 --- a/src/Squidex/app/framework/angular/pipes/date-time.pipes.spec.ts +++ b/src/Squidex/app/framework/angular/pipes/date-time.pipes.spec.ts @@ -5,7 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { DateTime, Duration } from './../../'; +import { DateTime, Duration } from '@app/framework/internal'; import { DatePipe, diff --git a/src/Squidex/app/framework/angular/pipes/money.pipe.spec.ts b/src/Squidex/app/framework/angular/pipes/money.pipe.spec.ts index 80f1b6cc8..5b760fd49 100644 --- a/src/Squidex/app/framework/angular/pipes/money.pipe.spec.ts +++ b/src/Squidex/app/framework/angular/pipes/money.pipe.spec.ts @@ -5,7 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { CurrencyConfig, DecimalSeparatorConfig } from './../../'; +import { CurrencyConfig, DecimalSeparatorConfig } from '@app/framework/internal'; import { MoneyPipe } from './money.pipe'; diff --git a/src/Squidex/app/framework/angular/shortcut.component.spec.ts b/src/Squidex/app/framework/angular/shortcut.component.spec.ts index 50009a2cb..a5a28fe32 100644 --- a/src/Squidex/app/framework/angular/shortcut.component.spec.ts +++ b/src/Squidex/app/framework/angular/shortcut.component.spec.ts @@ -7,7 +7,7 @@ import { NgZone } from '@angular/core'; -import { ShortcutService } from './../'; +import { ShortcutService } from '@app/framework/internal'; import { ShortcutComponent } from './shortcut.component'; describe('ShortcutComponent', () => { diff --git a/src/Squidex/app/framework/angular/stateful.component.ts b/src/Squidex/app/framework/angular/stateful.component.ts index b3ba9f3c7..ec261fcfa 100644 --- a/src/Squidex/app/framework/angular/stateful.component.ts +++ b/src/Squidex/app/framework/angular/stateful.component.ts @@ -12,7 +12,7 @@ import { onErrorResumeNext, skip } from 'rxjs/operators'; import { Types } from './../utils/types'; -import { State } from '../state'; +import { State } from './../state'; declare type UnsubscribeFunction = () => void; diff --git a/src/Squidex/app/framework/services/analytics.service.ts b/src/Squidex/app/framework/services/analytics.service.ts index 4b94c2279..9bf3183c1 100644 --- a/src/Squidex/app/framework/services/analytics.service.ts +++ b/src/Squidex/app/framework/services/analytics.service.ts @@ -9,7 +9,7 @@ import { Injectable } from '@angular/core'; import { NavigationEnd, Router } from '@angular/router'; import { filter } from 'rxjs/operators'; -import { AnalyticsIdConfig } from '../configurations'; +import { AnalyticsIdConfig } from './../configurations'; import { Types } from './../utils/types'; import { ResourceLoaderService } from './resource-loader.service'; diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index c788a7700..9d15cbb32 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -10,6 +10,7 @@ import { BehaviorSubject, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ErrorDto } from './utils/error'; + import { Types } from './utils/types'; import { fullValue} from './angular/forms/forms-helper'; diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 253d111a8..b330cc647 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -15,7 +15,7 @@ import { StatefulComponent, Types } from '@app/shared/internal'; -import { AssetUploaderState, UploadCanceled } from '../state/asset-uploader.state'; +import { AssetUploaderState, UploadCanceled } from './../state/asset-uploader.state'; interface State { progress: number; diff --git a/src/Squidex/app/shared/declarations.ts b/src/Squidex/app/shared/declarations.ts index f69259f8a..7d5d57367 100644 --- a/src/Squidex/app/shared/declarations.ts +++ b/src/Squidex/app/shared/declarations.ts @@ -27,4 +27,16 @@ export * from './components/schema-category.component'; export * from './components/search-form.component'; export * from './components/table-header.component'; +export * from './guards/app-must-exist.guard'; +export * from './guards/content-must-exist.guard'; +export * from './guards/load-apps.guard'; +export * from './guards/load-languages.guard'; +export * from './guards/must-be-authenticated.guard'; +export * from './guards/must-be-not-authenticated.guard'; +export * from './guards/schema-must-exist-published.guard'; +export * from './guards/schema-must-exist.guard'; +export * from './guards/schema-must-not-be-singleton.guard'; +export * from './guards/unset-app.guard'; +export * from './guards/unset-content.guard'; + export * from './internal'; \ No newline at end of file diff --git a/src/Squidex/app/shared/guards/content-must-exist.guard.spec.ts b/src/Squidex/app/shared/guards/content-must-exist.guard.spec.ts index 96f0727b6..b54ee76fd 100644 --- a/src/Squidex/app/shared/guards/content-must-exist.guard.spec.ts +++ b/src/Squidex/app/shared/guards/content-must-exist.guard.spec.ts @@ -9,8 +9,7 @@ import { Router } from '@angular/router'; import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; -import { ContentDto } from './../services/contents.service'; -import { ContentsState } from './../state/contents.state'; +import { ContentDto, ContentsState } from '@app/shared/internal'; import { ContentMustExistGuard } from './content-must-exist.guard'; describe('ContentMustExistGuard', () => { diff --git a/src/Squidex/app/shared/guards/schema-must-exist-published.guard.spec.ts b/src/Squidex/app/shared/guards/schema-must-exist-published.guard.spec.ts index 560ff9a86..89028ec95 100644 --- a/src/Squidex/app/shared/guards/schema-must-exist-published.guard.spec.ts +++ b/src/Squidex/app/shared/guards/schema-must-exist-published.guard.spec.ts @@ -9,8 +9,7 @@ import { Router } from '@angular/router'; import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; -import { SchemaDetailsDto } from './../services/schemas.service'; -import { SchemasState } from './../state/schemas.state'; +import { SchemaDetailsDto, SchemasState } from '@app/shared/internal'; import { SchemaMustExistPublishedGuard } from './schema-must-exist-published.guard'; describe('SchemaMustExistPublishedGuard', () => { diff --git a/src/Squidex/app/shared/guards/schema-must-exist.guard.spec.ts b/src/Squidex/app/shared/guards/schema-must-exist.guard.spec.ts index 2c517be7b..f5c4e3475 100644 --- a/src/Squidex/app/shared/guards/schema-must-exist.guard.spec.ts +++ b/src/Squidex/app/shared/guards/schema-must-exist.guard.spec.ts @@ -9,8 +9,7 @@ import { Router } from '@angular/router'; import { of } from 'rxjs'; import { IMock, Mock, Times } from 'typemoq'; -import { SchemaDetailsDto } from './../services/schemas.service'; -import { SchemasState } from './../state/schemas.state'; +import { SchemaDetailsDto, SchemasState } from '@app/shared/internal'; import { SchemaMustExistGuard } from './schema-must-exist.guard'; describe('SchemaMustExistGuard', () => { diff --git a/src/Squidex/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts b/src/Squidex/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts index 2de66fc8b..ccc3b32ec 100644 --- a/src/Squidex/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts +++ b/src/Squidex/app/shared/guards/schema-must-not-be-singleton.guard.spec.ts @@ -9,8 +9,7 @@ import { Router, RouterStateSnapshot, UrlSegment } from '@angular/router'; import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; -import { SchemaDetailsDto } from './../services/schemas.service'; -import { SchemasState } from './../state/schemas.state'; +import { SchemaDetailsDto, SchemasState } from '@app/shared/internal'; import { SchemaMustNotBeSingletonGuard } from './schema-must-not-be-singleton.guard'; describe('SchemaMustNotBeSingletonGuard', () => { diff --git a/src/Squidex/app/shared/guards/unset-app.guard.spec.ts b/src/Squidex/app/shared/guards/unset-app.guard.spec.ts index 14ed0f21d..f04d5acb0 100644 --- a/src/Squidex/app/shared/guards/unset-app.guard.spec.ts +++ b/src/Squidex/app/shared/guards/unset-app.guard.spec.ts @@ -8,7 +8,7 @@ import { of } from 'rxjs'; import { IMock, Mock, Times } from 'typemoq'; -import { AppsState } from '@app/shared'; +import { AppsState } from '@app/shared/internal'; import { UnsetAppGuard } from './unset-app.guard'; diff --git a/src/Squidex/app/shared/guards/unset-content.guard.spec.ts b/src/Squidex/app/shared/guards/unset-content.guard.spec.ts index 8c0e6905f..9aba68f66 100644 --- a/src/Squidex/app/shared/guards/unset-content.guard.spec.ts +++ b/src/Squidex/app/shared/guards/unset-content.guard.spec.ts @@ -8,7 +8,7 @@ import { of } from 'rxjs'; import { IMock, Mock, Times } from 'typemoq'; -import { ContentsState } from './../state/contents.state'; +import { ContentsState } from '@app/shared/internal'; import { UnsetContentGuard } from './unset-content.guard'; describe('UnsetContentGuard', () => { diff --git a/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts b/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts index 11b66ab1a..a7206035c 100644 --- a/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts +++ b/src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts @@ -12,11 +12,8 @@ import { of } from 'rxjs'; import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, Mock, Times } from 'typemoq'; -import { - ApiUrlConfig, - AuthInterceptor, - AuthService -} from './../'; +import { ApiUrlConfig, AuthService } from '@app/shared/internal'; +import { AuthInterceptor } from './auth.interceptor'; describe('AuthInterceptor', () => { let authService: IMock; diff --git a/src/Squidex/app/shared/internal.ts b/src/Squidex/app/shared/internal.ts index 665d17c84..f467a7636 100644 --- a/src/Squidex/app/shared/internal.ts +++ b/src/Squidex/app/shared/internal.ts @@ -5,18 +5,6 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -export * from './guards/app-must-exist.guard'; -export * from './guards/content-must-exist.guard'; -export * from './guards/load-apps.guard'; -export * from './guards/load-languages.guard'; -export * from './guards/must-be-authenticated.guard'; -export * from './guards/must-be-not-authenticated.guard'; -export * from './guards/schema-must-exist-published.guard'; -export * from './guards/schema-must-exist.guard'; -export * from './guards/schema-must-not-be-singleton.guard'; -export * from './guards/unset-app.guard'; -export * from './guards/unset-content.guard'; - export * from './interceptors/auth.interceptor'; export * from './services/app-languages.service'; diff --git a/src/Squidex/app/shared/services/app-languages.service.spec.ts b/src/Squidex/app/shared/services/app-languages.service.spec.ts index 4c41624de..e9c57425a 100644 --- a/src/Squidex/app/shared/services/app-languages.service.spec.ts +++ b/src/Squidex/app/shared/services/app-languages.service.spec.ts @@ -15,7 +15,7 @@ import { AppLanguagesDto, AppLanguagesService, Version -} from './../'; +} from '@app/shared/internal'; describe('AppLanguagesService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/apps.service.spec.ts b/src/Squidex/app/shared/services/apps.service.spec.ts index 361d80a2d..75f064593 100644 --- a/src/Squidex/app/shared/services/apps.service.spec.ts +++ b/src/Squidex/app/shared/services/apps.service.spec.ts @@ -15,7 +15,7 @@ import { AppsService, DateTime, Permission -} from './../'; +} from '@app/shared/internal'; describe('AppsService', () => { const now = DateTime.now(); diff --git a/src/Squidex/app/shared/services/assets.service.spec.ts b/src/Squidex/app/shared/services/assets.service.spec.ts index 6c32b85d4..4bca45ca4 100644 --- a/src/Squidex/app/shared/services/assets.service.spec.ts +++ b/src/Squidex/app/shared/services/assets.service.spec.ts @@ -19,7 +19,7 @@ import { ErrorDto, Version, Versioned -} from './../'; +} from '@app/shared/internal'; describe('AssetDto', () => { const creation = DateTime.today(); diff --git a/src/Squidex/app/shared/services/backups.service.spec.ts b/src/Squidex/app/shared/services/backups.service.spec.ts index 3f2c971a2..f4f51683b 100644 --- a/src/Squidex/app/shared/services/backups.service.spec.ts +++ b/src/Squidex/app/shared/services/backups.service.spec.ts @@ -15,7 +15,7 @@ import { BackupsService, DateTime, RestoreDto -} from './../'; +} from '@app/shared/internal'; describe('BackupsService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/clients.service.spec.ts b/src/Squidex/app/shared/services/clients.service.spec.ts index 25c9c9e97..02afa3486 100644 --- a/src/Squidex/app/shared/services/clients.service.spec.ts +++ b/src/Squidex/app/shared/services/clients.service.spec.ts @@ -16,7 +16,7 @@ import { ClientsDto, ClientsService, Version -} from './../'; +} from '@app/shared/internal'; describe('ClientsService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/comments.service.spec.ts b/src/Squidex/app/shared/services/comments.service.spec.ts index 03be1dcc6..c86ad3ea9 100644 --- a/src/Squidex/app/shared/services/comments.service.spec.ts +++ b/src/Squidex/app/shared/services/comments.service.spec.ts @@ -15,7 +15,7 @@ import { CommentsService, DateTime, Version -} from './../'; +} from '@app/shared/internal'; describe('CommentsService', () => { const user = 'me'; diff --git a/src/Squidex/app/shared/services/contents.service.spec.ts b/src/Squidex/app/shared/services/contents.service.spec.ts index 87fc4112e..4ff9e0c0b 100644 --- a/src/Squidex/app/shared/services/contents.service.spec.ts +++ b/src/Squidex/app/shared/services/contents.service.spec.ts @@ -18,7 +18,7 @@ import { ScheduleDto, Version, Versioned -} from './../'; +} from '@app/shared/internal'; describe('ContentsService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/contributors.service.spec.ts b/src/Squidex/app/shared/services/contributors.service.spec.ts index 55a92e447..930f1b9c0 100644 --- a/src/Squidex/app/shared/services/contributors.service.spec.ts +++ b/src/Squidex/app/shared/services/contributors.service.spec.ts @@ -16,7 +16,7 @@ import { ContributorsDto, ContributorsService, Version -} from './../'; +} from '@app/shared/internal'; describe('ContributorsService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/graphql.service.spec.ts b/src/Squidex/app/shared/services/graphql.service.spec.ts index 97146d2f4..4221f51a9 100644 --- a/src/Squidex/app/shared/services/graphql.service.spec.ts +++ b/src/Squidex/app/shared/services/graphql.service.spec.ts @@ -8,7 +8,7 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { inject, TestBed } from '@angular/core/testing'; -import { ApiUrlConfig, GraphQlService } from './../'; +import { ApiUrlConfig, GraphQlService } from '@app/shared/internal'; describe('GraphQlService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/help.service.spec.ts b/src/Squidex/app/shared/services/help.service.spec.ts index 29891a4a3..83d85a4d9 100644 --- a/src/Squidex/app/shared/services/help.service.spec.ts +++ b/src/Squidex/app/shared/services/help.service.spec.ts @@ -8,7 +8,7 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { inject, TestBed } from '@angular/core/testing'; -import { HelpService } from './../'; +import { HelpService } from '@app/shared/internal'; describe('ClientsService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/history.service.spec.ts b/src/Squidex/app/shared/services/history.service.spec.ts index a8662865f..26ffd00a0 100644 --- a/src/Squidex/app/shared/services/history.service.spec.ts +++ b/src/Squidex/app/shared/services/history.service.spec.ts @@ -8,13 +8,12 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { inject, TestBed } from '@angular/core/testing'; -import { DateTime } from '@app/framework'; - import { ApiUrlConfig, + DateTime, HistoryEventDto, HistoryService -} from './../'; +} from '@app/shared/internal'; describe('HistoryService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/languages.service.spec.ts b/src/Squidex/app/shared/services/languages.service.spec.ts index ee55ea9f1..b7ddce678 100644 --- a/src/Squidex/app/shared/services/languages.service.spec.ts +++ b/src/Squidex/app/shared/services/languages.service.spec.ts @@ -12,7 +12,7 @@ import { ApiUrlConfig, LanguageDto, LanguagesService -} from './../'; +} from '@app/shared/internal'; describe('LanguageService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/news.service.spec.ts b/src/Squidex/app/shared/services/news.service.spec.ts index ccba7d3c9..fc81c675b 100644 --- a/src/Squidex/app/shared/services/news.service.spec.ts +++ b/src/Squidex/app/shared/services/news.service.spec.ts @@ -13,7 +13,7 @@ import { FeatureDto, FeaturesDto, NewsService -} from './../'; +} from '@app/shared/internal'; describe('NewsService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/patterns.service.spec.ts b/src/Squidex/app/shared/services/patterns.service.spec.ts index 3c6800391..8454db9da 100644 --- a/src/Squidex/app/shared/services/patterns.service.spec.ts +++ b/src/Squidex/app/shared/services/patterns.service.spec.ts @@ -15,7 +15,7 @@ import { PatternsDto, PatternsService, Version -} from './../'; +} from '@app/shared/internal'; describe('PatternsService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/plans.service.spec.ts b/src/Squidex/app/shared/services/plans.service.spec.ts index 3369a6425..4c4cd4792 100644 --- a/src/Squidex/app/shared/services/plans.service.spec.ts +++ b/src/Squidex/app/shared/services/plans.service.spec.ts @@ -16,7 +16,7 @@ import { PlansDto, PlansService, Version -} from './../'; +} from '@app/shared/internal'; describe('PlansService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/roles.service.spec.ts b/src/Squidex/app/shared/services/roles.service.spec.ts index 91cd3c879..687e9e305 100644 --- a/src/Squidex/app/shared/services/roles.service.spec.ts +++ b/src/Squidex/app/shared/services/roles.service.spec.ts @@ -15,7 +15,7 @@ import { RolesDto, RolesService, Version -} from './../'; +} from '@app/shared/internal'; describe('RolesService', () => { const version = new Version('1'); diff --git a/src/Squidex/app/shared/services/rules.service.spec.ts b/src/Squidex/app/shared/services/rules.service.spec.ts index 5a46294ff..955954bb4 100644 --- a/src/Squidex/app/shared/services/rules.service.spec.ts +++ b/src/Squidex/app/shared/services/rules.service.spec.ts @@ -20,7 +20,7 @@ import { RuleEventsDto, RulesService, Version -} from './../'; +} from '@app/shared/internal'; describe('RulesService', () => { const now = DateTime.now(); diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index 0a9bed879..c0405c407 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -23,7 +23,7 @@ import { SchemaPropertiesDto, SchemasService, Version -} from './../'; +} from '@app/shared/internal'; describe('SchemasService', () => { const now = DateTime.now(); diff --git a/src/Squidex/app/shared/services/translations.service.spec.ts b/src/Squidex/app/shared/services/translations.service.spec.ts index 864fab019..3ac0c22d1 100644 --- a/src/Squidex/app/shared/services/translations.service.spec.ts +++ b/src/Squidex/app/shared/services/translations.service.spec.ts @@ -12,7 +12,7 @@ import { ApiUrlConfig, TranslationDto, TranslationsService -} from './../'; +} from '@app/shared/internal'; describe('TranslationsService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/ui.service.spec.ts b/src/Squidex/app/shared/services/ui.service.spec.ts index 0331a9c21..537ea44e0 100644 --- a/src/Squidex/app/shared/services/ui.service.spec.ts +++ b/src/Squidex/app/shared/services/ui.service.spec.ts @@ -12,7 +12,7 @@ import { ApiUrlConfig, UIService, UISettingsDto -} from './../'; +} from '@app/shared/internal'; describe('UIService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/usages.service.spec.ts b/src/Squidex/app/shared/services/usages.service.spec.ts index f44ea471d..3faaff8c4 100644 --- a/src/Squidex/app/shared/services/usages.service.spec.ts +++ b/src/Squidex/app/shared/services/usages.service.spec.ts @@ -16,7 +16,7 @@ import { DateTime, StorageUsageDto, UsagesService -} from './../'; +} from '@app/shared/internal'; describe('UsagesService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/services/users-provider.service.spec.ts b/src/Squidex/app/shared/services/users-provider.service.spec.ts index 81a87740b..d31a57901 100644 --- a/src/Squidex/app/shared/services/users-provider.service.spec.ts +++ b/src/Squidex/app/shared/services/users-provider.service.spec.ts @@ -14,7 +14,7 @@ import { UserDto, UsersProviderService, UsersService -} from './../'; +} from '@app/shared/internal'; describe('UsersProviderService', () => { let authService: IMock; diff --git a/src/Squidex/app/shared/services/users.service.spec.ts b/src/Squidex/app/shared/services/users.service.spec.ts index 8f454b8f0..f3881dd7a 100644 --- a/src/Squidex/app/shared/services/users.service.spec.ts +++ b/src/Squidex/app/shared/services/users.service.spec.ts @@ -12,7 +12,7 @@ import { ApiUrlConfig, UserDto, UsersService -} from './../'; +} from '@app/shared/internal'; describe('UsersService', () => { beforeEach(() => { diff --git a/src/Squidex/app/shared/state/apps.state.spec.ts b/src/Squidex/app/shared/state/apps.state.spec.ts index 67d7009ed..c963063cc 100644 --- a/src/Squidex/app/shared/state/apps.state.spec.ts +++ b/src/Squidex/app/shared/state/apps.state.spec.ts @@ -15,7 +15,7 @@ import { DateTime, DialogService, Permission -} from './../'; +} from '@app/shared/internal'; describe('AppsState', () => { const now = DateTime.now(); diff --git a/src/Squidex/app/shared/state/asset-uploader.state.spec.ts b/src/Squidex/app/shared/state/asset-uploader.state.spec.ts index b24c45891..28215cf43 100644 --- a/src/Squidex/app/shared/state/asset-uploader.state.spec.ts +++ b/src/Squidex/app/shared/state/asset-uploader.state.spec.ts @@ -10,15 +10,17 @@ import { onErrorResumeNext } from 'rxjs/operators'; import { IMock, Mock } from 'typemoq'; import { + AssetDto, + AssetReplacedDto, + AssetsService, AssetUploaderState, DialogService, ofForever, Types, Version, versioned -} from './../'; +} from '@app/shared/internal'; -import { AssetDto, AssetReplacedDto, AssetsService } from '../services/assets.service'; import { TestValues } from './_test-helpers'; describe('AssetsState', () => { diff --git a/src/Squidex/app/shared/state/asset-uploader.state.ts b/src/Squidex/app/shared/state/asset-uploader.state.ts index 58c8ac741..bbc8af196 100644 --- a/src/Squidex/app/shared/state/asset-uploader.state.ts +++ b/src/Squidex/app/shared/state/asset-uploader.state.ts @@ -18,8 +18,8 @@ import { Types } from '@app/framework'; -import { AuthService } from '../services/auth.service'; import { AssetDto, AssetsService } from './../services/assets.service'; +import { AuthService } from './../services/auth.service'; import { AppsState } from './apps.state'; import { AssetsState } from './assets.state'; diff --git a/src/Squidex/app/shared/state/assets.state.spec.ts b/src/Squidex/app/shared/state/assets.state.spec.ts index 0cfd5a8ab..17f604219 100644 --- a/src/Squidex/app/shared/state/assets.state.spec.ts +++ b/src/Squidex/app/shared/state/assets.state.spec.ts @@ -15,7 +15,7 @@ import { AssetsState, DialogService, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/backups.state.spec.ts b/src/Squidex/app/shared/state/backups.state.spec.ts index e5f597be0..db6bcfccd 100644 --- a/src/Squidex/app/shared/state/backups.state.spec.ts +++ b/src/Squidex/app/shared/state/backups.state.spec.ts @@ -15,7 +15,7 @@ import { BackupsState, DateTime, DialogService -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/clients.state.spec.ts b/src/Squidex/app/shared/state/clients.state.spec.ts index 30325bdfb..3199673cb 100644 --- a/src/Squidex/app/shared/state/clients.state.spec.ts +++ b/src/Squidex/app/shared/state/clients.state.spec.ts @@ -14,7 +14,7 @@ import { ClientsState, DialogService, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/comments.state.spec.ts b/src/Squidex/app/shared/state/comments.state.spec.ts index a26d15d56..54fdf9e3e 100644 --- a/src/Squidex/app/shared/state/comments.state.spec.ts +++ b/src/Squidex/app/shared/state/comments.state.spec.ts @@ -16,7 +16,7 @@ import { DialogService, ImmutableArray, Version -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/contents.forms.spec.ts b/src/Squidex/app/shared/state/contents.forms.spec.ts index 7f7d11b04..5190bee57 100644 --- a/src/Squidex/app/shared/state/contents.forms.spec.ts +++ b/src/Squidex/app/shared/state/contents.forms.spec.ts @@ -5,12 +5,11 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { DateTime } from '@app/framework'; - import { ArrayFieldPropertiesDto, AssetsFieldPropertiesDto, BooleanFieldPropertiesDto, + DateTime, DateTimeFieldPropertiesDto, FieldDefaultValue, FieldFormatter, @@ -25,7 +24,7 @@ import { SchemaPropertiesDto, StringFieldPropertiesDto, TagsFieldPropertiesDto -} from './../'; +} from '@app/shared/internal'; describe('SchemaDetailsDto', () => { it('should return label as display name', () => { diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index 8883ea1b2..d7e85a301 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -14,7 +14,7 @@ import { ContributorsState, DialogService, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/filter.state.spec.ts b/src/Squidex/app/shared/state/filter.state.spec.ts index 24840bdaf..c5b3190bb 100644 --- a/src/Squidex/app/shared/state/filter.state.spec.ts +++ b/src/Squidex/app/shared/state/filter.state.spec.ts @@ -9,7 +9,7 @@ import { FilterState, LanguageDto, Sorting -} from './../'; +} from '@app/shared/internal'; describe('FilterState', () => { let query: string | undefined; diff --git a/src/Squidex/app/shared/state/filter.state.ts b/src/Squidex/app/shared/state/filter.state.ts index a326ff01d..769b5d882 100644 --- a/src/Squidex/app/shared/state/filter.state.ts +++ b/src/Squidex/app/shared/state/filter.state.ts @@ -10,9 +10,9 @@ import { distinctUntilChanged, map } from 'rxjs/internal/operators'; import { State, Types } from '@app/framework'; -import { LanguageDto } from '../services/languages.service'; +import { LanguageDto } from './../services/languages.service'; -import { RootFieldDto } from '../services/schemas.service'; +import { RootFieldDto } from './../services/schemas.service'; interface Snapshot { // The current language. diff --git a/src/Squidex/app/shared/state/languages.forms.ts b/src/Squidex/app/shared/state/languages.forms.ts index 776ea1724..1840c123c 100644 --- a/src/Squidex/app/shared/state/languages.forms.ts +++ b/src/Squidex/app/shared/state/languages.forms.ts @@ -9,7 +9,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Form } from '@app/framework'; -import { LanguageDto } from '../services/languages.service'; +import { LanguageDto } from './../services/languages.service'; export class EditLanguageForm extends Form { constructor(formBuilder: FormBuilder) { diff --git a/src/Squidex/app/shared/state/languages.state.spec.ts b/src/Squidex/app/shared/state/languages.state.spec.ts index a4ab191cd..3a4f6dc50 100644 --- a/src/Squidex/app/shared/state/languages.state.spec.ts +++ b/src/Squidex/app/shared/state/languages.state.spec.ts @@ -17,7 +17,7 @@ import { LanguagesService, LanguagesState, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/patterns.state.spec.ts b/src/Squidex/app/shared/state/patterns.state.spec.ts index eb4179837..b0de52e42 100644 --- a/src/Squidex/app/shared/state/patterns.state.spec.ts +++ b/src/Squidex/app/shared/state/patterns.state.spec.ts @@ -14,7 +14,7 @@ import { PatternsService, PatternsState, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/plans.state.spec.ts b/src/Squidex/app/shared/state/plans.state.spec.ts index 152511812..100a5be6f 100644 --- a/src/Squidex/app/shared/state/plans.state.spec.ts +++ b/src/Squidex/app/shared/state/plans.state.spec.ts @@ -15,7 +15,7 @@ import { PlansService, PlansState, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/queries.spec.ts b/src/Squidex/app/shared/state/queries.spec.ts index fa174c260..7a469b9b1 100644 --- a/src/Squidex/app/shared/state/queries.spec.ts +++ b/src/Squidex/app/shared/state/queries.spec.ts @@ -12,7 +12,7 @@ import { Queries, Query, UIState -} from './../'; +} from '@app/shared/internal'; describe('Queries', () => { const prefix = 'schemas.my-schema'; diff --git a/src/Squidex/app/shared/state/roles.state.spec.ts b/src/Squidex/app/shared/state/roles.state.spec.ts index 91680effb..d3326a6f5 100644 --- a/src/Squidex/app/shared/state/roles.state.spec.ts +++ b/src/Squidex/app/shared/state/roles.state.spec.ts @@ -14,7 +14,7 @@ import { RolesService, RolesState, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/rule-events.state.spec.ts b/src/Squidex/app/shared/state/rule-events.state.spec.ts index 50ca944f0..764654588 100644 --- a/src/Squidex/app/shared/state/rule-events.state.spec.ts +++ b/src/Squidex/app/shared/state/rule-events.state.spec.ts @@ -15,7 +15,7 @@ import { RuleEventsDto, RuleEventsState, RulesService -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index 2f0a13dcf..c296c968b 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -15,7 +15,7 @@ import { RuleDto, RulesService, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/schemas.forms.ts b/src/Squidex/app/shared/state/schemas.forms.ts index a7aebd973..23846fbf7 100644 --- a/src/Squidex/app/shared/state/schemas.forms.ts +++ b/src/Squidex/app/shared/state/schemas.forms.ts @@ -14,7 +14,7 @@ import { value$ } from '@app/framework'; -import { AddFieldDto } from '../services/schemas.service'; +import { AddFieldDto } from './../services/schemas.service'; import { createProperties } from './../services/schemas.types'; diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index ece6fddae..7d5229824 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -22,7 +22,7 @@ import { SchemasService, UpdateSchemaCategoryDto, versioned -} from './../'; +} from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/app/shared/state/ui.state.spec.ts b/src/Squidex/app/shared/state/ui.state.spec.ts index 8ca7da532..3502b656a 100644 --- a/src/Squidex/app/shared/state/ui.state.spec.ts +++ b/src/Squidex/app/shared/state/ui.state.spec.ts @@ -8,7 +8,7 @@ import { of } from 'rxjs'; import { IMock, It, Mock, Times } from 'typemoq'; -import { UIService, UIState } from './../'; +import { UIService, UIState } from '@app/shared/internal'; import { TestValues } from './_test-helpers'; diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index 47045544d..d1e634ee7 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -2741,7 +2741,7 @@ "dependencies": { "jsesc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, @@ -3546,6 +3546,12 @@ "safe-buffer": "^5.0.1" } }, + "circular-dependency-plugin": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz", + "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -4178,7 +4184,7 @@ }, "json5": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { @@ -10663,7 +10669,7 @@ }, "node-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" }, "node-forge": { @@ -11080,7 +11086,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -15320,7 +15326,7 @@ "dependencies": { "json5": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { @@ -18603,7 +18609,7 @@ }, "whatwg-fetch": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" }, "which": { diff --git a/src/Squidex/package.json b/src/Squidex/package.json index baf455083..539bdd9da 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -62,6 +62,7 @@ "angular2-template-loader": "0.6.2", "awesome-typescript-loader": "5.2.1", "babel-core": "6.26.3", + "circular-dependency-plugin": "5.0.2", "codelyzer": "5.0.1", "cpx": "1.5.0", "css-loader": "2.1.1", From 2493ca400fa1a20fdb07d36f80dd33824d09af7f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 4 May 2019 22:35:45 +0200 Subject: [PATCH 17/20] Move business logic from service to states. --- .../app/shared/services/apps.service.spec.ts | 14 ++++-- .../app/shared/services/apps.service.ts | 27 ++++------ .../app/shared/services/rules.service.spec.ts | 34 +++++-------- .../app/shared/services/rules.service.ts | 38 +++++--------- .../shared/services/schemas.service.spec.ts | 27 +++++----- .../app/shared/services/schemas.service.ts | 49 ++++++------------- src/Squidex/app/shared/state/_test-helpers.ts | 3 -- .../app/shared/state/apps.state.spec.ts | 12 ++--- src/Squidex/app/shared/state/apps.state.ts | 22 ++++++++- .../shared/state/asset-uploader.state.spec.ts | 26 +++++----- .../app/shared/state/comments.state.spec.ts | 30 ++++++------ .../shared/state/contributors.state.spec.ts | 6 +-- .../app/shared/state/rules.state.spec.ts | 10 ++-- src/Squidex/app/shared/state/rules.state.ts | 39 ++++++++++++--- .../app/shared/state/schemas.state.spec.ts | 17 +++---- src/Squidex/app/shared/state/schemas.state.ts | 29 +++++++++-- src/Squidex/package-lock.json | 24 ++++----- src/Squidex/package.json | 8 +-- src/Squidex/tslint.json | 4 +- 19 files changed, 217 insertions(+), 202 deletions(-) diff --git a/src/Squidex/app/shared/services/apps.service.spec.ts b/src/Squidex/app/shared/services/apps.service.spec.ts index 75f064593..65d86a946 100644 --- a/src/Squidex/app/shared/services/apps.service.spec.ts +++ b/src/Squidex/app/shared/services/apps.service.spec.ts @@ -11,6 +11,7 @@ import { inject, TestBed } from '@angular/core/testing'; import { AnalyticsService, ApiUrlConfig, + AppCreatedDto, AppDto, AppsService, DateTime, @@ -18,8 +19,6 @@ import { } from '@app/shared/internal'; describe('AppsService', () => { - const now = DateTime.now(); - beforeEach(() => { TestBed.configureTestingModule({ imports: [ @@ -84,9 +83,9 @@ describe('AppsService', () => { const dto = { name: 'new-app' }; - let app: AppDto; + let app: AppCreatedDto; - appsService.postApp(dto, now).subscribe(result => { + appsService.postApp(dto).subscribe(result => { app = result; }); @@ -102,7 +101,12 @@ describe('AppsService', () => { planUpgrade: 'Enterprise' }); - expect(app!).toEqual(new AppDto('123', dto.name, [new Permission('Reader')], now, now, 'Basic', 'Enterprise')); + expect(app!).toEqual({ + id: '123', + permissions: ['Reader'], + planName: 'Basic', + planUpgrade: 'Enterprise' + }); })); it('should make delete request to archive app', diff --git a/src/Squidex/app/shared/services/apps.service.ts b/src/Squidex/app/shared/services/apps.service.ts index 382a14eeb..c80d71dc4 100644 --- a/src/Squidex/app/shared/services/apps.service.ts +++ b/src/Squidex/app/shared/services/apps.service.ts @@ -38,6 +38,13 @@ export interface CreateAppDto { readonly template?: string; } +export interface AppCreatedDto { + readonly id: string; + readonly permissions: string[]; + readonly planName?: string; + readonly planUpgrade?: string; +} + @Injectable() export class AppsService { constructor( @@ -70,26 +77,10 @@ export class AppsService { pretifyError('Failed to load apps. Please reload.')); } - public postApp(dto: CreateAppDto, now?: DateTime): Observable { + public postApp(dto: CreateAppDto): Observable { const url = this.apiUrl.buildUrl('api/apps'); - return this.http.post(url, dto).pipe( - map(body => { - now = now || DateTime.now(); - - const permissions = (body.permissions).map(x => new Permission(x)); - - const app = new AppDto( - body.id, - dto.name, - permissions, - now, - now, - body.planName, - body.planUpgrade); - - return app; - }), + return this.http.post(url, dto).pipe( tap(() => { this.analytics.trackEvent('App', 'Created', dto.name); }), diff --git a/src/Squidex/app/shared/services/rules.service.spec.ts b/src/Squidex/app/shared/services/rules.service.spec.ts index 955954bb4..7cc53c635 100644 --- a/src/Squidex/app/shared/services/rules.service.spec.ts +++ b/src/Squidex/app/shared/services/rules.service.spec.ts @@ -19,12 +19,12 @@ import { RuleEventDto, RuleEventsDto, RulesService, - Version + Version, + Versioned } from '@app/shared/internal'; +import { RuleCreatedDto } from './rules.service'; describe('RulesService', () => { - const now = DateTime.now(); - const user = 'me'; const version = new Version('1'); beforeEach(() => { @@ -179,9 +179,9 @@ describe('RulesService', () => { } }; - let rule: RuleDto; + let rule: Versioned; - rulesService.postRule('my-app', dto, user, now).subscribe(result => { + rulesService.postRule('my-app', dto).subscribe(result => { rule = result; }); @@ -190,28 +190,18 @@ describe('RulesService', () => { expect(req.request.method).toEqual('POST'); expect(req.request.headers.get('If-Match')).toBeNull(); - req.flush({ id: 'id1', sharedSecret: 'token1', schemaId: 'schema1' }, { + req.flush({ id: 'id1' }, { headers: { etag: '1' } }); - expect(rule!).toEqual( - new RuleDto('id1', user, user, now, now, - version, - true, - { - param1: 1, - param2: 2, - triggerType: 'ContentChanged' - }, - 'ContentChanged', - { - param3: 3, - param4: 4, - actionType: 'Webhook' - }, - 'Webhook')); + expect(rule!).toEqual({ + payload: { + id: 'id1' + }, + version + }); })); it('should make put request to update rule', diff --git a/src/Squidex/app/shared/services/rules.service.ts b/src/Squidex/app/shared/services/rules.service.ts index 820f3152b..7af1acfb7 100644 --- a/src/Squidex/app/shared/services/rules.service.ts +++ b/src/Squidex/app/shared/services/rules.service.ts @@ -15,6 +15,7 @@ import { ApiUrlConfig, DateTime, HTTP, + mapVersioned, Model, pretifyError, ResultSet, @@ -109,16 +110,18 @@ export class RuleEventDto extends Model { } } -export interface CreateRuleDto { - readonly trigger: any; - readonly action: any; +export interface UpsertRuleDto { + readonly trigger: RuleAction; + readonly action: RuleAction; } -export interface UpdateRuleDto { - readonly trigger?: any; - readonly action?: any; +export interface RuleCreatedDto { + readonly id: string; } +export type RuleAction = { actionType: string } & any; +export type RuleTrigger = { triggerType: string } & any; + @Injectable() export class RulesService { constructor( @@ -190,33 +193,18 @@ export class RulesService { pretifyError('Failed to load Rules. Please reload.')); } - public postRule(appName: string, dto: CreateRuleDto, user: string, now: DateTime): Observable { + public postRule(appName: string, dto: UpsertRuleDto): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/rules`); - return HTTP.postVersioned(this.http, url, dto).pipe( - map(({ version, payload }) => { - const body = payload.body; - - return new RuleDto( - body.id, - user, - user, - now, - now, - version, - true, - dto.trigger, - dto.trigger.triggerType, - dto.action, - dto.action.actionType); - }), + return HTTP.postVersioned(this.http, url, dto).pipe( + mapVersioned(({ body }) => body!), tap(() => { this.analytics.trackEvent('Rule', 'Created', appName); }), pretifyError('Failed to create rule. Please reload.')); } - public putRule(appName: string, id: string, dto: UpdateRuleDto, version: Version): Observable> { + public putRule(appName: string, id: string, dto: Partial, version: Version): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/rules/${id}`); return HTTP.putVersioned(this.http, url, dto, version).pipe( diff --git a/src/Squidex/app/shared/services/schemas.service.spec.ts b/src/Squidex/app/shared/services/schemas.service.spec.ts index c0405c407..21e69270d 100644 --- a/src/Squidex/app/shared/services/schemas.service.spec.ts +++ b/src/Squidex/app/shared/services/schemas.service.spec.ts @@ -9,11 +9,9 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/ import { inject, TestBed } from '@angular/core/testing'; import { - AddFieldDto, AnalyticsService, ApiUrlConfig, createProperties, - CreateSchemaDto, DateTime, FieldDto, NestedFieldDto, @@ -22,12 +20,12 @@ import { SchemaDto, SchemaPropertiesDto, SchemasService, - Version + Version, + Versioned } from '@app/shared/internal'; +import { SchemaCreatedDto } from './schemas.service'; describe('SchemasService', () => { - const now = DateTime.now(); - const user = 'me'; const version = new Version('1'); beforeEach(() => { @@ -330,11 +328,11 @@ describe('SchemasService', () => { it('should make post request to create schema', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new CreateSchemaDto('name', undefined, undefined, true); + const dto = { name: 'name' }; - let schema: SchemaDetailsDto; + let schema: Versioned; - schemasService.postSchema('my-app', dto, user, now).subscribe(result => { + schemasService.postSchema('my-app', dto).subscribe(result => { schema = result; }); @@ -347,11 +345,16 @@ describe('SchemasService', () => { id: '1' }, { headers: { - etag: '2' + etag: '1' } }); - expect(schema!).toEqual(new SchemaDetailsDto('1', dto.name, '', new SchemaPropertiesDto(), true, false, now, user, now, user, new Version('2'), [], {}, {})); + expect(schema!).toEqual({ + payload: { + id: '1' + }, + version + }); })); it('should make put request to update schema', @@ -417,7 +420,7 @@ describe('SchemasService', () => { it('should make post request to add field', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new AddFieldDto('name', 'invariant', createProperties('Number')); + const dto = { name: 'name', partitioning: 'invariant', properties: createProperties('Number') }; let field: FieldDto; @@ -464,7 +467,7 @@ describe('SchemasService', () => { it('should make post request to add nested field', inject([SchemasService, HttpTestingController], (schemasService: SchemasService, httpMock: HttpTestingController) => { - const dto = new AddFieldDto('name', 'invariant', createProperties('Number')); + const dto = { name: 'name', partitioning: 'invariant', properties: createProperties('Number') }; let field: FieldDto; diff --git a/src/Squidex/app/shared/services/schemas.service.ts b/src/Squidex/app/shared/services/schemas.service.ts index b3da2159d..f8b08abda 100644 --- a/src/Squidex/app/shared/services/schemas.service.ts +++ b/src/Squidex/app/shared/services/schemas.service.ts @@ -171,23 +171,21 @@ export class SchemaPropertiesDto { } } -export class AddFieldDto { - constructor( - public readonly name: string, - public readonly partitioning: string, - public readonly properties: FieldPropertiesDto - ) { - } +export interface AddFieldDto { + readonly name: string; + readonly partitioning: string; + readonly properties: FieldPropertiesDto; } -export class CreateSchemaDto { - constructor( - public readonly name: string, - public readonly fields?: RootFieldDto[], - public readonly properties?: SchemaPropertiesDto, - public readonly isSingleton?: boolean - ) { - } +export interface CreateSchemaDto { + readonly name: string; + readonly fields?: RootFieldDto[]; + readonly properties?: SchemaPropertiesDto; + readonly isSingleton?: boolean; +} + +export interface SchemaCreatedDto { + readonly id: string; } export interface UpdateSchemaCategoryDto { @@ -303,28 +301,11 @@ export class SchemasService { pretifyError('Failed to load schema. Please reload.')); } - public postSchema(appName: string, dto: CreateSchemaDto, user: string, now: DateTime): Observable { + public postSchema(appName: string, dto: CreateSchemaDto): Observable> { const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas`); return HTTP.postVersioned(this.http, url, dto).pipe( - map(({ version, payload }) => { - const body = payload.body; - - now = now || DateTime.now(); - - const schema = new SchemaDetailsDto( - body.id, - dto.name, '', - dto.properties || new SchemaPropertiesDto(), - dto.isSingleton === true, - false, - now, user, - now, user, - version, - dto.fields || []); - - return schema; - }), + mapVersioned(({ body }) => body!), tap(() => { this.analytics.trackEvent('Schema', 'Created', appName); }), diff --git a/src/Squidex/app/shared/state/_test-helpers.ts b/src/Squidex/app/shared/state/_test-helpers.ts index 69d6e55ce..d6a1c8f62 100644 --- a/src/Squidex/app/shared/state/_test-helpers.ts +++ b/src/Squidex/app/shared/state/_test-helpers.ts @@ -20,7 +20,6 @@ const creation = DateTime.today().addDays(-2); const creator = 'me'; const modified = DateTime.now().addDays(-1); const modifier = 'now-me'; -const now = DateTime.now(); const version = new Version('1'); const newVersion = new Version('2'); @@ -45,8 +44,6 @@ export const TestValues = { creator, modified, modifier, - now, newVersion, - userId: modifier, version }; \ No newline at end of file diff --git a/src/Squidex/app/shared/state/apps.state.spec.ts b/src/Squidex/app/shared/state/apps.state.spec.ts index c963063cc..aedec3170 100644 --- a/src/Squidex/app/shared/state/apps.state.spec.ts +++ b/src/Squidex/app/shared/state/apps.state.spec.ts @@ -88,9 +88,9 @@ describe('AppsState', () => { const request = { ...newApp }; appsService.setup(x => x.postApp(request)) - .returns(() => of(newApp)).verifiable(); + .returns(() => of({ ...newApp, permissions: ['Owner'] })).verifiable(); - appsState.create(request).subscribe(); + appsState.create(request, now).subscribe(); expect(appsState.snapshot.apps.values).toEqual([newApp, ...oldApps]); }); @@ -99,12 +99,12 @@ describe('AppsState', () => { const request = { ...newApp }; appsService.setup(x => x.postApp(request)) - .returns(() => of(newApp)).verifiable(); + .returns(() => of({ ...newApp, permissions: ['Owner'] })).verifiable(); appsService.setup(x => x.deleteApp(newApp.name)) .returns(() => of({})).verifiable(); - appsState.create(request).subscribe(); + appsState.create(request, now).subscribe(); const appsAfterCreate = appsState.snapshot.apps.values; @@ -120,12 +120,12 @@ describe('AppsState', () => { const request = { ...newApp }; appsService.setup(x => x.postApp(request)) - .returns(() => of(newApp)).verifiable(); + .returns(() => of({ ...newApp, permissions: ['Owner'] })).verifiable(); appsService.setup(x => x.deleteApp(newApp.name)) .returns(() => of({})).verifiable(); - appsState.create(request).subscribe(); + appsState.create(request, now).subscribe(); appsState.select(newApp.name).subscribe(); appsState.delete(newApp.name).subscribe(); diff --git a/src/Squidex/app/shared/state/apps.state.ts b/src/Squidex/app/shared/state/apps.state.ts index 2a97377cd..c3bf22d0a 100644 --- a/src/Squidex/app/shared/state/apps.state.ts +++ b/src/Squidex/app/shared/state/apps.state.ts @@ -10,13 +10,16 @@ import { Observable, of } from 'rxjs'; import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { + DateTime, DialogService, ImmutableArray, + Permission, shareSubscribed, State } from '@app/framework'; import { + AppCreatedDto, AppDto, AppsService, CreateAppDto @@ -79,11 +82,11 @@ export class AppsState extends State { shareSubscribed(this.dialogs)); } - public create(request: CreateAppDto): Observable { + public create(request: CreateAppDto, now?: DateTime): Observable { return this.appsService.postApp(request).pipe( tap(payload => { this.next(s => { - const apps = s.apps.push(payload).sortByStringAsc(x => x.name); + const apps = s.apps.push(createApp(request, payload, now)).sortByStringAsc(x => x.name); return { ...s, apps }; }); @@ -104,4 +107,19 @@ export class AppsState extends State { }), shareSubscribed(this.dialogs)); } +} + +function createApp(request: CreateAppDto, response: AppCreatedDto, now?: DateTime) { + now = now || DateTime.now(); + + const app = new AppDto( + response.id, + request.name, + response.permissions.map(x => new Permission(x)), + now, + now, + response.planName, + response.planUpgrade); + + return app; } \ No newline at end of file diff --git a/src/Squidex/app/shared/state/asset-uploader.state.spec.ts b/src/Squidex/app/shared/state/asset-uploader.state.spec.ts index 28215cf43..0a184eb31 100644 --- a/src/Squidex/app/shared/state/asset-uploader.state.spec.ts +++ b/src/Squidex/app/shared/state/asset-uploader.state.spec.ts @@ -31,9 +31,7 @@ describe('AssetsState', () => { creator, creation, modified, - modifier, - now, - userId + modifier } = TestValues; let assetsService: IMock; @@ -74,10 +72,10 @@ describe('AssetsState', () => { it('should create initial state when uploading file', () => { const file: File = { name: 'my-file' }; - assetsService.setup(x => x.uploadFile(app, file, userId, now)) + assetsService.setup(x => x.uploadFile(app, file, modifier, modified)) .returns(() => never()).verifiable(); - assetUploader.uploadFile(file, undefined, now).subscribe(); + assetUploader.uploadFile(file, undefined, modified).subscribe(); const upload = assetUploader.snapshot.uploads.at(0); @@ -88,10 +86,10 @@ describe('AssetsState', () => { it('should update progress when uploading file makes progress', () => { const file: File = { name: 'my-file' }; - assetsService.setup(x => x.uploadFile(app, file, userId, now)) + assetsService.setup(x => x.uploadFile(app, file, modifier, modified)) .returns(() => ofForever(10, 20)).verifiable(); - assetUploader.uploadFile(file, undefined, now).subscribe(); + assetUploader.uploadFile(file, undefined, modified).subscribe(); const upload = assetUploader.snapshot.uploads.at(0); @@ -102,10 +100,10 @@ describe('AssetsState', () => { it('should update status when uploading file failed', () => { const file: File = { name: 'my-file' }; - assetsService.setup(x => x.uploadFile(app, file, userId, now)) + assetsService.setup(x => x.uploadFile(app, file, modifier, modified)) .returns(() => throwError('Error')).verifiable(); - assetUploader.uploadFile(file, undefined, now).pipe(onErrorResumeNext()).subscribe(); + assetUploader.uploadFile(file, undefined, modified).pipe(onErrorResumeNext()).subscribe(); const upload = assetUploader.snapshot.uploads.at(0); @@ -116,12 +114,12 @@ describe('AssetsState', () => { it('should update status when uploading file completes', (cb) => { const file: File = { name: 'my-file' }; - assetsService.setup(x => x.uploadFile(app, file, userId, now)) + assetsService.setup(x => x.uploadFile(app, file, modifier, modified)) .returns(() => of(10, 20, asset)).verifiable(); let uploadedAsset: AssetDto; - assetUploader.uploadFile(file, undefined, now).subscribe(dto => { + assetUploader.uploadFile(file, undefined, modified).subscribe(dto => { if (Types.is(dto, AssetDto)) { uploadedAsset = dto; } @@ -142,7 +140,7 @@ describe('AssetsState', () => { assetsService.setup(x => x.replaceFile(app, asset.id, file, asset.version)) .returns(() => never()).verifiable(); - assetUploader.uploadAsset(asset, file, now).subscribe(); + assetUploader.uploadAsset(asset, file, modified).subscribe(); const upload = assetUploader.snapshot.uploads.at(0); @@ -156,7 +154,7 @@ describe('AssetsState', () => { assetsService.setup(x => x.replaceFile(app, asset.id, file, asset.version)) .returns(() => ofForever(10, 20)).verifiable(); - assetUploader.uploadAsset(asset, file, now).subscribe(); + assetUploader.uploadAsset(asset, file, modified).subscribe(); const upload = assetUploader.snapshot.uploads.at(0); @@ -170,7 +168,7 @@ describe('AssetsState', () => { assetsService.setup(x => x.replaceFile(app, asset.id, file, asset.version)) .returns(() => throwError('Error')).verifiable(); - assetUploader.uploadAsset(asset, file, now).pipe(onErrorResumeNext()).subscribe(); + assetUploader.uploadAsset(asset, file, modified).pipe(onErrorResumeNext()).subscribe(); const upload = assetUploader.snapshot.uploads.at(0); diff --git a/src/Squidex/app/shared/state/comments.state.spec.ts b/src/Squidex/app/shared/state/comments.state.spec.ts index 54fdf9e3e..05169f4e3 100644 --- a/src/Squidex/app/shared/state/comments.state.spec.ts +++ b/src/Squidex/app/shared/state/comments.state.spec.ts @@ -25,14 +25,14 @@ describe('CommentsState', () => { app, appsState, creator, - now + modified } = TestValues; const commentsId = 'my-comments'; const oldComments = new CommentsDto([ - new CommentDto('1', now, 'text1', creator), - new CommentDto('2', now, 'text2', creator) + new CommentDto('1', modified, 'text1', creator), + new CommentDto('2', modified, 'text2', creator) ], [], [], new Version('1')); let dialogs: IMock; @@ -53,9 +53,9 @@ describe('CommentsState', () => { describe('Loading', () => { it('should load and merge comments', () => { const newComments = new CommentsDto([ - new CommentDto('3', now, 'text3', creator) + new CommentDto('3', modified, 'text3', creator) ], [ - new CommentDto('2', now, 'text2_2', creator) + new CommentDto('2', modified, 'text2_2', creator) ], ['1'], new Version('2')); commentsService.setup(x => x.getComments(app, commentsId, new Version('-1'))) @@ -69,8 +69,8 @@ describe('CommentsState', () => { expect(commentsState.snapshot.isLoaded).toBeTruthy(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('2', now, 'text2_2', creator), - new CommentDto('3', now, 'text3', creator) + new CommentDto('2', modified, 'text2_2', creator), + new CommentDto('3', modified, 'text3', creator) ])); }); }); @@ -84,7 +84,7 @@ describe('CommentsState', () => { }); it('should add comment to snapshot when created', () => { - const newComment = new CommentDto('3', now, 'text3', creator); + const newComment = new CommentDto('3', modified, 'text3', creator); const request = { text: 'text3' }; @@ -94,9 +94,9 @@ describe('CommentsState', () => { commentsState.create('text3').subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', creator), - new CommentDto('2', now, 'text2', creator), - new CommentDto('3', now, 'text3', creator) + new CommentDto('1', modified, 'text1', creator), + new CommentDto('2', modified, 'text2', creator), + new CommentDto('3', modified, 'text3', creator) ])); }); @@ -106,11 +106,11 @@ describe('CommentsState', () => { commentsService.setup(x => x.putComment(app, commentsId, '2', request)) .returns(() => of({})).verifiable(); - commentsState.update(oldComments.createdComments[1], 'text2_2', now).subscribe(); + commentsState.update(oldComments.createdComments[1], 'text2_2', modified).subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', creator), - new CommentDto('2', now, 'text2_2', creator) + new CommentDto('1', modified, 'text1', creator), + new CommentDto('2', modified, 'text2_2', creator) ])); }); @@ -121,7 +121,7 @@ describe('CommentsState', () => { commentsState.delete(oldComments.createdComments[1]).subscribe(); expect(commentsState.snapshot.comments).toEqual(ImmutableArray.of([ - new CommentDto('1', now, 'text1', creator) + new CommentDto('1', modified, 'text1', creator) ])); }); }); diff --git a/src/Squidex/app/shared/state/contributors.state.spec.ts b/src/Squidex/app/shared/state/contributors.state.spec.ts index d7e85a301..f103f4bad 100644 --- a/src/Squidex/app/shared/state/contributors.state.spec.ts +++ b/src/Squidex/app/shared/state/contributors.state.spec.ts @@ -23,14 +23,14 @@ describe('ContributorsState', () => { app, appsState, authService, + modifier, newVersion, - userId, version } = TestValues; const oldContributors = [ new ContributorDto('id1', 'Developer'), - new ContributorDto(userId, 'Developer') + new ContributorDto(modifier, 'Developer') ]; let dialogs: IMock; @@ -109,7 +109,7 @@ describe('ContributorsState', () => { }); it('should update contributor in snapshot when assigned and already added', () => { - const newContributor = new ContributorDto(userId, 'Owner'); + const newContributor = new ContributorDto(modifier, 'Owner'); const request = { ...newContributor }; const response = { contributorId: newContributor.contributorId, isCreated: true }; diff --git a/src/Squidex/app/shared/state/rules.state.spec.ts b/src/Squidex/app/shared/state/rules.state.spec.ts index c296c968b..6b8a8cdd5 100644 --- a/src/Squidex/app/shared/state/rules.state.spec.ts +++ b/src/Squidex/app/shared/state/rules.state.spec.ts @@ -87,14 +87,14 @@ describe('RulesState', () => { }); it('should add rule to snapshot when created', () => { - const newRule = new RuleDto('id3', creator, creator, creation, creation, version, false, {}, 'trigger3', {}, 'action3'); + const newRule = new RuleDto('id3', modifier, modifier, modified, modified, version, true, { value: 3 }, 'trigger3', { value: 1 }, 'action3'); - const request = { action: {}, trigger: {} }; + const request = { trigger: { triggerType: 'trigger3', value: 3 }, action: { actionType: 'action3', value: 1 } }; - rulesService.setup(x => x.postRule(app, request, modifier, creation)) - .returns(() => of(newRule)); + rulesService.setup(x => x.postRule(app, request)) + .returns(() => of(versioned(version, { id: 'id3' }))); - rulesState.create(request, creation).subscribe(); + rulesState.create(request, modified).subscribe(); expect(rulesState.snapshot.rules.values).toEqual([...oldRules, newRule]); }); diff --git a/src/Squidex/app/shared/state/rules.state.ts b/src/Squidex/app/shared/state/rules.state.ts index e75b71f6c..d01cb1233 100644 --- a/src/Squidex/app/shared/state/rules.state.ts +++ b/src/Squidex/app/shared/state/rules.state.ts @@ -15,16 +15,18 @@ import { ImmutableArray, shareSubscribed, State, - Version + Version, + Versioned } from '@app/framework'; import { AuthService} from './../services/auth.service'; import { AppsState } from './apps.state'; import { - CreateRuleDto, + RuleCreatedDto, RuleDto, - RulesService + RulesService, + UpsertRuleDto } from './../services/rules.service'; interface Snapshot { @@ -76,11 +78,11 @@ export class RulesState extends State { shareSubscribed(this.dialogs)); } - public create(request: CreateRuleDto, now?: DateTime): Observable { - return this.rulesService.postRule(this.appName, request, this.user, now || DateTime.now()).pipe( - tap(rule => { + public create(request: UpsertRuleDto, now?: DateTime): Observable { + return this.rulesService.postRule(this.appName, request).pipe( + tap(response => { this.next(s => { - const rules = s.rules.push(rule); + const rules = s.rules.push(createRule(request, response, this.user, now)); return { ...s, rules }; }); @@ -178,3 +180,26 @@ const setEnabled = (rule: RuleDto, isEnabled: boolean, user: string, version: Ve lastModifiedBy: user, version }); + +function createRule(request: UpsertRuleDto, { payload, version }: Versioned, user: string, now?: DateTime) { + now = now || DateTime.now(); + + const { triggerType, ...trigger } = request.trigger; + + const { actionType, ...action } = request.action; + + const rule = new RuleDto( + payload.id, + user, + user, + now, + now, + version, + true, + trigger, + triggerType, + action, + actionType); + + return rule; +} \ No newline at end of file diff --git a/src/Squidex/app/shared/state/schemas.state.spec.ts b/src/Squidex/app/shared/state/schemas.state.spec.ts index 7d5229824..5b084eab0 100644 --- a/src/Squidex/app/shared/state/schemas.state.spec.ts +++ b/src/Squidex/app/shared/state/schemas.state.spec.ts @@ -11,14 +11,13 @@ import { IMock, It, Mock, Times } from 'typemoq'; import { SchemasState } from './schemas.state'; import { - AddFieldDto, createProperties, - CreateSchemaDto, DialogService, NestedFieldDto, RootFieldDto, SchemaDetailsDto, SchemaDto, + SchemaPropertiesDto, SchemasService, UpdateSchemaCategoryDto, versioned @@ -298,17 +297,17 @@ describe('SchemasState', () => { }); it('should add schema to snapshot when created', () => { - const request = new CreateSchemaDto('newName'); + const request = { name: 'newName' }; - const result = new SchemaDetailsDto('id4', 'newName', '', {}, false, false, modified, modifier, modified, modifier, version); + const result = new SchemaDetailsDto('id4', 'newName', '', new SchemaPropertiesDto(), false, false, modified, modifier, modified, modifier, version); - schemasService.setup(x => x.postSchema(app, request, modifier, modified)) - .returns(() => of(result)).verifiable(); + schemasService.setup(x => x.postSchema(app, request)) + .returns(() => of(versioned(version, { id: 'id4' }))).verifiable(); schemasState.create(request, modified).subscribe(); expect(schemasState.snapshot.schemas.values.length).toBe(3); - expect(schemasState.snapshot.schemas.at(2)).toBe(result); + expect(schemasState.snapshot.schemas.at(2)).toEqual(result); }); it('should remove schema from snapshot when deleted', () => { @@ -322,7 +321,7 @@ describe('SchemasState', () => { }); it('should add field and update user info when field added', () => { - const request = new AddFieldDto(field1.name, field1.partitioning, field1.properties); + const request = { ...field1 }; const newField = new RootFieldDto(3, '3', createProperties('String'), 'invariant'); @@ -338,7 +337,7 @@ describe('SchemasState', () => { }); it('should add field and update user info when nested field added', () => { - const request = new AddFieldDto(field1.name, field1.partitioning, field1.properties); + const request = { ...field1 }; const newField = new NestedFieldDto(3, '3', createProperties('String'), 2); diff --git a/src/Squidex/app/shared/state/schemas.state.ts b/src/Squidex/app/shared/state/schemas.state.ts index 6e2928ed5..b5285958b 100644 --- a/src/Squidex/app/shared/state/schemas.state.ts +++ b/src/Squidex/app/shared/state/schemas.state.ts @@ -17,7 +17,8 @@ import { shareSubscribed, State, Types, - Version + Version, + Versioned } from '@app/framework'; import { AuthService } from './../services/auth.service'; @@ -29,6 +30,7 @@ import { FieldDto, NestedFieldDto, RootFieldDto, + SchemaCreatedDto, SchemaDetailsDto, SchemaDto, SchemaPropertiesDto, @@ -136,10 +138,10 @@ export class SchemasState extends State { } public create(request: CreateSchemaDto, now?: DateTime): Observable { - return this.schemasService.postSchema(this.appName, request, this.user, now || DateTime.now()).pipe( - tap(payload => { + return this.schemasService.postSchema(this.appName, request).pipe( + tap(response => { this.next(s => { - const schemas = s.schemas.push(payload).sortByStringAsc(x => x.displayName); + const schemas = s.schemas.push(createSchema(request, response, this.user, now)).sortByStringAsc(x => x.displayName); return { ...s, schemas }; }); @@ -513,4 +515,21 @@ const pidof = (field: T) => Types.is(field, NestedFieldDto) ? field.parentId : undefined; const pid = (field?: RootFieldDto) => - field ? field.fieldId : undefined; \ No newline at end of file + field ? field.fieldId : undefined; + +function createSchema(request: CreateSchemaDto, { payload, version }: Versioned, user: string, now?: DateTime) { + now = now || DateTime.now(); + + const schema = new SchemaDetailsDto( + payload.id, + request.name, '', + request.properties || new SchemaPropertiesDto(), + request.isSingleton === true, + false, + now, user, + now, user, + version, + request.fields || []); + + return schema; +} \ No newline at end of file diff --git a/src/Squidex/package-lock.json b/src/Squidex/package-lock.json index d1e634ee7..3051cf82b 100644 --- a/src/Squidex/package-lock.json +++ b/src/Squidex/package-lock.json @@ -1670,9 +1670,9 @@ "dev": true }, "@types/node": { - "version": "11.13.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz", - "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.0.tgz", + "integrity": "sha512-Jrb/x3HT4PTJp6a4avhmJCDEVrPdqLfl3e8GGMbpkGGdwAV5UGlIs4vVEfsHHfylZVOKZWpOqmqFH8CbfOZ6kg==", "dev": true }, "@types/prop-types": { @@ -1688,9 +1688,9 @@ "dev": true }, "@types/react": { - "version": "16.8.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.14.tgz", - "integrity": "sha512-26tFVJ1omGmzIdFTFmnC5zhz1GTaqCjxgUxV4KzWvsybF42P7/j4RBn6UeO3KbHPXqKWZszMXMoI65xIWm954A==", + "version": "16.8.16", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.16.tgz", + "integrity": "sha512-A0+6kS6zwPtvubOLiCJmZ8li5bm3wKIkoKV0h3RdMDOnCj9cYkUnj3bWbE03/lcICdQmwBmUfoFiHeNhbFiyHQ==", "dev": true, "requires": { "@types/prop-types": "*", @@ -15023,9 +15023,9 @@ } }, "ts-loader": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.4.tgz", - "integrity": "sha512-haLwWMts/tCruBFbLUWOR9hZezZ89TMW3EntrAEtYARDnPZSQt6dPA5tN3fvlsmUIYXVWDHO5SUhw8ndAomVlw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz", + "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==", "dev": true, "requires": { "chalk": "^2.3.0", @@ -18772,9 +18772,9 @@ "dev": true }, "zone.js": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.9.0.tgz", - "integrity": "sha512-EfygvVnLxPSCMSgJ4h7SoY+XNr7ybdwvvwEQ70lvMFl9coNnciXSyWi8Kg6znK1ubyUSffkCKvleSQpLuUKw0Q==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.9.1.tgz", + "integrity": "sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag==" } } } diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 539bdd9da..f9ed9c7e6 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -44,7 +44,7 @@ "slugify": "1.3.4", "sortablejs": "1.9.0", "tslib": "1.9.3", - "zone.js": "0.9.0" + "zone.js": "0.9.1" }, "devDependencies": { "@angular/compiler": "7.2.14", @@ -54,8 +54,8 @@ "@types/jasmine": "3.3.12", "@types/marked": "0.6.5", "@types/mousetrap": "1.6", - "@types/node": "11.13.8", - "@types/react": "16.8.14", + "@types/node": "12.0.0", + "@types/react": "16.8.16", "@types/react-dom": "16.8.4", "@types/sortablejs": "1.7.2", "angular-router-loader": "0.8.5", @@ -91,7 +91,7 @@ "sass-lint": "1.13.1", "sass-loader": "7.1.0", "style-loader": "0.23.1", - "ts-loader": "^5.4.4", + "ts-loader": "5.4.5", "tsconfig-paths-webpack-plugin": "3.2.0", "tslint": "5.16.0", "tslint-webpack-plugin": "2.0.4", diff --git a/src/Squidex/tslint.json b/src/Squidex/tslint.json index 88d7ea0ad..9654b463a 100644 --- a/src/Squidex/tslint.json +++ b/src/Squidex/tslint.json @@ -65,6 +65,7 @@ ], "no-input-rename": false, "no-output-rename": false, + "no-pipe-impure": true, "no-shadowed-variable": true, "no-string-literal": false, "no-switch-case-fall-through": true, @@ -103,7 +104,8 @@ true, "always" ], - "templates-no-negated-async": true, + "template-no-negated-async": true, + "template-use-track-by-function": true, "trailing-comma": [ true, { From e57599991407cf8bbd048375e44a4180786dc89b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 4 May 2019 23:12:27 +0200 Subject: [PATCH 18/20] Track by --- .../apps/pages/apps-page.component.html | 2 +- .../apps/pages/apps-page.component.ts | 5 ++ .../apps/pages/news-dialog.component.html | 2 +- .../apps/pages/news-dialog.component.ts | 4 ++ .../pages/content/content-page.component.html | 2 +- .../pages/content/content-page.component.ts | 5 ++ .../contents-filters-page.component.html | 2 +- .../shared/content-item.component.html | 2 +- .../content/shared/content-item.component.ts | 4 ++ .../shared/references-editor.component.html | 2 +- .../shared/references-editor.component.ts | 4 ++ .../content-changed-trigger.component.html | 2 +- .../content-changed-trigger.component.ts | 4 ++ .../pages/clients/client.component.html | 2 +- .../pages/clients/client.component.ts | 4 ++ .../angular/forms/tag-editor.component.ts | 30 ++++++---- .../language-selector.component.html | 4 +- .../components/language-selector.component.ts | 5 ++ src/Squidex/app/shared/components/pipes.ts | 2 + .../shared/services/assets.service.spec.ts | 55 +++++++++---------- .../app/shared/services/assets.service.ts | 41 +++++--------- .../shared/state/asset-uploader.state.spec.ts | 39 +++++++------ .../app/shared/state/asset-uploader.state.ts | 48 ++++++++++++++-- .../pages/internal/apps-menu.component.html | 2 +- .../pages/internal/apps-menu.component.ts | 5 ++ src/Squidex/tslint.json | 2 +- 26 files changed, 175 insertions(+), 104 deletions(-) diff --git a/src/Squidex/app/features/apps/pages/apps-page.component.html b/src/Squidex/app/features/apps/pages/apps-page.component.html index 3acadfa07..abd6252d9 100644 --- a/src/Squidex/app/features/apps/pages/apps-page.component.html +++ b/src/Squidex/app/features/apps/pages/apps-page.component.html @@ -14,7 +14,7 @@

You are not collaborating to any app yet

-
+

{{app.name}}

diff --git a/src/Squidex/app/features/apps/pages/apps-page.component.ts b/src/Squidex/app/features/apps/pages/apps-page.component.ts index d5eba2e0a..631592433 100644 --- a/src/Squidex/app/features/apps/pages/apps-page.component.ts +++ b/src/Squidex/app/features/apps/pages/apps-page.component.ts @@ -9,6 +9,7 @@ import { Component, OnInit } from '@angular/core'; import { take } from 'rxjs/operators'; import { + AppDto, AppsState, AuthService, DialogModel, @@ -77,4 +78,8 @@ export class AppsPageComponent implements OnInit { public stop(event: Event) { event.stopPropagation(); } + + public trackByApp(index: number, app: AppDto) { + return app.id; + } } \ No newline at end of file diff --git a/src/Squidex/app/features/apps/pages/news-dialog.component.html b/src/Squidex/app/features/apps/pages/news-dialog.component.html index 3b8e5dc4f..70c0f1625 100644 --- a/src/Squidex/app/features/apps/pages/news-dialog.component.html +++ b/src/Squidex/app/features/apps/pages/news-dialog.component.html @@ -7,7 +7,7 @@

What's new?

-
+

{{feature.name}}

diff --git a/src/Squidex/app/features/apps/pages/news-dialog.component.ts b/src/Squidex/app/features/apps/pages/news-dialog.component.ts index 01d0ce8d9..1871e0594 100644 --- a/src/Squidex/app/features/apps/pages/news-dialog.component.ts +++ b/src/Squidex/app/features/apps/pages/news-dialog.component.ts @@ -24,4 +24,8 @@ export class NewsDialogComponent { public emitClose() { this.close.emit(); } + + public trackByFeature(index: number, feature: FeatureDto) { + return feature; + } } \ No newline at end of file diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.html b/src/Squidex/app/features/content/pages/content/content-page.component.html index 44168b5cf..48bfeb3d3 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.html +++ b/src/Squidex/app/features/content/pages/content/content-page.component.html @@ -111,7 +111,7 @@ Viewing version {{version.value}}.
-
+

Saved queries

- {{query.name}} diff --git a/src/Squidex/app/features/content/shared/content-item.component.html b/src/Squidex/app/features/content/shared/content-item.component.html index 0ae1e664b..985056255 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.html +++ b/src/Squidex/app/features/content/shared/content-item.component.html @@ -10,7 +10,7 @@ - + diff --git a/src/Squidex/app/features/content/shared/content-item.component.ts b/src/Squidex/app/features/content/shared/content-item.component.ts index f97f9baab..6e9abe81c 100644 --- a/src/Squidex/app/features/content/shared/content-item.component.ts +++ b/src/Squidex/app/features/content/shared/content-item.component.ts @@ -187,5 +187,9 @@ export class ContentItemComponent implements OnChanges { return undefined; } + + public trackByField(index: number, field: FieldDto) { + return field.fieldId + this.schema.id; + } } diff --git a/src/Squidex/app/features/content/shared/references-editor.component.html b/src/Squidex/app/features/content/shared/references-editor.component.html index 2ca51947a..312c46e7f 100644 --- a/src/Squidex/app/features/content/shared/references-editor.component.html +++ b/src/Squidex/app/features/content/shared/references-editor.component.html @@ -9,7 +9,7 @@ - +
diff --git a/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts b/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts index d9644c4fa..a3e1f140b 100644 --- a/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts +++ b/src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts @@ -103,4 +103,8 @@ export class ContentChangedTriggerComponent implements OnInit { this.schemasToAdd = this.schemas.filter(schema => !this.triggerSchemas.find(s => s.schema.id === schema.id)).sortByStringAsc(x => x.name); this.schemaToAdd = this.schemasToAdd.at(0); } + + public trackBySchema(index: number, schema: SchemaDto) { + return schema.id; + } } \ No newline at end of file diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.html b/src/Squidex/app/features/settings/pages/clients/client.component.html index 9ebb54ab5..70ae8e22a 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.html +++ b/src/Squidex/app/features/settings/pages/clients/client.component.html @@ -71,7 +71,7 @@
diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.ts b/src/Squidex/app/features/settings/pages/clients/client.component.ts index 35437867a..e9d3d67d4 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/client.component.ts @@ -111,6 +111,10 @@ export class ClientComponent implements OnChanges { this.dialogs.notifyError(error); }); } + + public trackByRole(index: number, role: RoleDto) { + return role.name; + } } function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { diff --git a/src/Squidex/app/framework/angular/forms/tag-editor.component.ts b/src/Squidex/app/framework/angular/forms/tag-editor.component.ts index 4e049dc45..df703254b 100644 --- a/src/Squidex/app/framework/angular/forms/tag-editor.component.ts +++ b/src/Squidex/app/framework/angular/forms/tag-editor.component.ts @@ -5,6 +5,8 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ +// tslint:disable:template-use-track-by-function + import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms'; import { distinctUntilChanged, map, tap } from 'rxjs/operators'; @@ -362,32 +364,36 @@ export class TagEditorComponent extends StatefulControlComponent i public onCopy(event: ClipboardEvent) { if (!this.hasSelection()) { - event.clipboardData.setData('text/plain', this.snapshot.items.filter(x => !!x).join(',')); + if (event.clipboardData) { + event.clipboardData.setData('text/plain', this.snapshot.items.filter(x => !!x).join(',')); + } event.preventDefault(); } } public onPaste(event: ClipboardEvent) { - const value = event.clipboardData.getData('text/plain'); + if (event.clipboardData) { + const value = event.clipboardData.getData('text/plain'); - if (value) { - this.resetForm(); + if (value) { + this.resetForm(); - const values = [...this.snapshot.items]; + const values = [...this.snapshot.items]; - for (let part of value.split(',')) { - const converted = this.converter.convert(part); + for (let part of value.split(',')) { + const converted = this.converter.convert(part); - if (converted) { - values.push(converted); + if (converted) { + values.push(converted); + } } + + this.updateItems(values); } - this.updateItems(values); + event.preventDefault(); } - - event.preventDefault(); } private hasSelection() { diff --git a/src/Squidex/app/shared/components/language-selector.component.html b/src/Squidex/app/shared/components/language-selector.component.html index 995a4302f..d56354bce 100644 --- a/src/Squidex/app/shared/components/language-selector.component.html +++ b/src/Squidex/app/shared/components/language-selector.component.html @@ -1,5 +1,5 @@
-
@@ -9,7 +9,7 @@ {{selectedLanguage.iso2Code}}