Browse Source

Fix loading state

pull/879/head
Sebastian 4 years ago
parent
commit
7e071725da
  1. 17
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs
  2. 4
      backend/src/Squidex.Domain.Apps.Entities/Backup/TempFolderBackupArchiveLocation.cs
  3. 7
      backend/src/Squidex/appsettings.json
  4. 27
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs
  5. 3
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ScriptingCompleterTests.cs
  6. 12
      backend/tools/TestSuite/TestSuite.Shared/Fixtures/SchemaFixtureBase.cs
  7. 133
      backend/tools/TestSuite/TestSuite.Shared/SharedInstances.cs
  8. 22
      frontend/src/app/features/settings/pages/contributors/contributors-page.component.html
  9. 2
      frontend/src/app/features/settings/pages/workflows/workflows-page.component.html
  10. 8
      frontend/src/app/framework/state.ts

17
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/JsonMapper.cs

@ -82,11 +82,6 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
return JsonValue.Create(value.AsBoolean());
}
if (value.IsNumber())
{
return JsonValue.Create(value.AsNumber());
}
if (value.IsDate())
{
return JsonValue.Create(value.AsDate().ToString());
@ -97,6 +92,18 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
return JsonValue.Create(value.AsRegExp().Value?.ToString());
}
if (value.IsNumber())
{
var number = value.AsNumber();
if (double.IsNaN(number) || double.IsPositiveInfinity(number) || double.IsNegativeInfinity(number))
{
return JsonValue.Zero;
}
return JsonValue.Create(number);
}
if (value.IsArray())
{
var arr = value.AsArray();

4
backend/src/Squidex.Domain.Apps.Entities/Backup/TempFolderBackupArchiveLocation.cs

@ -51,7 +51,9 @@ namespace Squidex.Domain.Apps.Entities.Backup
}
catch (HttpRequestException ex)
{
throw new BackupRestoreException($"Cannot download the archive. Got status code: {response?.StatusCode}.", ex);
var statusCode = response != null ? (int)response.StatusCode : 0;
throw new BackupRestoreException($"Cannot download the archive. Got status code {statusCode}: {ex.Message}.", ex);
}
finally
{

7
backend/src/Squidex/appsettings.json

@ -211,6 +211,13 @@
}
},
"apps": {
// True to delete apps permanently.
//
// This process can take a while and is executed in the background.
"deletePermanent": false
},
"contents": {
// True to enable memory caching.
//

27
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ContentDataObjectTests.cs

@ -373,6 +373,33 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
ExecuteScript(original, script);
}
[Theory]
[InlineData("NaN")]
[InlineData("Number.POSITIVE_INFINITY")]
[InlineData("Number.NEGATIVE_INFINITY")]
public void Should_not_throw_exceptions_if_invalid_numbers(string input)
{
var original =
new ContentData()
.AddField("number",
new ContentFieldData()
.AddInvariant(JsonValue.Array()));
var expected =
new ContentData()
.AddField("number",
new ContentFieldData()
.AddInvariant(JsonValue.Zero));
string script = $@"
data.number.iv = {input};
";
var result = ExecuteScript(original, script);
Assert.Equal(expected, result);
}
[Fact]
public void Should_null_propagate_unknown_fields()
{

3
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/ScriptingCompleterTests.cs

@ -73,7 +73,8 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
"ctx.schemaId",
"ctx.schemaName",
"ctx.status",
"ctx.statusOld"
"ctx.statusOld",
"ctx.validate"
});
}

12
backend/tools/TestSuite/TestSuite.Shared/Fixtures/SchemaFixtureBase.cs

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestSuite.Fixtures
{
internal class SchemaFixtureBase
{
}
}

133
backend/tools/TestSuite/TestSuite.Shared/SharedInstances.cs

