Browse Source

Style improvements.

pull/711/head
Sebastian Stehle 5 years ago
parent
commit
b57ab4af9c
  1. 9
      backend/src/Migrations/RebuildOptions.cs
  2. 14
      backend/src/Migrations/RebuildRunner.cs
  3. 26
      backend/src/Migrations/RebuilderExtensions.cs
  4. 5
      backend/src/Squidex.Domain.Apps.Entities/Assets/BackupAssets.cs
  5. 4
      backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs
  6. 3
      backend/src/Squidex.Domain.Apps.Entities/Contents/BackupContents.cs
  7. 21
      backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs
  8. 2
      backend/src/Squidex/Areas/IdentityServer/Views/Account/AccessDenied.cshtml
  9. 3
      backend/src/Squidex/Areas/IdentityServer/Views/Account/Consent.cshtml
  10. 2
      backend/src/Squidex/Areas/IdentityServer/Views/Account/LockedOut.cshtml
  11. 2
      backend/src/Squidex/Areas/IdentityServer/Views/Account/Login.cshtml
  12. 2
      backend/src/Squidex/Areas/IdentityServer/Views/Account/LogoutCompleted.cshtml
  13. 6
      backend/src/Squidex/Areas/IdentityServer/Views/Error/Error.cshtml
  14. 5
      backend/src/Squidex/Areas/IdentityServer/Views/Profile/Profile.cshtml
  15. 217
      backend/src/Squidex/Areas/IdentityServer/Views/Setup/Setup.cshtml
  16. 16
      backend/src/Squidex/Areas/IdentityServer/Views/_Layout.cshtml

9
backend/src/Migrations/RebuildOptions.cs

@ -5,6 +5,8 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
namespace Migrations namespace Migrations
{ {
public sealed class RebuildOptions public sealed class RebuildOptions
@ -22,5 +24,12 @@ namespace Migrations
public bool Rules { get; set; } public bool Rules { get; set; }
public bool Schemas { get; set; } public bool Schemas { get; set; }
public int BatchSize { get; set; } = 100;
public int CalculateBatchSize()
{
return Math.Max(10, Math.Min(1000, BatchSize));
}
} }
} }

14
backend/src/Migrations/RebuildRunner.cs

