From a18177ce5e01bff5f2d66b2345d7da5d8a20c4d5 Mon Sep 17 00:00:00 2001 From: Atul Tameshwari Date: Tue, 4 Aug 2026 19:50:08 +0530 Subject: [PATCH] feat(api): enhance workspace module query to include member IDs (#9541) Added an annotation to the WorkspaceModulesEndpoint to aggregate member IDs into an array, ensuring that only active members are included. This change improves the data structure returned by the API, allowing for better handling of member information in the frontend. Updated the corresponding utility function to handle potential null values for member IDs. --- apps/api/plane/app/views/workspace/module.py | 18 +++++++++++++++++- packages/utils/src/module.ts | 6 +++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/api/plane/app/views/workspace/module.py b/apps/api/plane/app/views/workspace/module.py index ea217809b9..0ace291286 100644 --- a/apps/api/plane/app/views/workspace/module.py +++ b/apps/api/plane/app/views/workspace/module.py @@ -3,7 +3,10 @@ # See the LICENSE file for details. # Django imports -from django.db.models import Prefetch, Q, Count +from django.contrib.postgres.aggregates import ArrayAgg +from django.contrib.postgres.fields import ArrayField +from django.db.models import Prefetch, Q, Count, UUIDField, Value +from django.db.models.functions import Coalesce # Third party modules from rest_framework import status @@ -109,6 +112,19 @@ class WorkspaceModulesEndpoint(BaseAPIView): distinct=True, ) ) + .annotate( + member_ids=Coalesce( + ArrayAgg( + "members__id", + distinct=True, + filter=Q( + members__id__isnull=False, + modulemember__deleted_at__isnull=True, + ), + ), + Value([], output_field=ArrayField(UUIDField())), + ) + ) .order_by(self.kwargs.get("order_by", "-created_at")) ) diff --git a/packages/utils/src/module.ts b/packages/utils/src/module.ts index c446836107..bd96120308 100644 --- a/packages/utils/src/module.ts +++ b/packages/utils/src/module.ts @@ -30,8 +30,8 @@ export const orderModules = (modules: IModule[], orderByKey: TModuleOrderByOptio let orderedModules: IModule[] = []; if (modules.length === 0 || !orderByKey) return []; - if (orderByKey === "name") orderedModules = [...modules].sort((a, b) => naturalSort(a.name, b.name)); - if (orderByKey === "-name") orderedModules = [...modules].sort((a, b) => naturalSort(b.name, a.name)); + if (orderByKey === "name") orderedModules = [...modules].toSorted((a, b) => naturalSort(a.name, b.name)); + if (orderByKey === "-name") orderedModules = [...modules].toSorted((a, b) => naturalSort(b.name, a.name)); if (["progress", "-progress"].includes(orderByKey)) orderedModules = sortBy(modules, [ (m) => { @@ -71,7 +71,7 @@ export const shouldFilterModule = ( if (filterKey === "lead" && filters.lead && filters.lead.length > 0) fallsInFilters = fallsInFilters && filters.lead.includes(`${module.lead_id}`); if (filterKey === "members" && filters.members && filters.members.length > 0) { - const memberIds = module.member_ids; + const memberIds = module.member_ids ?? []; fallsInFilters = fallsInFilters && filters.members.some((memberId) => memberIds.includes(memberId)); } if (filterKey === "start_date" && filters.start_date && filters.start_date.length > 0) {