@ -0,0 +1,133 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Concurrent;
using Squidex.ClientLibrary;
using Squidex.ClientLibrary.Management;
using TestSuite.Model;
namespace TestSuite
{
public static class SharedInstances
{
private static readonly string[] Contributors =
{
"hello@squidex.io"
};
private static readonly Task<ClientManagerWrapper> ClientManager = CreateClientManagerInternalAsync();
private static readonly ConcurrentDictionary<string, Task> ReferenceSchemas =
new ConcurrentDictionary<string, Task>();
private static readonly ConcurrentDictionary<string, Task> DefaultSchemas =
new ConcurrentDictionary<string, Task>();
private static readonly Task App = CreateAppInternalAsync();
private static Task<ClientManagerWrapper> CreateClientManagerInternalAsync()
{
var clientManager = new ClientManagerWrapper();
return clientManager.ConnectAsync();
}
private static async Task CreateAppInternalAsync()
{
var wrapper = await ClientManager;
try
{
await wrapper.Apps.PostAppAsync(new CreateAppDto { Name = wrapper.ClientManager.App });
}
catch (SquidexManagementException ex)
{
if (ex.StatusCode != 400)
{
throw;
}
}
var invite = new AssignContributorDto { Invite = true, Role = "Owner" };
foreach (var contributor in Contributors)
{
invite.ContributorId = contributor;
await wrapper.Apps.PostContributorAsync(wrapper.ClientManager.App, invite);
}
try
{
await wrapper.Apps.PostLanguageAsync(wrapper.ClientManager.App, new AddLanguageDto
{
Language = "de"
});
}
catch (SquidexManagementException ex)
{
if (ex.StatusCode != 400)
{
throw;
}
}
}
public static Task<ClientManagerWrapper> CreateClientManagerAsync()
{
return ClientManager;
}
public static async Task<IContentsClient<TestEntityWithReferences, TestEntityWithReferencesData>> CreateReferenceSchema(string name)
{
var wrapper = await ClientManager;
async Task CreateAsync()
{
try
{
await TestEntityWithReferences.CreateSchemaAsync(wrapper.Schemas, wrapper.ClientManager.App, name);
}
catch (SquidexManagementException ex)
{
if (ex.StatusCode != 400)
{
throw;
}
}
}
await ReferenceSchemas.GetOrAdd(name, _ => CreateAsync());
return wrapper.ClientManager.CreateContentsClient<TestEntityWithReferences, TestEntityWithReferencesData>(name);
}
public static async Task<IContentsClient<TestEntity, TestEntityData>> CreateDefaultSchema(string name)
{
var wrapper = await ClientManager;
async Task CreateAsync()
{
try
{
await TestEntity.CreateSchemaAsync(wrapper.Schemas, wrapper.ClientManager.App, name);
}
catch (SquidexManagementException ex)
{
if (ex.StatusCode != 400)
{
throw;
}
}
}
await DefaultSchemas.GetOrAdd(name, _ => CreateAsync());
return wrapper.ClientManager.CreateContentsClient<TestEntity, TestEntityData>(name);
}
}
}

22
frontend/src/app/features/settings/pages/contributors/contributors-page.component.html

@ -35,21 +35,17 @@
</ng-container>
</ng-container>
<ng-container *ngIf="contributorsState.contributorsFiltered | async; let contributors">
<ng-container *ngIf="(contributorsState.isLoaded | async) && (contributorsState.contributorsFiltered | async); let contributors">
<ng-container *ngIf="rolesState.roles | async; let roles">
<ng-container *ngIf="contributors.length > 0; else noContributors">
<table class="table table-items table-fixed">
<tbody *ngFor="let contributor of contributors; trackBy: trackByContributor" [sqxContributor]="contributor"
[search]="contributorsState.queryRegex | async" [roles]="roles">
</tbody>
</table>
</ng-container>
<div class="table-items-row table-items-row-summary table-items-row-empty" *ngIf="contributors.length === 0">
{{ 'contributors.empty' | sqxTranslate }}
</div>
<ng-template #noContributors>
<div class="table-items-row table-items-row-summary table-items-row-empty">
{{ 'contributors.empty' | sqxTranslate }}
</div>
</ng-template>
<table class="table table-items table-fixed">
<tbody *ngFor="let contributor of contributors; trackBy: trackByContributor" [sqxContributor]="contributor"
[search]="contributorsState.queryRegex | async" [roles]="roles">
</tbody>
</table>
</ng-container>
</ng-container>
</ng-container>

2
frontend/src/app/features/settings/pages/workflows/workflows-page.component.html

@ -21,7 +21,7 @@
</div>
</ng-container>
<ng-container *ngIf="schemasSource && workflowsState.workflows | async; let workflows">
<ng-container *ngIf="schemasSource && (workflowsState.isLoaded | async) && (workflowsState.workflows | async); let workflows">
<div class="table-items-row table-items-row-summary table-items-row-empty" *ngIf="workflows.length === 0">
{{ 'workflows.empty' | sqxTranslate }}
</div>

8
frontend/src/app/framework/state.ts

@ -134,8 +134,14 @@ export class State<T extends {}> {
if (debugName && devToolsExtension) {
const name = `[Squidex] ${debugName}`;
this.devTools = devToolsExtension.connect({ name, features: {} });
this.devTools = devToolsExtension.connect({ name, features: { jump: true } });
this.devTools.init(initialState);
this.devTools.subscribe((message: any) => {
if (message.type === 'DISPATCH' && message.payload.type === 'JUMP_TO_ACTION') {
this.state.next(JSON.parse(message.state));
}
});
}
}

Loading…
Cancel
Save