@ -41,25 +41,27 @@ namespace Migrations
public async Task RunAsync(CancellationToken ct) public async Task RunAsync(CancellationToken ct)
{ {
var batchSize = rebuildOptions.CalculateBatchSize();
if (rebuildOptions.Apps) if (rebuildOptions.Apps)
{ {
await rebuilder.RebuildAppsAsync(ct); await rebuilder.RebuildAppsAsync(batchSize, ct);
} }
if (rebuildOptions.Schemas) if (rebuildOptions.Schemas)
{ {
await rebuilder.RebuildSchemasAsync(ct); await rebuilder.RebuildSchemasAsync(batchSize, ct);
} }
if (rebuildOptions.Rules) if (rebuildOptions.Rules)
{ {
await rebuilder.RebuildRulesAsync(ct); await rebuilder.RebuildRulesAsync(batchSize, ct);
} }
if (rebuildOptions.Assets) if (rebuildOptions.Assets)
{ {
await rebuilder.RebuildAssetsAsync(ct); await rebuilder.RebuildAssetsAsync(batchSize, ct);
await rebuilder.RebuildAssetFoldersAsync(ct); await rebuilder.RebuildAssetFoldersAsync(batchSize, ct);
} }
if (rebuildOptions.AssetFiles) if (rebuildOptions.AssetFiles)
@ -69,7 +71,7 @@ namespace Migrations
if (rebuildOptions.Contents) if (rebuildOptions.Contents)
{ {
await rebuilder.RebuildContentAsync(ct); await rebuilder.RebuildContentAsync(batchSize, ct);
} }
if (rebuildOptions.Indexes) if (rebuildOptions.Indexes)

26
backend/src/Migrations/RebuilderExtensions.cs

@ -18,34 +18,34 @@ namespace Migrations
{ {
public static class RebuilderExtensions public static class RebuilderExtensions
{ {
public static Task RebuildAppsAsync(this Rebuilder rebuilder, CancellationToken ct = default) public static Task RebuildAppsAsync(this Rebuilder rebuilder, int batchSize, CancellationToken ct = default)
{ {
return rebuilder.RebuildAsync<AppDomainObject, AppDomainObject.State>("^app\\-", ct); return rebuilder.RebuildAsync<AppDomainObject, AppDomainObject.State>("^app\\-", batchSize, ct);
} }
public static Task RebuildSchemasAsync(this Rebuilder rebuilder, CancellationToken ct = default) public static Task RebuildSchemasAsync(this Rebuilder rebuilder, int batchSize, CancellationToken ct = default)
{ {
return rebuilder.RebuildAsync<SchemaDomainObject, SchemaDomainObject.State>("^schema\\-", ct); return rebuilder.RebuildAsync<SchemaDomainObject, SchemaDomainObject.State>("^schema\\-", batchSize, ct);
} }
public static Task RebuildRulesAsync(this Rebuilder rebuilder, CancellationToken ct = default) public static Task RebuildRulesAsync(this Rebuilder rebuilder, int batchSize, CancellationToken ct = default)
{ {
return rebuilder.RebuildAsync<RuleDomainObject, RuleDomainObject.State>("^rule\\-", ct); return rebuilder.RebuildAsync<RuleDomainObject, RuleDomainObject.State>("^rule\\-", batchSize, ct);
} }
public static Task RebuildAssetsAsync(this Rebuilder rebuilder, CancellationToken ct = default) public static Task RebuildAssetsAsync(this Rebuilder rebuilder, int batchSize, CancellationToken ct = default)
{ {
return rebuilder.RebuildAsync<AssetDomainObject, AssetDomainObject.State>("^asset\\-", ct); return rebuilder.RebuildAsync<AssetDomainObject, AssetDomainObject.State>("^asset\\-", batchSize, ct);
} }
public static Task RebuildAssetFoldersAsync(this Rebuilder rebuilder, CancellationToken ct = default) public static Task RebuildAssetFoldersAsync(this Rebuilder rebuilder, int batchSize, CancellationToken ct = default)
{ {
return rebuilder.RebuildAsync<AssetFolderDomainObject, AssetFolderDomainObject.State>("^assetFolder\\-", ct); return rebuilder.RebuildAsync<AssetFolderDomainObject, AssetFolderDomainObject.State>("^assetFolder\\-", batchSize, ct);
} }
public static Task RebuildContentAsync(this Rebuilder rebuilder, CancellationToken ct = default) public static Task RebuildContentAsync(this Rebuilder rebuilder, int batchSize, CancellationToken ct = default)
{ {
return rebuilder.RebuildAsync<ContentDomainObject, ContentDomainObject.State>("^content\\-", ct); return rebuilder.RebuildAsync<ContentDomainObject, ContentDomainObject.State>("^content\\-", batchSize, ct);
} }
} }
} }

5
backend/src/Squidex.Domain.Apps.Entities/Assets/BackupAssets.cs

@ -21,6 +21,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
{ {
public sealed class BackupAssets : IBackupHandler public sealed class BackupAssets : IBackupHandler
{ {
private const int BatchSize = 100;
private const string TagsFile = "AssetTags.json"; private const string TagsFile = "AssetTags.json";
private readonly HashSet<DomainId> assetIds = new HashSet<DomainId>(); private readonly HashSet<DomainId> assetIds = new HashSet<DomainId>();
private readonly HashSet<DomainId> assetFolderIds = new HashSet<DomainId>(); private readonly HashSet<DomainId> assetFolderIds = new HashSet<DomainId>();
@ -101,12 +102,12 @@ namespace Squidex.Domain.Apps.Entities.Assets
if (assetIds.Count > 0) if (assetIds.Count > 0)
{ {
await rebuilder.InsertManyAsync<AssetDomainObject, AssetDomainObject.State>(assetIds); await rebuilder.InsertManyAsync<AssetDomainObject, AssetDomainObject.State>(assetIds, BatchSize);
} }
if (assetFolderIds.Count > 0) if (assetFolderIds.Count > 0)
{ {
await rebuilder.InsertManyAsync<AssetFolderDomainObject, AssetFolderDomainObject.State>(assetFolderIds); await rebuilder.InsertManyAsync<AssetFolderDomainObject, AssetFolderDomainObject.State>(assetFolderIds, BatchSize);
} }
} }

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

@ -1,4 +1,4 @@
// ========================================================================== // ==========================================================================
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt) // Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -356,7 +356,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
var batchBlock = new BatchBlock<(string, Envelope<IEvent>)>(BatchSize, new GroupingDataflowBlockOptions var batchBlock = new BatchBlock<(string, Envelope<IEvent>)>(BatchSize, new GroupingDataflowBlockOptions
{ {
BoundedCapacity = BatchSize BoundedCapacity = BatchSize * 2
}); });
batchBlock.LinkTo(writeBlock, new DataflowLinkOptions batchBlock.LinkTo(writeBlock, new DataflowLinkOptions

3
backend/src/Squidex.Domain.Apps.Entities/Contents/BackupContents.cs

@ -24,6 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
public sealed class BackupContents : IBackupHandler public sealed class BackupContents : IBackupHandler
{ {
private const int BatchSize = 100;
private delegate void ObjectSetter(IReadOnlyDictionary<string, IJsonValue> obj, string key, IJsonValue value); private delegate void ObjectSetter(IReadOnlyDictionary<string, IJsonValue> obj, string key, IJsonValue value);
private const string UrlsFile = "Urls.json"; private const string UrlsFile = "Urls.json";
@ -216,7 +217,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
if (ids.Any()) if (ids.Any())
{ {
await rebuilder.InsertManyAsync<ContentDomainObject, ContentDomainObject.State>(ids); await rebuilder.InsertManyAsync<ContentDomainObject, ContentDomainObject.State>(ids, BatchSize);
} }
} }

21
backend/src/Squidex.Infrastructure/Commands/Rebuilder.cs

@ -19,8 +19,6 @@ using Squidex.Infrastructure.States;
namespace Squidex.Infrastructure.Commands namespace Squidex.Infrastructure.Commands
{ {
public delegate Task IdSource(Func<DomainId, Task> add);
public class Rebuilder public class Rebuilder
{ {
private readonly ILocalCache localCache; private readonly ILocalCache localCache;
@ -51,7 +49,7 @@ namespace Squidex.Infrastructure.Commands
this.localCache = localCache; this.localCache = localCache;
} }
public virtual async Task RebuildAsync<T, TState>(string filter, CancellationToken ct) where T : DomainObject<TState> where TState : class, IDomainState<TState>, new() public virtual async Task RebuildAsync<T, TState>(string filter, int batchSize, CancellationToken ct = default) where T : DomainObject<TState> where TState : class, IDomainState<TState>, new()
{ {
var store = serviceProvider.GetRequiredService<IStore<TState>>(); var store = serviceProvider.GetRequiredService<IStore<TState>>();
@ -65,12 +63,13 @@ namespace Squidex.Infrastructure.Commands
await target(id); await target(id);
} }
}, ct); }, batchSize, ct);
} }
public virtual async Task InsertManyAsync<T, TState>(IEnumerable<DomainId> source, CancellationToken ct = default) where T : DomainObject<TState> where TState : class, IDomainState<TState>, new() public virtual async Task InsertManyAsync<T, TState>(IEnumerable<DomainId> source, int batchSize, CancellationToken ct = default) where T : DomainObject<TState> where TState : class, IDomainState<TState>, new()
{ {
Guard.NotNull(source, nameof(source)); Guard.NotNull(source, nameof(source));
Guard.Between(batchSize, 1, 1000, nameof(batchSize));
var store = serviceProvider.GetRequiredService<IStore<TState>>(); var store = serviceProvider.GetRequiredService<IStore<TState>>();
@ -80,15 +79,13 @@ namespace Squidex.Infrastructure.Commands
{ {
await target(id); await target(id);
} }
}, ct); }, batchSize, ct);
} }
private async Task InsertManyAsync<T, TState>(IStore<TState> store, IdSource source, CancellationToken ct = default) where T : DomainObject<TState> where TState : class, IDomainState<TState>, new() private async Task InsertManyAsync<T, TState>(IStore<TState> store, Func<Func<DomainId, Task>, Task> source, int batchSize, CancellationToken ct = default) where T : DomainObject<TState> where TState : class, IDomainState<TState>, new()
{ {
var parallelism = Environment.ProcessorCount; var parallelism = Environment.ProcessorCount;
const int BatchSize = 100;
var workerBlock = new ActionBlock<DomainId[]>(async ids => var workerBlock = new ActionBlock<DomainId[]>(async ids =>
{ {
try try
@ -127,9 +124,9 @@ namespace Squidex.Infrastructure.Commands
BoundedCapacity = parallelism BoundedCapacity = parallelism
}); });
var batchBlock = new BatchBlock<DomainId>(BatchSize, new GroupingDataflowBlockOptions var batchBlock = new BatchBlock<DomainId>(batchSize, new GroupingDataflowBlockOptions
{ {
BoundedCapacity = BatchSize BoundedCapacity = batchSize
}); });
batchBlock.LinkTo(workerBlock, new DataflowLinkOptions batchBlock.LinkTo(workerBlock, new DataflowLinkOptions
@ -157,4 +154,4 @@ namespace Squidex.Infrastructure.Commands
} }
} }
} }
} }

