From a85d49c25c470e49dc9b151332b974135bb412f8 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 3 Sep 2019 22:07:49 +0200 Subject: [PATCH] Pagination for contributors. (#408) * Pagination for contributors. --- .../DefaultUserResolver.cs | 8 ++ .../UserManagerExtensions.cs | 9 +++ src/Squidex.Shared/Users/IUserResolver.cs | 3 + .../Controllers/Apps/AppClientsController.cs | 9 ++- .../Apps/AppContributorsController.cs | 19 +++-- .../Apps/AppLanguagesController.cs | 9 ++- .../Controllers/Apps/AppPatternsController.cs | 9 ++- .../Controllers/Apps/AppRolesController.cs | 9 ++- .../Apps/AppWorkflowsController.cs | 9 ++- .../Controllers/Apps/Models/AppLanguageDto.cs | 6 +- .../Apps/Models/AppLanguagesDto.cs | 6 +- .../Api/Controllers/Apps/Models/ClientDto.cs | 6 +- .../Api/Controllers/Apps/Models/ClientsDto.cs | 10 ++- .../Controllers/Apps/Models/ContributorDto.cs | 30 +++++++- .../Apps/Models/ContributorsDto.cs | 38 +++++++-- .../Api/Controllers/Apps/Models/RoleDto.cs | 20 +++-- .../Api/Controllers/Apps/Models/RolesDto.cs | 11 ++- .../Controllers/Apps/Models/WorkflowDto.cs | 9 ++- .../Controllers/Apps/Models/WorkflowsDto.cs | 10 ++- .../Contents/Models/ContentsDto.cs | 9 +-- .../services/event-consumers.service.spec.ts | 8 +- .../contributors-page.component.html | 72 ++++++++++------- .../contributors-page.component.ts | 12 +++ .../angular/forms/dropdown.component.ts | 16 ++-- .../app/framework/angular/highlight.pipe.ts | 10 ++- .../shared/services/assets.service.spec.ts | 8 +- .../shared/services/contents.service.spec.ts | 8 +- .../services/contributors.service.spec.ts | 6 +- .../shared/services/contributors.service.ts | 2 + .../app/shared/services/rules.service.spec.ts | 8 +- .../shared/services/schemas.service.spec.ts | 16 ++-- src/Squidex/app/shared/state/clients.state.ts | 8 +- .../app/shared/state/contents.state.ts | 2 +- .../shared/state/contributors.state.spec.ts | 77 ++++++++++++++++--- .../app/shared/state/contributors.state.ts | 75 ++++++++++++++++-- src/Squidex/app/shared/state/rules.state.ts | 7 +- src/Squidex/app/theme/_lists.scss | 8 ++ tools/LoadTest/TestUtils.cs | 31 ++++++++ tools/LoadTest/WritingBenchmarks.cs | 1 - 39 files changed, 475 insertions(+), 139 deletions(-) create mode 100644 tools/LoadTest/TestUtils.cs diff --git a/src/Squidex.Domain.Users/DefaultUserResolver.cs b/src/Squidex.Domain.Users/DefaultUserResolver.cs index 49723af01..b03abae64 100644 --- a/src/Squidex.Domain.Users/DefaultUserResolver.cs +++ b/src/Squidex.Domain.Users/DefaultUserResolver.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -69,5 +70,12 @@ namespace Squidex.Domain.Users return result.OfType().ToList(); } + + public async Task> QueryManyAsync(string[] ids) + { + var result = await userManager.QueryByIdsAync(ids); + + return result.OfType().ToDictionary(x => x.Id); + } } } diff --git a/src/Squidex.Domain.Users/UserManagerExtensions.cs b/src/Squidex.Domain.Users/UserManagerExtensions.cs index 94176bfc0..4217194c0 100644 --- a/src/Squidex.Domain.Users/UserManagerExtensions.cs +++ b/src/Squidex.Domain.Users/UserManagerExtensions.cs @@ -85,6 +85,15 @@ namespace Squidex.Domain.Users return Task.FromResult(count); } + public static async Task> QueryByIdsAync(this UserManager userManager, string[] ids) + { + var users = userManager.Users.Where(x => ids.Contains(x.Id)).ToList(); + + var result = await userManager.ResolveUsersAsync(users); + + return result.ToList(); + } + public static async Task> QueryByEmailAsync(this UserManager userManager, string email = null, int take = 10, int skip = 0) { var users = QueryUsers(userManager, email).Skip(skip).Take(take).ToList(); diff --git a/src/Squidex.Shared/Users/IUserResolver.cs b/src/Squidex.Shared/Users/IUserResolver.cs index 29f3b541a..4406107a8 100644 --- a/src/Squidex.Shared/Users/IUserResolver.cs +++ b/src/Squidex.Shared/Users/IUserResolver.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -17,5 +18,7 @@ namespace Squidex.Shared.Users Task FindByIdOrEmailAsync(string idOrEmail); Task> QueryByEmailAsync(string email); + + Task> QueryManyAsync(string[] ids); } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs index 7ce6c79b8..fb444d2a3 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs @@ -48,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Apps { var response = Deferred.Response(() => { - return ClientsDto.FromApp(App, this); + return GetResponse(App); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); @@ -143,9 +143,14 @@ namespace Squidex.Areas.Api.Controllers.Apps var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = ClientsDto.FromApp(result, this); + var response = GetResponse(result); return response; } + + private ClientsDto GetResponse(IAppEntity app) + { + return ClientsDto.FromApp(App, this); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs index fda51ba82..7d5e1ed37 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs @@ -15,6 +15,7 @@ using Squidex.Domain.Apps.Entities.Apps.Invitation; using Squidex.Domain.Apps.Entities.Apps.Services; using Squidex.Infrastructure.Commands; using Squidex.Shared; +using Squidex.Shared.Users; using Squidex.Web; namespace Squidex.Areas.Api.Controllers.Apps @@ -26,11 +27,14 @@ namespace Squidex.Areas.Api.Controllers.Apps public sealed class AppContributorsController : ApiController { private readonly IAppPlansProvider appPlansProvider; + private readonly IUserResolver userResolver; - public AppContributorsController(ICommandBus commandBus, IAppPlansProvider appPlansProvider) + public AppContributorsController(ICommandBus commandBus, IAppPlansProvider appPlansProvider, IUserResolver userResolver) : base(commandBus) { this.appPlansProvider = appPlansProvider; + + this.userResolver = userResolver; } /// @@ -48,9 +52,9 @@ namespace Squidex.Areas.Api.Controllers.Apps [ApiCosts(0)] public IActionResult GetContributors(string app) { - var response = Deferred.Response(() => + var response = Deferred.AsyncResponse(() => { - return ContributorsDto.FromApp(App, appPlansProvider, this, false); + return GetResponseAsync(App, false); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); @@ -112,12 +116,17 @@ namespace Squidex.Areas.Api.Controllers.Apps if (context.PlainResult is InvitedResult invited) { - return ContributorsDto.FromApp(invited.App, appPlansProvider, this, true); + return await GetResponseAsync(invited.App, true); } else { - return ContributorsDto.FromApp(context.Result(), appPlansProvider, this, false); + return await GetResponseAsync(context.Result(), false); } } + + private Task GetResponseAsync(IAppEntity app, bool invited) + { + return ContributorsDto.FromAppAsync(app, this, userResolver, appPlansProvider, invited); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs index 43498aa82..f76da205d 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs @@ -47,7 +47,7 @@ namespace Squidex.Areas.Api.Controllers.Apps { var response = Deferred.Response(() => { - return AppLanguagesDto.FromApp(App, this); + return GetResponse(App); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); @@ -132,11 +132,16 @@ namespace Squidex.Areas.Api.Controllers.Apps var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = AppLanguagesDto.FromApp(result, this); + var response = GetResponse(result); return response; } + private AppLanguagesDto GetResponse(IAppEntity result) + { + return AppLanguagesDto.FromApp(result, this); + } + private static Language ParseLanguage(string language) { try diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs index 31b788e83..da58aade8 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs @@ -49,7 +49,7 @@ namespace Squidex.Areas.Api.Controllers.Apps { var response = Deferred.Response(() => { - return PatternsDto.FromApp(App, this); + return GetResponse(App); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); @@ -137,9 +137,14 @@ namespace Squidex.Areas.Api.Controllers.Apps var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = PatternsDto.FromApp(result, this); + var response = GetResponse(result); return response; } + + private PatternsDto GetResponse(IAppEntity result) + { + return PatternsDto.FromApp(result, this); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs index 2961a91b7..8a3aef0ba 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs @@ -49,7 +49,7 @@ namespace Squidex.Areas.Api.Controllers.Apps { var response = Deferred.Response(() => { - return RolesDto.FromApp(App, this); + return GetResponse(App); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); @@ -160,9 +160,14 @@ namespace Squidex.Areas.Api.Controllers.Apps var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = RolesDto.FromApp(result, this); + var response = GetResponse(result); return response; } + + private RolesDto GetResponse(IAppEntity result) + { + return RolesDto.FromApp(result, this); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs b/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs index 9f798add0..09c8c93d1 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs @@ -50,7 +50,7 @@ namespace Squidex.Areas.Api.Controllers.Apps { var response = Deferred.AsyncResponse(() => { - return WorkflowsDto.FromAppAsync(workflowsValidator, App, this); + return GetResponse(App); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); @@ -135,9 +135,14 @@ namespace Squidex.Areas.Api.Controllers.Apps var context = await CommandBus.PublishAsync(command); var result = context.Result(); - var response = await WorkflowsDto.FromAppAsync(workflowsValidator, result, this); + var response = await GetResponse(result); return response; } + + private async Task GetResponse(IAppEntity result) + { + return await WorkflowsDto.FromAppAsync(workflowsValidator, result, this); + } } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs index 85f6ef7ce..43992079e 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs @@ -46,7 +46,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models /// public bool IsOptional { get; set; } - public static AppLanguageDto FromLanguage(LanguageConfig language, IAppEntity app, ApiController controller) + public static AppLanguageDto FromLanguage(LanguageConfig language, IAppEntity app) { var result = SimpleMapper.Map(language.Language, new AppLanguageDto @@ -56,10 +56,10 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models Fallback = language.LanguageFallbacks.ToArray() }); - return result.CreateLinks(controller, app); + return result; } - private AppLanguageDto CreateLinks(ApiController controller, IAppEntity app) + public AppLanguageDto WithLinks(ApiController controller, IAppEntity app) { var values = new { app = app.Name, language = Iso2Code }; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs index 77580f5e9..11c2063f9 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs @@ -27,9 +27,9 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models var result = new AppLanguagesDto { Items = app.LanguagesConfig.OfType() - .Select(x => AppLanguageDto.FromLanguage(x, app, controller)) - .OrderByDescending(x => x.IsMaster) - .ThenBy(x => x.Iso2Code) + .Select(x => AppLanguageDto.FromLanguage(x, app)) + .Select(x => x.WithLinks(controller, app)) + .OrderByDescending(x => x.IsMaster).ThenBy(x => x.Iso2Code) .ToArray() }; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs index a7a344251..6781ee20b 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs @@ -38,14 +38,14 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models /// public string Role { get; set; } - public static ClientDto FromClient(string id, AppClient client, ApiController controller, string app) + public static ClientDto FromClient(string id, AppClient client) { var result = SimpleMapper.Map(client, new ClientDto { Id = id }); - return result.CreateLinks(controller, app); + return result; } - private ClientDto CreateLinks(ApiController controller, string app) + public ClientDto WithLinks(ApiController controller, string app) { var values = new { app, id = Id }; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs index 7116e99f2..1d456251e 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs @@ -23,12 +23,18 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models public static ClientsDto FromApp(IAppEntity app, ApiController controller) { + var appName = app.Name; + var result = new ClientsDto { - Items = app.Clients.Select(x => ClientDto.FromClient(x.Key, x.Value, controller, app.Name)).ToArray() + Items = + app.Clients + .Select(x => ClientDto.FromClient(x.Key, x.Value)) + .Select(x => x.WithLinks(controller, appName)) + .ToArray() }; - return result.CreateLinks(controller, app.Name); + return result.CreateLinks(controller, appName); } private ClientsDto CreateLinks(ApiController controller, string app) diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs index 4929ed76b..9efa1133a 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs @@ -5,33 +5,57 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Squidex.Shared; +using Squidex.Shared.Users; using Squidex.Web; namespace Squidex.Areas.Api.Controllers.Apps.Models { public sealed class ContributorDto : Resource { + private const string NotFound = "- not found -"; + /// /// The id of the user that contributes to the app. /// [Required] public string ContributorId { get; set; } + /// + /// The display name. + /// + [Required] + public string ContributorName { get; set; } + /// /// The role of the contributor. /// public string Role { get; set; } - public static ContributorDto FromIdAndRole(string id, string role, ApiController controller, string app) + public static ContributorDto FromIdAndRole(string id, string role) { var result = new ContributorDto { ContributorId = id, Role = role }; - return result.CreateLinks(controller, app); + return result; + } + + public ContributorDto WithUser(IDictionary users) + { + if (users.TryGetValue(ContributorId, out var user)) + { + ContributorName = user.DisplayName(); + } + else + { + ContributorName = NotFound; + } + + return this; } - private ContributorDto CreateLinks(ApiController controller, string app) + public ContributorDto WithLinks(ApiController controller, string app) { if (!controller.IsUser(ContributorId)) { diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs index 540725c75..805a7e227 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs @@ -5,12 +5,15 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Threading.Tasks; using Newtonsoft.Json; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.Services; using Squidex.Shared; +using Squidex.Shared.Users; using Squidex.Web; namespace Squidex.Areas.Api.Controllers.Apps.Models @@ -29,29 +32,50 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models public int MaxContributors { get; set; } /// - /// The metadata. + /// The metadata to provide information about this request. /// [JsonProperty("_meta")] public ContributorsMetadata Metadata { get; set; } - public static ContributorsDto FromApp(IAppEntity app, IAppPlansProvider plans, ApiController controller, bool isInvited) + public static async Task FromAppAsync(IAppEntity app, ApiController controller, IUserResolver userResolver, IAppPlansProvider plans, bool invited) { + var users = await userResolver.QueryManyAsync(app.Contributors.Keys.ToArray()); + var result = new ContributorsDto { - Items = app.Contributors.Select(x => ContributorDto.FromIdAndRole(x.Key, x.Value, controller, app.Name)).ToArray(), + Items = + app.Contributors + .Select(x => ContributorDto.FromIdAndRole(x.Key, x.Value)) + .Select(x => x.WithUser(users)) + .Select(x => x.WithLinks(controller, app.Name)) + .OrderBy(x => x.ContributorName) + .ToArray() }; + result.WithInvited(invited); + result.WithPlan(app, plans); + + return result.CreateLinks(controller, app.Name); + } + + private ContributorsDto WithPlan(IAppEntity app, IAppPlansProvider plans) + { + MaxContributors = plans.GetPlanForApp(app).MaxContributors; + + return this; + } + + private ContributorsDto WithInvited(bool isInvited) + { if (isInvited) { - result.Metadata = new ContributorsMetadata + Metadata = new ContributorsMetadata { IsInvited = isInvited.ToString() }; } - result.MaxContributors = plans.GetPlanForApp(app).MaxContributors; - - return result.CreateLinks(controller, app.Name); + return this; } private ContributorsDto CreateLinks(ApiController controller, string app) diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs index ff0ddf201..1617c69a6 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs @@ -44,23 +44,33 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models [Required] public IEnumerable Permissions { get; set; } - public static RoleDto FromRole(Role role, IAppEntity app, ApiController controller) + public static RoleDto FromRole(Role role, IAppEntity app) { var permissions = role.Permissions.WithoutApp(app.Name); var result = new RoleDto { Name = role.Name, - NumClients = app.Clients.Count(x => Role.IsRole(x.Value.Role, role.Name)), - NumContributors = app.Contributors.Count(x => Role.IsRole(x.Value, role.Name)), + NumClients = GetNumClients(role, app), + NumContributors = GetNumContributors(role, app), Permissions = permissions.ToIds(), IsDefaultRole = Role.IsDefaultRole(role.Name) }; - return result.CreateLinks(controller, app.Name); + return result; } - private RoleDto CreateLinks(ApiController controller, string app) + private static int GetNumContributors(Role role, IAppEntity app) + { + return app.Contributors.Count(x => Role.IsRole(x.Value, role.Name)); + } + + private static int GetNumClients(Role role, IAppEntity app) + { + return app.Clients.Count(x => Role.IsRole(x.Value.Role, role.Name)); + } + + public RoleDto WithLinks(ApiController controller, string app) { var values = new { app, name = Name }; diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs index b43c32041..c7daa77df 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs @@ -23,12 +23,19 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models public static RolesDto FromApp(IAppEntity app, ApiController controller) { + var appName = app.Name; + var result = new RolesDto { - Items = app.Roles.Values.Select(x => RoleDto.FromRole(x, app, controller)).OrderBy(x => x.Name).ToArray() + Items = + app.Roles.Values + .Select(x => RoleDto.FromRole(x, app)) + .Select(x => x.WithLinks(controller, appName)) + .OrderBy(x => x.Name) + .ToArray() }; - return result.CreateLinks(controller, app.Name); + return result.CreateLinks(controller, appName); } private RolesDto CreateLinks(ApiController controller, string app) diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs index 1601340cc..b026d6dba 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Entities.Apps; using Squidex.Infrastructure.Reflection; using Squidex.Shared; using Squidex.Web; @@ -44,7 +45,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models /// public Status Initial { get; set; } - public static WorkflowDto FromWorkflow(Guid id, Workflow workflow, ApiController controller, string app) + public static WorkflowDto FromWorkflow(Guid id, Workflow workflow) { var result = SimpleMapper.Map(workflow, new WorkflowDto { @@ -54,12 +55,12 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models Id = id }); - return result.CreateLinks(controller, app, id); + return result; } - private WorkflowDto CreateLinks(ApiController controller, string app, Guid id) + public WorkflowDto WithLinks(ApiController controller, string app) { - var values = new { app, id }; + var values = new { app, id = Id }; if (controller.HasPermission(Permissions.AppWorkflowsUpdate, app)) { diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs index 5e3515eba..d95aa9a3d 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs @@ -31,16 +31,22 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models public static async Task FromAppAsync(IWorkflowsValidator workflowsValidator, IAppEntity app, ApiController controller) { + var appName = app.Name; + var result = new WorkflowsDto { - Items = app.Workflows.Select(x => WorkflowDto.FromWorkflow(x.Key, x.Value, controller, app.Name)).ToArray(), + Items = + app.Workflows + .Select(x => WorkflowDto.FromWorkflow(x.Key, x.Value)) + .Select(x => x.WithLinks(controller, appName)) + .ToArray() }; var errors = await workflowsValidator.ValidateAsync(app.Id, app.Workflows); result.Errors = errors.ToArray(); - return result.CreateLinks(controller, app.Name); + return result.CreateLinks(controller, appName); } private WorkflowsDto CreateLinks(ApiController controller, string app) diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs index 2f2b2afcc..83ed3a14b 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs @@ -36,8 +36,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models [Required] public StatusInfoDto[] Statuses { get; set; } - public static async Task FromContentsAsync(IResultList contents, - Context context, ApiController controller, ISchemaEntity schema, IContentWorkflow contentWorkflow) + public static async Task FromContentsAsync(IResultList contents, Context context, ApiController controller, ISchemaEntity schema, IContentWorkflow workflow) { var result = new ContentsDto { @@ -45,14 +44,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models Items = contents.Select(x => ContentDto.FromContent(context, x, controller)).ToArray() }; - await result.AssignStatusesAsync(contentWorkflow, schema); + await result.AssignStatusesAsync(workflow, schema); return result.CreateLinks(controller, schema.AppId.Name, schema.SchemaDef.Name); } - private async Task AssignStatusesAsync(IContentWorkflow contentWorkflow, ISchemaEntity schema) + private async Task AssignStatusesAsync(IContentWorkflow workflow, ISchemaEntity schema) { - var allStatuses = await contentWorkflow.GetAllAsync(schema); + var allStatuses = await workflow.GetAllAsync(schema); Statuses = allStatuses.Select(StatusInfoDto.FromStatusInfo).ToArray(); } diff --git a/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts b/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts index 6815d1093..8bb0607c2 100644 --- a/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts +++ b/src/Squidex/app/features/administration/services/event-consumers.service.spec.ts @@ -139,10 +139,10 @@ describe('EventConsumersService', () => { function eventConsumerResponse(id: number) { return { name: `event-consumer${id}`, - position: `position-${id}`, + position: `position${id}`, isStopped: true, isResetting: true, - error: `failure-${id}`, + error: `failure${id}`, _links: { reset: { method: 'PUT', href: `/event-consumers/${id}/reset` } } @@ -159,6 +159,6 @@ export function createEventConsumer(id: number, suffix = '') { `event-consumer${id}`, true, true, - `failure-${id}${suffix}`, - `position-${id}${suffix}`); + `failure${id}${suffix}`, + `position${id}${suffix}`); } \ No newline at end of file diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html index 011e94b55..3242e97b4 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html @@ -6,11 +6,17 @@ - + +
+ +
@@ -21,33 +27,43 @@ - - - - - - - - - - - -
- - - {{contributor.contributorId | sqxUserName}} - - - - -
+ + + + + + + + + + + + +
+ + + + + + + +
+ + +
+ + +
+ No contributors found. +
+