From f35d133e610a800f747789cad2e113572bab8717 Mon Sep 17 00:00:00 2001 From: hyzx86 Date: Thu, 22 Feb 2024 14:39:48 +0800 Subject: [PATCH 1/3] Add UserPickerField --- .../GraphQL/Startup.cs | 3 +- .../Types/UserPickerFieldQueryObjectType.cs | 71 +++++++++++++++++++ .../OrchardCore.ContentFields.csproj | 1 + .../OrchardCore.Users/GraphQL/Startup.cs | 2 +- 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs index 7baaf362ede..c13376033b8 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs @@ -8,7 +8,7 @@ namespace OrchardCore.ContentFields.GraphQL { - [RequireFeatures("OrchardCore.Apis.GraphQL")] + [RequireFeatures("OrchardCore.Apis.GraphQL","OrchardCore.Users")] public class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services) @@ -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..fec5a347625 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs @@ -0,0 +1,71 @@ +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() + { + Name = nameof(UserPickerField); + + Field, IEnumerable>("userIds") + .Description("user ids") + .PagingArguments() + .Resolve(x => + { + return x.Page(x.Source.UserIds); + }); + + Field, IEnumerable>("users") + .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") + .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..90ff703ac1d 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.AddSingleton(); } } From d85bc64a50064ad9e419bbf33432b752fb8c19ff Mon Sep 17 00:00:00 2001 From: hyzx86 Date: Fri, 23 Feb 2024 01:36:33 +0800 Subject: [PATCH 2/3] fix query --- .../Types/UserPickerFieldQueryObjectType.cs | 4 ++- .../OrchardCore.Users/GraphQL/Startup.cs | 2 +- .../OrchardCore.Users/GraphQL/UserType.cs | 36 ++++++++++--------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs index fec5a347625..07f253d4a85 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Types/UserPickerFieldQueryObjectType.cs @@ -17,7 +17,7 @@ namespace OrchardCore.ContentFields.GraphQL { public class UserPickerFieldQueryObjectType : ObjectGraphType { - public UserPickerFieldQueryObjectType() + public UserPickerFieldQueryObjectType(UserType userType) { Name = nameof(UserPickerField); @@ -30,6 +30,7 @@ public UserPickerFieldQueryObjectType() }); Field, IEnumerable>("users") + .Type(new ListGraphType(userType)) .Description("the user items") .PagingArguments() .ResolveAsync(x => @@ -41,6 +42,7 @@ public UserPickerFieldQueryObjectType() }); }); Field("user") + .Type(userType) .Description("the first user") .ResolveAsync(x => { diff --git a/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Users/GraphQL/Startup.cs index 90ff703ac1d..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.AddSingleton(); + 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; + }); } } From 1418b06fce7d8e69262d6b1fb0912971cb8de60d Mon Sep 17 00:00:00 2001 From: hyzx86 Date: Fri, 23 Feb 2024 10:04:42 +0800 Subject: [PATCH 3/3] update dependency --- .../OrchardCore.ContentFields/GraphQL/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs index c13376033b8..6eff7d9ab16 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/GraphQL/Startup.cs @@ -8,7 +8,7 @@ namespace OrchardCore.ContentFields.GraphQL { - [RequireFeatures("OrchardCore.Apis.GraphQL","OrchardCore.Users")] + [RequireFeatures("OrchardCore.Apis.GraphQL")] public class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services)