2
backend/src/Squidex/Areas/IdentityServer/Views/Account/AccessDenied.cshtml

@ -1,6 +1,4 @@
@{ @{
ViewBag.ThemeColor = "white";
ViewBag.Title = T.Get("users.accessDenied.title"); ViewBag.Title = T.Get("users.accessDenied.title");
} }

3
backend/src/Squidex/Areas/IdentityServer/Views/Account/Consent.cshtml

@ -1,9 +1,6 @@
@model Squidex.Areas.IdentityServer.Controllers.Account.ConsentVM @model Squidex.Areas.IdentityServer.Controllers.Account.ConsentVM
@{ @{
ViewBag.ThemeColor = "white";
ViewBag.ThemeSize = "profile-lg";
ViewBag.Title = T.Get("users.consent.title"); ViewBag.Title = T.Get("users.consent.title");
} }

2
backend/src/Squidex/Areas/IdentityServer/Views/Account/LockedOut.cshtml

@ -1,6 +1,4 @@
@{ @{
ViewBag.ThemeColor = "white";
ViewBag.Title = T.Get("users.lockedOutTitle"); ViewBag.Title = T.Get("users.lockedOutTitle");
} }

2
backend/src/Squidex/Areas/IdentityServer/Views/Account/Login.cshtml

@ -1,8 +1,6 @@
@model Squidex.Areas.IdentityServer.Controllers.Account.LoginVM @model Squidex.Areas.IdentityServer.Controllers.Account.LoginVM
@{ @{
ViewBag.ThemeColor = "white";
var action = Model.IsLogin ? T.Get("common.login") : T.Get("common.signup"); var action = Model.IsLogin ? T.Get("common.login") : T.Get("common.signup");
ViewBag.Title = action; ViewBag.Title = action;

2
backend/src/Squidex/Areas/IdentityServer/Views/Account/LogoutCompleted.cshtml

@ -1,6 +1,4 @@
@{ @{
ViewBag.ThemeColor = "white";
ViewBag.Title = T.Get("users.logout.title"); ViewBag.Title = T.Get("users.logout.title");
} }

6
backend/src/Squidex/Areas/IdentityServer/Views/Error/Error.cshtml

@ -1,8 +1,6 @@
@model Squidex.Areas.IdentityServer.Controllers.Error.ErrorVM @model Squidex.Areas.IdentityServer.Controllers.Error.ErrorVM
@{ @{
ViewBag.ThemeColor = "white";
ViewBag.Title = T.Get("users.error.title"); ViewBag.Title = T.Get("users.error.title");
} }
@ -11,9 +9,9 @@
<h1 class="splash-h1">@T.Get("users.error.headline")</h1> <h1 class="splash-h1">@T.Get("users.error.headline")</h1>
<p class="splash-text"> <p class="splash-text">
@if (Model.ErrorMessage != null) @if (Model.Error?.ErrorDescription != null)
{ {
@Model.ErrorMessage @Model.Error.ErrorDescription
} }
else else
{ {

5
backend/src/Squidex/Areas/IdentityServer/Views/Profile/Profile.cshtml

@ -1,9 +1,6 @@
@model Squidex.Areas.IdentityServer.Controllers.Profile.ProfileVM @model Squidex.Areas.IdentityServer.Controllers.Profile.ProfileVM
@{ @{
ViewBag.ThemeColor = "white";
ViewBag.ThemeSize = "profile-lg";
ViewBag.Title = T.Get("users.profile.title"); ViewBag.Title = T.Get("users.profile.title");
void RenderValidation(string field) void RenderValidation(string field)
@ -279,7 +276,7 @@
} }
document.addEventListener('click', document.addEventListener('click',
function(event) { function (event) {
if (event.target.className.indexOf('remove-item') >= 0) { if (event.target.className.indexOf('remove-item') >= 0) {
event.target.parentNode.parentNode.remove(); event.target.parentNode.parentNode.remove();

217
backend/src/Squidex/Areas/IdentityServer/Views/Setup/Setup.cshtml

@ -1,9 +1,6 @@
@model Squidex.Areas.IdentityServer.Controllers.Setup.SetupVM @model Squidex.Areas.IdentityServer.Controllers.Setup.SetupVM
@{ @{
ViewBag.ThemeColor = "gray";
ViewBag.ThemeSize = "profile-lg";
ViewBag.Title = T.Get("setup.title"); ViewBag.Title = T.Get("setup.title");
void RenderValidation(string field) void RenderValidation(string field)
@ -68,134 +65,124 @@
} }
} }
<div class="card"> <h1>@T.Get("setup.headline")</h1>
<div class="card-body">
<h1>@T.Get("setup.headline")</h1>
<img style="height: 250px" class="mt-2 mb-2" src="@Url.RootContentUrl("~/squid.svg?title=Welcome&text=Welcome%20to%20the%20Installation%20Process&face=happy")" />
<small class="form-text text-muted mt-2 mb-2">@T.Get("setup.hint")</small>
<div class="profile-section">
<h2>@T.Get("setup.rules.headline")</h2>
@if (Model.IsValidHttps)
{
RenderRuleAsSuccess(T.Get("setup.ruleHttps.success"));
}
else
{
RenderRuleAsCritical(T.Get("setup.ruleHttps.failure"));
}
@if (Model.BaseUrlConfigured == Model.BaseUrlCurrent)
{
RenderRuleAsSuccess(T.Get("setup.ruleUrl.success"));
}
else
{
RenderRuleAsCritical(T.Get("setup.ruleUrl.failure", new { actual = Model.BaseUrlCurrent, configured = Model.BaseUrlConfigured }));
}
@if (Model.EverybodyCanCreateApps)
{
RenderRuleAsWarning(T.Get("setup.ruleAppCreation.warningAdmins"));
}
else
{
RenderRuleAsWarning(T.Get("setup.ruleAppCreation.warningAll"));
}
@if (Model.IsAssetStoreFtp)
{
RenderRuleAsWarning(T.Get("setup.ruleFtp.warning"));
}
@if (Model.IsAssetStoreFile)
{
RenderRuleAsWarning(T.Get("setup.ruleFolder.warning"));
}
</div>
<hr /> <img style="height: 250px" class="mt-2 mb-2" src="@Url.RootContentUrl("~/squid.svg?title=Welcome&text=Welcome%20to%20the%20Installation%20Process&face=happy")" />
<div class="profile-section"> <small class="form-text text-muted mt-2 mb-2">@T.Get("setup.hint")</small>
<h2>@T.Get("setup.createUser.headline")</h2>
@if (Model.HasExternalLogin) <div class="profile-section">
{ <h2>@T.Get("setup.rules.headline")</h2>
<div>
<small class="form-text text-muted mt-2 mb-2">@T.Get("setup.createUser.loginHint")</small>
<div class="mt-3"> @if (Model.IsValidHttps)
<a class="btn btn-primary" asp-controller="Account" asp-action="Login"> {
@T.Get("setup.createUser.loginLink") RenderRuleAsSuccess(T.Get("setup.ruleHttps.success"));
</a> }
</div> else
</div> {
} RenderRuleAsCritical(T.Get("setup.ruleHttps.failure"));
}
@if (Model.HasExternalLogin && Model.HasPasswordAuth) @if (Model.BaseUrlConfigured == Model.BaseUrlCurrent)
{ {
<div class="profile-separator"> RenderRuleAsSuccess(T.Get("setup.ruleUrl.success"));
<div class="profile-separator-text">@T.Get("setup.createUser.separator")</div> }
</div> else
} {
RenderRuleAsCritical(T.Get("setup.ruleUrl.failure", new { actual = Model.BaseUrlCurrent, configured = Model.BaseUrlConfigured }));
}
@if (Model.HasPasswordAuth) @if (Model.EverybodyCanCreateApps)
{ {
<h3>@T.Get("setup.createUser.headlineCreate")</h3> RenderRuleAsWarning(T.Get("setup.ruleAppCreation.warningAdmins"));
}
else
{
RenderRuleAsWarning(T.Get("setup.ruleAppCreation.warningAll"));
}
@if (!string.IsNullOrWhiteSpace(Model.ErrorMessage)) @if (Model.IsAssetStoreFtp)
{ {
<div class="form-alert form-alert-error"> RenderRuleAsWarning(T.Get("setup.ruleFtp.warning"));
@Model.ErrorMessage }
</div>
}
<form class="profile-form" asp-controller="Setup" asp-action="Setup" method="post"> @if (Model.IsAssetStoreFile)
<div class="form-group"> {
<label for="email">@T.Get("common.email")</label> RenderRuleAsWarning(T.Get("setup.ruleFolder.warning"));
}
</div>
@{ RenderValidation("Email"); } <hr />
<input type="text" class="form-control" name="email" id="email" /> <div class="profile-section">
</div> <h2>@T.Get("setup.createUser.headline")</h2>
<div class="form-group"> @if (Model.HasExternalLogin)
<label for="password">@T.Get("common.password")</label> {
<div>
<small class="form-text text-muted mt-2 mb-2">@T.Get("setup.createUser.loginHint")</small>
@{ RenderValidation("Password"); } <div class="mt-3">
<a class="btn btn-primary" asp-controller="Account" asp-action="Login">
@T.Get("setup.createUser.loginLink")
</a>
</div>
</div>
}
<input type="password" class="form-control" name="password" id="password" /> @if (Model.HasExternalLogin && Model.HasPasswordAuth)
</div> {
<div class="profile-separator">
<div class="profile-separator-text">@T.Get("setup.createUser.separator")</div>
</div>
}
<div class="form-group"> @if (Model.HasPasswordAuth)
<label for="passwordConfirm">@T.Get("setup.createUser.confirmPassword")</label> {
<h3>@T.Get("setup.createUser.headlineCreate")</h3>
@{ RenderValidation("PasswordConfirm"); } @if (!string.IsNullOrWhiteSpace(Model.ErrorMessage))
{
<div class="form-alert form-alert-error">
@Model.ErrorMessage
</div>
}
<input type="password" class="form-control" name="passwordConfirm" id="passwordConfirm" /> <form class="profile-form" asp-controller="Setup" asp-action="Setup" method="post">
</div> <div class="form-group">
<label for="email">@T.Get("common.email")</label>
<div class="form-group"> @{ RenderValidation("Email"); }
<button type="submit" class="btn btn-success">@T.Get("setup.createUser.button")</button>
</div>
</form>
}
@if (!Model.HasExternalLogin && !Model.HasPasswordAuth) <input type="text" class="form-control" name="email" id="email" />
{ </div>
<div>
@T.Get("setup.createUser.failure")
</div>
}
</div>
</div>
</div>
<div class="text-center mt-4 mb-2"> <div class="form-group">
<small class="text-muted"> <label for="password">@T.Get("common.password")</label>
@T.Get("setup.madeBy")<br />@T.Get("setup.madeByCopyright")
</small> @{ RenderValidation("Password"); }
</div>
<input type="password" class="form-control" name="password" id="password" />
</div>
<div class="form-group">
<label for="passwordConfirm">@T.Get("setup.createUser.confirmPassword")</label>
@{ RenderValidation("PasswordConfirm"); }
<input type="password" class="form-control" name="passwordConfirm" id="passwordConfirm" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-success">@T.Get("setup.createUser.button")</button>
</div>
</form>
}
@if (!Model.HasExternalLogin && !Model.HasPasswordAuth)
{
<div>
@T.Get("setup.createUser.failure")
</div>
}
</div>

16
backend/src/Squidex/Areas/IdentityServer/Views/_Layout.cshtml

@ -17,11 +17,21 @@
@await RenderSectionAsync("header") @await RenderSectionAsync("header")
} }
</head> </head>
<body class="@ViewBag.ThemeColor"> <body class="profile">
<div class="profile @ViewBag.ThemeSize"> <div class="profile-container">
<img class="profile-logo" alt="@T.Get("common.product")S" title="@T.Get("common.product")" src="@Url.RootContentUrl("~/images/logo.svg")" /> <img class="profile-logo" alt="@T.Get("common.product")S" title="@T.Get("common.product")" src="@Url.RootContentUrl("~/images/logo.svg")" />
@RenderBody() <div class="profile-card card">
<div class="profile-card-body card-body">
@RenderBody()
</div>
</div>
<div class="profile-footer text-center mt-4 mb-2">
<small class="text-muted">
@T.Get("setup.madeBy")<br />@T.Get("setup.madeByCopyright")
</small>
</div>
</div> </div>
<environment names="Development"> <environment names="Development">

Loading…
Cancel
Save