From e337e41de7241a02843c5c3e5eca0f84d505dc7c Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Thu, 14 Jul 2022 14:52:16 +0200 Subject: [PATCH] 6.8 bugfixes (#897) * Several bugfixes. * Fix scheduler and release semaphore. * Disable delete button if the user does not have permissions. * Fix concurrency issues with cache grains. * Map translate code. * Just some formatting. --- backend/i18n/source/backend_en.json | 1 + .../Apps/Indexes/AppsCacheGrain.cs | 4 ++ .../DomainObject/ContentDomainObject.cs | 1 + .../Guards/SingletonExtensions.cs | 8 ++++ .../Rules/Indexes/RulesCacheGrain.cs | 31 +++++++----- .../Schemas/Indexes/SchemasCacheGrain.cs | 45 +++++++++-------- .../Squidex.Infrastructure/Tasks/Scheduler.cs | 2 + .../Controllers/Schemas/Models/SchemaDto.cs | 4 +- .../Translations/Models/TranslationDto.cs | 2 +- .../Squidex/Config/Domain/BackupsServices.cs | 3 ++ .../Apps/Indexes/AppsCacheGrainTests.cs | 22 +++++++++ .../DomainObject/Guards/GuardContentTests.cs | 12 +++++ .../Rules/Indexes/RulesCacheGrainTests.cs | 46 ++++++++++++++++++ .../Schemas/Indexes/SchemasCacheGrainTests.cs | 48 ++++++++++++++++++- .../Tasks/SchedulerTests.cs | 25 ++++++++++ .../shared/list/content.component.html | 2 +- .../references/content-creator.component.ts | 2 +- .../references-validation.component.html | 2 +- .../fields/types/string-ui.component.html | 2 +- .../pages/workflows/workflow.component.html | 4 +- .../references/content-selector.component.ts | 2 +- .../src/app/shared/state/schema-tag-source.ts | 11 ++++- 22 files changed, 235 insertions(+), 44 deletions(-) diff --git a/backend/i18n/source/backend_en.json b/backend/i18n/source/backend_en.json index 98edba8acc..5d154fc316 100644 --- a/backend/i18n/source/backend_en.json +++ b/backend/i18n/source/backend_en.json @@ -142,6 +142,7 @@ "contents.singletonNotChangeable": "Singleton content cannot be updated.", "contents.singletonNotCreatable": "Singleton content cannot be created.", "contents.singletonNotDeletable": "Singleton content cannot be deleted.", + "contents.componentNotCreatable": "Component content cannot be created.", "contents.statusNotValid": "Status is not defined in the workflow.", "contents.statusTransitionNotAllowed": "Cannot change status from {oldStatus} to {newStatus}.", "contents.validation.aspectRatio": "Must have aspect ratio {width}:{height}.", diff --git a/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsCacheGrain.cs b/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsCacheGrain.cs index f0de5dca99..c05587e525 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsCacheGrain.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsCacheGrain.cs @@ -76,6 +76,10 @@ public async Task> GetAppIdsAsync(string[] names) result.Add(id); } + else if (appIds.TryGetValue(name, out var cachedId) && cachedId != DomainId.Empty) + { + result.Add(cachedId); + } else { appIds[name] = default; diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs index 340d730c54..4dd5b8cdef 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs @@ -229,6 +229,7 @@ public override Task ExecuteAsync(IAggregateCommand command) private async Task CreateCore(CreateContent c, ContentOperation operation) { + operation.MustNotCreateComponent(); operation.MustNotCreateSingleton(); operation.MustNotCreateForUnpublishedSchema(); operation.MustHaveData(c.Data); diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs index 61b3cfa4c2..bb4354e288 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SingletonExtensions.cs @@ -22,6 +22,14 @@ public static void MustNotCreateForUnpublishedSchema(this ContentOperation opera } } + public static void MustNotCreateComponent(this ContentOperation operation) + { + if (operation.SchemaDef.Type == SchemaType.Component) + { + throw new DomainException(T.Get("contents.componentNotCreatable")); + } + } + public static void MustNotCreateSingleton(this ContentOperation operation) { if (operation.SchemaDef.Type == SchemaType.Singleton && operation.CommandId != operation.Schema.Id) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesCacheGrain.cs b/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesCacheGrain.cs index 879b441a6e..8dcbf94cca 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesCacheGrain.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesCacheGrain.cs @@ -17,7 +17,8 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes public sealed class RulesCacheGrain : GrainBase, IRulesCacheGrain { private readonly IRuleRepository ruleRepository; - private List? ruleIds; + private readonly HashSet ruleIds = new HashSet(); + private bool isLoaded; public RulesCacheGrain(IGrainIdentity grainIdentity, IRuleRepository ruleRepository) : base(grainIdentity) @@ -25,32 +26,40 @@ public RulesCacheGrain(IGrainIdentity grainIdentity, IRuleRepository ruleReposit this.ruleRepository = ruleRepository; } - public async Task> GetRuleIdsAsync() + public override Task OnActivateAsync() { - var ids = ruleIds; + return GetRuleIdsAsync(); + } - if (ids == null) + public async Task> GetRuleIdsAsync() + { + if (!isLoaded) { - ids = await ruleRepository.QueryIdsAsync(Key); + var loaded = await ruleRepository.QueryIdsAsync(Key); + + foreach (var id in loaded) + { + ruleIds.Add(id); + } - ruleIds = ids; + isLoaded = true; } - return ids; + return ruleIds; } public Task AddAsync(DomainId id) { - ruleIds?.Add(id); + ruleIds.Add(id); return Task.CompletedTask; } - public Task RemoveAsync(DomainId id) + public async Task RemoveAsync(DomainId id) { - ruleIds?.Remove(id); + await GetRuleIdsAsync(); - return Task.CompletedTask; + ruleIds.Remove(id); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasCacheGrain.cs b/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasCacheGrain.cs index ec83d6b414..7e2f8c276c 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasCacheGrain.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasCacheGrain.cs @@ -17,7 +17,8 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes public sealed class SchemasCacheGrain : UniqueNameGrain, ISchemasCacheGrain { private readonly ISchemaRepository schemaRepository; - private Dictionary? schemaIds; + private readonly Dictionary schemaIds = new Dictionary(); + private bool isLoaded; public SchemasCacheGrain(IGrainIdentity identity, ISchemaRepository schemaRepository) : base(identity) @@ -25,6 +26,11 @@ public SchemasCacheGrain(IGrainIdentity identity, ISchemaRepository schemaReposi this.schemaRepository = schemaRepository; } + public override Task OnActivateAsync() + { + return GetIdsAsync(); + } + public override async Task ReserveAsync(DomainId id, string name) { var token = await base.ReserveAsync(id, name); @@ -61,41 +67,38 @@ public async Task GetSchemaIdAsync(string name) private async Task> GetIdsAsync() { - var ids = schemaIds; - - if (ids == null) + if (!isLoaded) { - ids = await schemaRepository.QueryIdsAsync(Key); + var loaded = await schemaRepository.QueryIdsAsync(Key); - schemaIds = ids; + foreach (var (name, id) in loaded) + { + schemaIds[name] = id; + } + + isLoaded = true; } - return ids; + return schemaIds; } public Task AddAsync(DomainId id, string name) { - if (schemaIds != null) - { - schemaIds[name] = id; - } + schemaIds[name] = id; return Task.CompletedTask; } - public Task RemoveAsync(DomainId id) + public async Task RemoveAsync(DomainId id) { - if (schemaIds != null) - { - var name = schemaIds.FirstOrDefault(x => x.Value == id).Key; + await GetIdsAsync(); - if (name != null) - { - schemaIds.Remove(name); - } - } + var name = schemaIds.FirstOrDefault(x => x.Value == id).Key; - return Task.CompletedTask; + if (name != null) + { + schemaIds.Remove(name); + } } } } diff --git a/backend/src/Squidex.Infrastructure/Tasks/Scheduler.cs b/backend/src/Squidex.Infrastructure/Tasks/Scheduler.cs index 0dbbdc1dfc..b061b7d4ae 100644 --- a/backend/src/Squidex.Infrastructure/Tasks/Scheduler.cs +++ b/backend/src/Squidex.Infrastructure/Tasks/Scheduler.cs @@ -113,6 +113,8 @@ private async Task ScheduleTask(SchedulerTask task, } finally { + semaphore.Release(); + if (Interlocked.Decrement(ref pendingTasks) <= 1) { tcs.TrySetResult(true); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs index 0c36075aeb..8d16d78b0e 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs @@ -154,12 +154,12 @@ protected virtual void CreateLinks(Resources resources) AddSelfLink(resources.Url(x => nameof(x.GetSchema), values)); - if (resources.CanReadContent(Name)) + if (resources.CanReadContent(Name) && Type == SchemaType.Default) { AddGetLink("contents", resources.Url(x => nameof(x.GetContents), values)); } - if (resources.CanCreateContent(Name)) + if (resources.CanCreateContent(Name) && Type == SchemaType.Default) { AddPostLink("contents/create", resources.Url(x => nameof(x.PostContent), values)); AddPostLink("contents/create/publish", resources.Url(x => nameof(x.PostContent), values) + "?publish=true"); diff --git a/backend/src/Squidex/Areas/Api/Controllers/Translations/Models/TranslationDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Translations/Models/TranslationDto.cs index 76aad29819..4f8c7ee94c 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Translations/Models/TranslationDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Translations/Models/TranslationDto.cs @@ -24,7 +24,7 @@ public sealed class TranslationDto public static TranslationDto FromDomain(TranslationResult translation) { - return SimpleMapper.Map(translation, new TranslationDto()); + return SimpleMapper.Map(translation, new TranslationDto { Result = translation.Code }); } } } diff --git a/backend/src/Squidex/Config/Domain/BackupsServices.cs b/backend/src/Squidex/Config/Domain/BackupsServices.cs index 038eccd769..d57fc57480 100644 --- a/backend/src/Squidex/Config/Domain/BackupsServices.cs +++ b/backend/src/Squidex/Config/Domain/BackupsServices.cs @@ -22,6 +22,9 @@ public static void AddSquidexBackups(this IServiceCollection services) services.AddSingletonAs() .As(); + services.AddSingletonAs() + .As(); + services.AddSingletonAs() .As(); diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsCacheGrainTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsCacheGrainTests.cs index 0bd4b57edc..89b26e76aa 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsCacheGrainTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsCacheGrainTests.cs @@ -149,5 +149,27 @@ public async Task Should_remove_id_from_loaded_result() A.CallTo(() => appRepository.QueryIdsAsync(A>.That.Is("name1", "name2"), default)) .MustHaveHappenedOnceExactly(); } + + [Fact] + public async Task Should_merge_found_value_with_added_id() + { + var foundId = DomainId.NewGuid(); + + async Task> GetIds() + { + await sut.AddAsync(foundId, "name1"); + + return new Dictionary(); + } + + A.CallTo(() => appRepository.QueryIdsAsync(A>._, A._)) + .ReturnsLazily(() => GetIds()); + + var result1 = await sut.GetAppIdsAsync(new[] { "name1" }); + var result2 = await sut.GetAppIdsAsync(new[] { "name1" }); + + Assert.Equal(foundId, result1.Single()); + Assert.Equal(foundId, result2.Single()); + } } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs index 33b085295e..54eeaf444c 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs @@ -34,6 +34,7 @@ public class GuardContentTests : IClassFixture private readonly ISchemaEntity normalUnpublishedSchema; private readonly ISchemaEntity singletonSchema; private readonly ISchemaEntity singletonUnpublishedSchema; + private readonly ISchemaEntity componentSchema; private readonly RefToken actor = RefToken.User("123"); public GuardContentTests() @@ -49,6 +50,9 @@ public GuardContentTests() singletonSchema = Mocks.Schema(appId, schemaId, new Schema(schemaId.Name, type: SchemaType.Singleton).Publish()); + + componentSchema = + Mocks.Schema(appId, schemaId, new Schema(schemaId.Name, type: SchemaType.Component).Publish()); } [Fact] @@ -91,6 +95,14 @@ public void Should_throw_exception_if_creating_singleton_content() Assert.Throws(() => operation.MustNotCreateSingleton()); } + [Fact] + public void Should_throw_exception_if_creating_component_content() + { + var operation = Operation(CreateContent(Status.Draft), componentSchema); + + Assert.Throws(() => operation.MustNotCreateComponent()); + } + [Fact] public void Should_not_throw_exception_if_creating_singleton_content_with_schema_id() { diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Indexes/RulesCacheGrainTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Indexes/RulesCacheGrainTests.cs index 1f654d0e10..091edd0229 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Indexes/RulesCacheGrainTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Rules/Indexes/RulesCacheGrainTests.cs @@ -99,5 +99,51 @@ public async Task Should_remove_id_from_loaded_result() A.CallTo(() => ruleRepository.QueryIdsAsync(appId, default)) .MustHaveHappenedOnceExactly(); } + + [Fact] + public async Task Should_remove_id_from_not_loaded_result() + { + var ids = new List + { + DomainId.NewGuid(), + DomainId.NewGuid() + }; + + var newId = DomainId.NewGuid(); + + A.CallTo(() => ruleRepository.QueryIdsAsync(appId, default)) + .Returns(ids); + + await sut.RemoveAsync(ids.ElementAt(0)); + + var result = await sut.GetRuleIdsAsync(); + + Assert.Equal(ids.Skip(1), result); + + A.CallTo(() => ruleRepository.QueryIdsAsync(appId, default)) + .MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task Should_merge_found_value_with_added_id() + { + var foundId = DomainId.NewGuid(); + + async Task> GetIds() + { + await sut.AddAsync(foundId); + + return new List(); + } + + A.CallTo(() => ruleRepository.QueryIdsAsync(appId, default)) + .ReturnsLazily(() => GetIds()); + + var result1 = await sut.GetRuleIdsAsync(); + var result2 = await sut.GetRuleIdsAsync(); + + Assert.Equal(foundId, result1.Single()); + Assert.Equal(foundId, result2.Single()); + } } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasCacheGrainTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasCacheGrainTests.cs index 443c22a697..f324246356 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasCacheGrainTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasCacheGrainTests.cs @@ -112,10 +112,56 @@ public async Task Should_remove_id_from_loaded_result() var result = await sut.GetSchemaIdsAsync(); - Assert.Equal(ids.Values.Take(1), result); + Assert.Equal(ids.Values.Skip(1), result); A.CallTo(() => schemaRepository.QueryIdsAsync(appId, default)) .MustHaveHappenedOnceExactly(); } + + [Fact] + public async Task Should_remove_id_from_not_loaded_result() + { + var ids = new Dictionary + { + ["name1"] = DomainId.NewGuid(), + ["name2"] = DomainId.NewGuid() + }; + + var newId = DomainId.NewGuid(); + + A.CallTo(() => schemaRepository.QueryIdsAsync(appId, default)) + .Returns(ids); + + await sut.RemoveAsync(ids.ElementAt(0).Value); + + var result = await sut.GetSchemaIdsAsync(); + + Assert.Equal(ids.Values.Skip(1), result); + + A.CallTo(() => schemaRepository.QueryIdsAsync(appId, default)) + .MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task Should_merge_found_value_with_added_id() + { + var foundId = DomainId.NewGuid(); + + async Task> GetIds() + { + await sut.AddAsync(foundId, "name1"); + + return new Dictionary(); + } + + A.CallTo(() => schemaRepository.QueryIdsAsync(appId, default)) + .ReturnsLazily(() => GetIds()); + + var result1 = await sut.GetSchemaIdsAsync(); + var result2 = await sut.GetSchemaIdsAsync(); + + Assert.Equal(foundId, result1.Single()); + Assert.Equal(foundId, result2.Single()); + } } } diff --git a/backend/tests/Squidex.Infrastructure.Tests/Tasks/SchedulerTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Tasks/SchedulerTests.cs index ebc35e0b92..2783c4b6de 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Tasks/SchedulerTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Tasks/SchedulerTests.cs @@ -25,6 +25,21 @@ public async Task Should_schedule_single_task() Assert.Equal(new[] { 1 }, results.ToArray()); } + [Fact] + public async Task Should_schedule_lot_of_tasks_with_limited_concurrency() + { + var limited = new Scheduler(1); + + for (var i = 1; i <= 10; i++) + { + Schedule(i, limited); + } + + await limited.CompleteAsync(); + + Assert.Equal(Enumerable.Range(1, 10).ToArray(), results.OrderBy(x => x).ToArray()); + } + [Fact] public async Task Should_schedule_multiple_tasks() { @@ -83,5 +98,15 @@ private void Schedule(int value) results.Add(value); }); } + + private void Schedule(int value, Scheduler target) + { + target.Schedule(async _ => + { + await Task.Delay(1); + + results.Add(value); + }); + } } } diff --git a/frontend/src/app/features/content/shared/list/content.component.html b/frontend/src/app/features/content/shared/list/content.component.html index 0bdf9826e6..e217c136f3 100644 --- a/frontend/src/app/features/content/shared/list/content.component.html +++ b/frontend/src/app/features/content/shared/list/content.component.html @@ -43,7 +43,7 @@ - x.canContentsCreate); if (this.schemaIds && this.schemaIds.length > 0) { - this.schemas = this.schemas.filter(x => this.schemaIds!.indexOf(x.id) >= 0); + this.schemas = this.schemas.filter(x => x.type === 'Default' && this.schemaIds!.indexOf(x.id) >= 0); } const selectedSchema = this.schemas.find(x => x.name === this.schemaName) || this.schemas[0]; diff --git a/frontend/src/app/features/schemas/pages/schema/fields/types/references-validation.component.html b/frontend/src/app/features/schemas/pages/schema/fields/types/references-validation.component.html index 0d02c9640c..92b9893934 100644 --- a/frontend/src/app/features/schemas/pages/schema/fields/types/references-validation.component.html +++ b/frontend/src/app/features/schemas/pages/schema/fields/types/references-validation.component.html @@ -4,7 +4,7 @@
+ [converter]="(schemasSource.normalConverter | async)!" [suggestions]="(schemasSource.normalConverter | async)?.suggestions">
diff --git a/frontend/src/app/features/schemas/pages/schema/fields/types/string-ui.component.html b/frontend/src/app/features/schemas/pages/schema/fields/types/string-ui.component.html index 6a34701725..b9d367ccbd 100644 --- a/frontend/src/app/features/schemas/pages/schema/fields/types/string-ui.component.html +++ b/frontend/src/app/features/schemas/pages/schema/fields/types/string-ui.component.html @@ -91,7 +91,7 @@
+ [converter]="(schemasSource.normalConverter | async)!" [suggestions]="(schemasSource.normalConverter | async)?.suggestions">
diff --git a/frontend/src/app/features/settings/pages/workflows/workflow.component.html b/frontend/src/app/features/settings/pages/workflows/workflow.component.html index 846509fc6f..33ba797f31 100644 --- a/frontend/src/app/features/settings/pages/workflows/workflow.component.html +++ b/frontend/src/app/features/settings/pages/workflows/workflow.component.html @@ -4,7 +4,7 @@ {{workflow.displayName}}
- @@ -81,7 +81,7 @@ [disabled]="!isEditable" [ngModel]="workflow.schemaIds" (ngModelChange)="changeSchemaIds($event)" - [suggestions]="(schemasSource.converter | async)?.suggestions"> + [suggestions]="(schemasSource.normalConverter | async)?.suggestions"> diff --git a/frontend/src/app/shared/components/references/content-selector.component.ts b/frontend/src/app/shared/components/references/content-selector.component.ts index 6b582ca810..033a3a4232 100644 --- a/frontend/src/app/shared/components/references/content-selector.component.ts +++ b/frontend/src/app/shared/components/references/content-selector.component.ts @@ -81,7 +81,7 @@ export class ContentSelectorComponent extends ResourceOwner implements OnInit { this.schemas = this.schemasState.snapshot.schemas.filter(x => x.canReadContents); if (this.schemaIds && this.schemaIds.length > 0) { - this.schemas = this.schemas.filter(x => x.canReadContents && this.schemaIds!.includes(x.id)); + this.schemas = this.schemas.filter(x => x.type === 'Default' && x.canReadContents && this.schemaIds!.includes(x.id)); } this.selectSchema(this.schemas[0]); diff --git a/frontend/src/app/shared/state/schema-tag-source.ts b/frontend/src/app/shared/state/schema-tag-source.ts index 9b3ff1092f..50a157578d 100644 --- a/frontend/src/app/shared/state/schema-tag-source.ts +++ b/frontend/src/app/shared/state/schema-tag-source.ts @@ -16,7 +16,12 @@ class SchemaConverter implements TagConverter { constructor( private readonly schemas: ReadonlyArray, + normalOnly: boolean, ) { + if (normalOnly) { + schemas = schemas.filter(x => x.type === 'Default'); + } + this.suggestions = schemas.map(x => new TagValue(x.id, x.name, x.id)); } @@ -45,7 +50,11 @@ class SchemaConverter implements TagConverter { export class SchemaTagSource { public converter = this.schemasState.schemas.pipe( - map(x => new SchemaConverter(x))); + map(x => new SchemaConverter(x, false))); + + public normalConverter = + this.schemasState.schemas.pipe( + map(x => new SchemaConverter(x, true))); constructor( readonly schemasState: SchemasState,