diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs index 7baaf362ede..6eff7d9ab16 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs @@ -19,6 +19,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddObjectGraphType(); services.AddObjectGraphType(); services.AddObjectGraphType(); + services.AddObjectGraphType(); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs new file mode 100644 index 00000000000..07f253d4a85 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using GraphQL; +using GraphQL.DataLoader; +using GraphQL.Types; +using Microsoft.Extensions.DependencyInjection; +using OrchardCore.Apis.GraphQL; +using OrchardCore.ContentFields.Fields; +using OrchardCore.ContentManagement; +using OrchardCore.Users.GraphQL; +using OrchardCore.Users.Indexes; +using OrchardCore.Users.Models; +using YesSql; +using YesSql.Services; + +namespace OrchardCore.ContentFields.GraphQL +{ + public class UserPickerFieldQueryObjectType : ObjectGraphType + { + public UserPickerFieldQueryObjectType(UserType userType) + { + Name = nameof(UserPickerField); + + Field, IEnumerable>("userIds") + .Description("user ids") + .PagingArguments() + .Resolve(x => + { + return x.Page(x.Source.UserIds); + }); + + Field, IEnumerable>("users") + .Type(new ListGraphType(userType)) + .Description("the user items") + .PagingArguments() + .ResolveAsync(x => + { + var userLoader = GetOrAddUserProfileByIdDataLoader(x); + return userLoader.LoadAsync(x.Page(x.Source.UserIds)).Then(itemResultSet => + { + return itemResultSet.SelectMany(x => x); + }); + }); + Field("user") + .Type(userType) + .Description("the first user") + .ResolveAsync(x => + { + var userLoader = GetOrAddUserProfileByIdDataLoader(x); + return userLoader.LoadAsync(x.Source.UserIds.FirstOrDefault()).Then(itemResultSet => + { + return itemResultSet.FirstOrDefault(); + }); + }); + } + + public static IDataLoader> GetOrAddUserProfileByIdDataLoader(IResolveFieldContext context) + { + IDataLoaderContextAccessor requiredService = context.RequestServices.GetRequiredService(); + var session = context.RequestServices.GetService(); + return requiredService.Context.GetOrAddCollectionBatchLoader("GetOrAddUserByIds", async (IEnumerable userIds) => + { + if (userIds == null || !userIds.Any()) + { + return null; + } + var users = await session.Query(y => y.UserId.IsIn(userIds)).ListAsync(); + + return users.ToLookup((User k) => k.UserId, (User user) => user); + }); + } + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj b/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj index d50cedac85f..1e75bfb884f 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj @@ -29,6 +29,7 @@ + diff --git a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs index 4dba4a80de3..85daf5d706f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs @@ -10,6 +10,6 @@ public class Startup : StartupBase public override void ConfigureServices(IServiceCollection services) { services.AddSingleton(); - services.AddTransient(); + services.AddScoped(); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs index f5d1818a94a..c1c09a4de73 100644 --- a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs +++ b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/UserType.cs @@ -3,6 +3,8 @@ using GraphQL.Types; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.GraphQL.Queries.Types; using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.Users.Models; using OrchardCore.Users.Services; @@ -30,27 +32,29 @@ public UserType(IStringLocalizer localizer) internal void AddField(ISchema schema, ContentTypeDefinition typeDefinition) { var contentItemType = schema.AdditionalTypeInstances.SingleOrDefault(t => t.Name == typeDefinition.Name); - + if (contentItemType == null) { // This error would indicate that this graph type is build too early. throw new InvalidOperationException("ContentTypeDefinition has not been registered in GraphQL"); } - var field = Field(typeDefinition.Name, contentItemType.GetType()) - .Description(S["Custom user settings of {0}.", typeDefinition.DisplayName]) - .ResolveAsync(static async context => { - // We don't want to create an empty content item if it does not exist. - if (context.Source is User user && - user.Properties.ContainsKey(context.FieldDefinition.ResolvedType.Name)) - { - var customUserSettingsService = context.RequestServices!.GetRequiredService(); - var settingsType = await customUserSettingsService.GetSettingsTypeAsync(context.FieldDefinition.ResolvedType.Name); - - return await customUserSettingsService.GetSettingsAsync(user, settingsType); - } - - return null; - }); + Field(typeDefinition.Name) + .Type(contentItemType) + .Description(S["Custom user settings of {0}.", typeDefinition.DisplayName]) + .ResolveAsync(static async context => + { + // We don't want to create an empty content item if it does not exist. + if (context.Source is User user && + user.Properties.ContainsKey(context.FieldDefinition.ResolvedType.Name)) + { + var customUserSettingsService = context.RequestServices!.GetRequiredService(); + var settingsType = await customUserSettingsService.GetSettingsTypeAsync(context.FieldDefinition.ResolvedType.Name); + + return await customUserSettingsService.GetSettingsAsync(user, settingsType); + } + + return null; + }); } }