Skip to content

Commit

Permalink
fix(organization): expose owner_label in ProjectView endpoint respo…
Browse files Browse the repository at this point in the history
…nse TASK-1384 (#5388)

### 📣 Summary
The Project view endpoint has been updated to include the owner label in
its response.


### 📖 Description
The Project view endpoint has been updated to include the owner label in
its response. This fix ensures that the front end can retrieve the owner
information directly from the endpoint, improving usability across the
application.
  • Loading branch information
noliveleger authored Dec 20, 2024
1 parent 06f8a52 commit 68a0cac
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 31 deletions.
18 changes: 13 additions & 5 deletions kobo/apps/project_views/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# coding: utf-8
from typing import Union
from typing import Union, Optional

from django.conf import settings
from django.db.models.query import QuerySet
Expand All @@ -14,6 +13,7 @@
AssetOrderingFilter,
SearchFilter,
)
from kpi.mixins.asset import AssetViewSetListMixin
from kpi.mixins.object_permission import ObjectPermissionViewSetMixin
from kpi.models import Asset, ProjectViewExportTask
from kpi.paginators import FastAssetPagination
Expand All @@ -31,7 +31,7 @@


class ProjectViewViewSet(
ObjectPermissionViewSetMixin, viewsets.ReadOnlyModelViewSet
AssetViewSetListMixin, ObjectPermissionViewSetMixin, viewsets.ReadOnlyModelViewSet
):

serializer_class = ProjectViewSerializer
Expand Down Expand Up @@ -134,9 +134,17 @@ def users(self, request, uid):
queryset, serializer_class=UserListSerializer
)

def get_serializer_context(self):
def get_serializer_context(self, data: Optional[list] = None):
context_ = super().get_serializer_context()
context_['request'] = self.request
if not data:
return context_

asset_ids = [asset.pk for asset in data]
context_['organizations_per_asset'] = (
self.get_organizations_per_asset_ids(asset_ids)
)

return context_

def _get_regional_response(self, queryset, serializer_class):
Expand All @@ -161,7 +169,7 @@ def _get_regional_serializer(
AssetMetadataListSerializer, UserListSerializer
],
):
context_ = self.get_serializer_context()
context_ = self.get_serializer_context(queryset)

return serializer_class(
queryset,
Expand Down
33 changes: 33 additions & 0 deletions kpi/mixins/asset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from collections import defaultdict
from django.db.models import Prefetch

from kobo.apps.organizations.models import Organization
from kpi.models.asset import Asset


class AssetViewSetListMixin:

def get_organizations_per_asset_ids(self, asset_ids: list) -> dict:

assets = (
Asset.objects.only('owner', 'uid', 'name')
.filter(id__in=asset_ids)
.select_related('owner')
.prefetch_related(
Prefetch(
'owner__organizations_organization',
queryset=Organization.objects.all().order_by(
'-organization_users__created'
),
to_attr='organizations',
)
)
)
organizations_per_asset = defaultdict(dict)
for asset in assets:
try:
organizations_per_asset[asset.id] = asset.owner.organizations[0]
except IndexError:
pass

return organizations_per_asset
5 changes: 3 additions & 2 deletions kpi/serializers/v2/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ def get_access_types(self, asset):
access_types.append('superuser')

try:
organization = self.context['organization_by_asset'].get(asset.id)
organization = self.context['organizations_per_asset'].get(asset.id)
except KeyError:
# Fallback on context if it exists (i.e.: asset lists of an organization).
# Otherwise, retrieve from the asset owner.
Expand All @@ -840,7 +840,7 @@ def get_access_types(self, asset):

def get_owner_label(self, asset):
try:
organization = self.context['organization_by_asset'].get(asset.id)
organization = self.context['organizations_per_asset'].get(asset.id)
except KeyError:
# Fallback on context if it exists (i.e.: asset lists of an organization).
# Otherwise, retrieve from the asset owner.
Expand Down Expand Up @@ -1135,6 +1135,7 @@ class Meta(AssetSerializer.Meta):
'deployment_status',
'asset_type',
'downloads',
'owner_label',
)

def get_deployment__submission_count(self, obj: Asset) -> int:
Expand Down
32 changes: 8 additions & 24 deletions kpi/views/v2/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from collections import OrderedDict, defaultdict
from operator import itemgetter

from django.db.models import Count, Prefetch
from django.db.models import Count
from django.http import Http404
from django.shortcuts import get_object_or_404
from rest_framework import exceptions, renderers, status
Expand All @@ -13,7 +13,6 @@

from kobo.apps.audit_log.base_views import AuditLoggedModelViewSet
from kobo.apps.audit_log.models import AuditType
from kobo.apps.organizations.models import Organization
from kpi.constants import (
ASSET_TYPE_ARG_NAME,
ASSET_TYPE_SURVEY,
Expand All @@ -26,6 +25,7 @@
from kpi.exceptions import BadAssetTypeException
from kpi.filters import AssetOrderingFilter, KpiObjectPermissionsFilter, SearchFilter
from kpi.highlighters import highlight_xform
from kpi.mixins.asset import AssetViewSetListMixin
from kpi.mixins.object_permission import ObjectPermissionViewSetMixin
from kpi.models import Asset, UserAssetSubscription
from kpi.paginators import AssetPagination
Expand All @@ -51,7 +51,10 @@


class AssetViewSet(
ObjectPermissionViewSetMixin, NestedViewSetMixin, AuditLoggedModelViewSet
AssetViewSetListMixin,
ObjectPermissionViewSetMixin,
NestedViewSetMixin,
AuditLoggedModelViewSet,
):
"""
* Assign an asset to a collection
Expand Down Expand Up @@ -731,28 +734,9 @@ def get_serializer_context(self):
else:
# …per asset
# e.g.: /api/v2/organizations/assets/`
assets = (
Asset.objects.only('owner', 'uid', 'name')
.filter(id__in=asset_ids)
.select_related('owner')
.prefetch_related(
Prefetch(
'owner__organizations_organization',
queryset=Organization.objects.all().order_by(
'-organization_users__created'
),
to_attr='organizations',
)
)
context_['organizations_per_asset'] = (
self.get_organizations_per_asset_ids(asset_ids)
)
organization_by_asset = defaultdict(dict)
for asset in assets:
try:
organization_by_asset[asset.id] = asset.owner.organizations[0]
except IndexError:
pass

context_['organization_by_asset'] = organization_by_asset

return context_

Expand Down

0 comments on commit 68a0cac

Please sign in to comment.