From d173b94e497d24bd3d0437d56381e5041ef75c9d Mon Sep 17 00:00:00 2001 From: sudan45 Date: Fri, 29 Dec 2023 13:43:43 +0545 Subject: [PATCH 1/2] add project count in analysisframework schema --- apps/analysis_framework/schema.py | 7 ++++++- schema.graphql | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/analysis_framework/schema.py b/apps/analysis_framework/schema.py index 33f7a249f3..1cb8a63f52 100644 --- a/apps/analysis_framework/schema.py +++ b/apps/analysis_framework/schema.py @@ -11,7 +11,7 @@ from utils.graphene.fields import DjangoPaginatedListObjectField, generate_type_for_serializer from deep.permissions import AnalysisFrameworkPermissions as AfP from project.schema import AnalysisFrameworkVisibleProjectType -from project.models import ProjectMembership +from project.models import ProjectMembership, Project from assisted_tagging.models import PredictionTagAnalysisFrameworkWidgetMapping from .models import ( AnalysisFramework, @@ -122,6 +122,7 @@ class Meta: ), required=True, ) + used_in_project_count = graphene.Int(required=True) @staticmethod def get_custom_node(_, info, id): @@ -147,6 +148,10 @@ def resolve_allowed_permissions(root, info): def resolve_tags(root, info): return info.context.dl.analysis_framework.af_tags.load(root.id) + @staticmethod + def resolve_used_in_project_count(root, info): + return Project.objects.filter(analysis_framework=root.id, is_test=False).count() + class AnalysisFrameworkRoleType(DjangoObjectType): class Meta: diff --git a/schema.graphql b/schema.graphql index 73913f8d9a..68dc8203dc 100644 --- a/schema.graphql +++ b/schema.graphql @@ -50,6 +50,7 @@ type AnalysisFrameworkDetailType { clonedFrom: ID allowedPermissions: [AnalysisFrameworkPermission!]! tags: [AnalysisFrameworkTagType!]! + usedInProjectCount: Int primaryTagging: [SectionType!] secondaryTagging: [WidgetType!] members: [AnalysisFrameworkMembershipType!] @@ -218,6 +219,7 @@ type AnalysisFrameworkType { clonedFrom: ID allowedPermissions: [AnalysisFrameworkPermission!]! tags: [AnalysisFrameworkTagType!]! + usedInProjectCount: Int } type AnalysisFrameworkVisibleProjectType { From 5fb57f5f5e03d3fab2b18519633c06a90a53237c Mon Sep 17 00:00:00 2001 From: sudan45 Date: Fri, 29 Dec 2023 14:25:37 +0545 Subject: [PATCH 2/2] add dataloader for project count --- apps/analysis_framework/dataloaders.py | 37 ++++++++++++++++++++++++++ apps/analysis_framework/schema.py | 11 +++++--- schema.graphql | 9 +++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/apps/analysis_framework/dataloaders.py b/apps/analysis_framework/dataloaders.py index 3e60585cdd..c4508144a7 100644 --- a/apps/analysis_framework/dataloaders.py +++ b/apps/analysis_framework/dataloaders.py @@ -3,6 +3,7 @@ from promise import Promise from django.utils.functional import cached_property from django.db import models +from project.models import Project from utils.graphene.dataloaders import DataLoaderWithContext, WithContextMixin @@ -102,6 +103,38 @@ def batch_load_fn(self, keys): return Promise.resolve([_map[key] for key in keys]) +class AnalysisFrameworkProjectCountLoader(DataLoaderWithContext): + def batch_load_fn(self, keys): + stat_qs = Project.objects\ + .filter(analysis_framework__in=keys)\ + .order_by('analysis_framework').values('analysis_framework')\ + .annotate( + project_count=models.functions.Coalesce( + models.Count( + 'id', + filter=models.Q(is_test=False) + ), + 0, + ), + test_project_count=models.functions.Coalesce( + models.Count( + 'id', + filter=models.Q(is_test=True) + ), + 0, + ), + ).values('analysis_framework', 'project_count', 'test_project_count') + _map = { + stat.pop('analysis_framework'): stat + for stat in stat_qs + } + _dummy = { + 'project_count': 0, + 'test_project_count': 0, + } + return Promise.resolve([_map.get(key, _dummy) for key in keys]) + + class DataLoaders(WithContextMixin): @cached_property def secondary_widgets(self): @@ -130,3 +163,7 @@ def members(self): @cached_property def af_tags(self): return AnalysisFrameworkTagsLoader(context=self.context) + + @cached_property + def af_project_count(self): + return AnalysisFrameworkProjectCountLoader(context=self.context) diff --git a/apps/analysis_framework/schema.py b/apps/analysis_framework/schema.py index 1cb8a63f52..931a7b9de5 100644 --- a/apps/analysis_framework/schema.py +++ b/apps/analysis_framework/schema.py @@ -11,7 +11,7 @@ from utils.graphene.fields import DjangoPaginatedListObjectField, generate_type_for_serializer from deep.permissions import AnalysisFrameworkPermissions as AfP from project.schema import AnalysisFrameworkVisibleProjectType -from project.models import ProjectMembership, Project +from project.models import ProjectMembership from assisted_tagging.models import PredictionTagAnalysisFrameworkWidgetMapping from .models import ( AnalysisFramework, @@ -97,6 +97,11 @@ class Meta: icon = graphene.Field(FileFieldType, required=False) +class AnalysisFrameworkProjectCount(graphene.ObjectType): + project_count = graphene.Int(required=True) + test_project_count = graphene.Int(required=True) + + # NOTE: We have AnalysisFrameworkDetailType for detailed AF Type. class AnalysisFrameworkType(DjangoObjectType): class Meta: @@ -122,7 +127,7 @@ class Meta: ), required=True, ) - used_in_project_count = graphene.Int(required=True) + used_in_project_count = graphene.Field(AnalysisFrameworkProjectCount, required=True) @staticmethod def get_custom_node(_, info, id): @@ -150,7 +155,7 @@ def resolve_tags(root, info): @staticmethod def resolve_used_in_project_count(root, info): - return Project.objects.filter(analysis_framework=root.id, is_test=False).count() + return info.context.dl.analysis_framework.af_project_count.load(root.id) class AnalysisFrameworkRoleType(DjangoObjectType): diff --git a/schema.graphql b/schema.graphql index 68dc8203dc..f0571f8fb9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -50,7 +50,7 @@ type AnalysisFrameworkDetailType { clonedFrom: ID allowedPermissions: [AnalysisFrameworkPermission!]! tags: [AnalysisFrameworkTagType!]! - usedInProjectCount: Int + usedInProjectCount: AnalysisFrameworkProjectCount! primaryTagging: [SectionType!] secondaryTagging: [WidgetType!] members: [AnalysisFrameworkMembershipType!] @@ -137,6 +137,11 @@ type AnalysisFrameworkPredictionMappingType { widgetType: WidgetWidgetTypeEnum! } +type AnalysisFrameworkProjectCount { + projectCount: Int! + testProjectCount: Int! +} + input AnalysisFrameworkPropertiesGqlInputType { statsConfig: AnalysisFrameworkPropertiesStatsConfigInputType } @@ -219,7 +224,7 @@ type AnalysisFrameworkType { clonedFrom: ID allowedPermissions: [AnalysisFrameworkPermission!]! tags: [AnalysisFrameworkTagType!]! - usedInProjectCount: Int + usedInProjectCount: AnalysisFrameworkProjectCount! } type AnalysisFrameworkVisibleProjectType {