Skip to content
28 changes: 7 additions & 21 deletions apps/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,9 +704,7 @@ def remove_member(self, request, *args, **kwargs):
def member(self, request, *args, **kwargs):
group = self.get_object()

modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.members()
queryset = group.modules_by_user(request.user).members()

page = self.paginate_queryset(queryset)
if page is not None:
Expand Down Expand Up @@ -795,9 +793,7 @@ def remove_featured_project(self, request, *args, **kwargs):
)
def project(self, request, *args, **kwargs):
group = self.get_object()
modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.featured_projects()
queryset = group.modules_by_user(request.user).featured_projects()

page = self.paginate_queryset(queryset)
project_serializer = ProjectLightSerializer(
Expand Down Expand Up @@ -842,9 +838,7 @@ def hierarchy(self, request, *args, **kwargs):
)
def subgroups(self, request, *args, **kwargs):
group = self.get_object()
modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.subgroups()
queryset = group.modules_by_user(request.user).subgroups()

queryset_page = self.paginate_queryset(queryset)
data = PeopleGroupLightSerializer(
Expand All @@ -861,9 +855,7 @@ def subgroups(self, request, *args, **kwargs):
)
def similars(self, request, *args, **kwargs):
group = self.get_object()
modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.similars()
queryset = group.modules_by_user(request.user).similars()

queryset_page = self.paginate_queryset(queryset)
data = PeopleGroupLightSerializer(
Expand All @@ -880,9 +872,7 @@ def similars(self, request, *args, **kwargs):
)
def locations(self, request, *args, **kwargs):
group = self.get_object()
modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.locations()
queryset = group.modules_by_user(request.user).locations()

return Response(
LocationSerializer(queryset, many=True, context={"request": request}).data,
Expand All @@ -898,9 +888,7 @@ def locations(self, request, *args, **kwargs):
)
def news(self, request, *args, **kwargs):
group = self.get_object()
modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.news()
queryset = group.modules_by_user(request.user).news()

# use NewsViewSet to filter/order events
queryset = NewsViewSet(request=self.request).filter_queryset(queryset)
Expand All @@ -920,9 +908,7 @@ def news(self, request, *args, **kwargs):
)
def event(self, request, *args, **kwargs):
group = self.get_object()
modules_manager = group.get_related_module()
modules = modules_manager(group, request.user)
queryset = modules.event()
queryset = group.modules_by_user(request.user).event()

# use EventViewSet to filter/order events
queryset = EventViewSet(request=self.request).filter_queryset(queryset)
Expand Down
58 changes: 57 additions & 1 deletion apps/files/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
from azure.core.exceptions import ResourceNotFoundError
from django.apps import apps
from django.conf import settings
from django.core.cache import cache
from django.core.files.uploadedfile import SimpleUploadedFile
from django.db import models, transaction
from django.db.models import ForeignObjectRel, Model, Q, QuerySet
from django.db.models import ForeignObjectRel, ImageField, Model, Q, QuerySet
from django.utils import timezone
from simple_history.models import HistoricalRecords
from stdimage import StdImageField
Expand Down Expand Up @@ -253,6 +254,57 @@ class Meta:
ordering = ("-created_at",)
abstract = True

@staticmethod
def get_url(cache_key: str, field: ImageField) -> str:
"""create cache for url file"""
url = cache.get(cache_key)
if url:
return url

try:
url = field.url
except AttributeError:
return ""

# expirations defined by azure/env - 60s
timeout = settings.STORAGE_EXPIRATION_SECS - 60
cache.set(cache_key, url, timeout=timeout)
return url

@property
def __url_key(self) -> str:
return f"image::url::{self.pk}"

@property
def __url_variations_key(self) -> dict[str, str]:
field = self.file.field

obj = {}
for name in field.variations.keys():
obj[name] = f"image::url::{name}::{self.pk}"
return obj

@property
def url(self) -> str:
"""create cache for url file"""
return self.get_url(self.__url_key, self.file)

@property
def variations(self) -> dict[str, str]:
varias = {"original": self.url}

for name, key in self.__url_variations_key.items():
field = getattr(self.file, name, None)

url = ""
if field:
url = self.get_url(key, field)
varias[name] = url
return varias

def clear_cache_urls(self):
cache.delete_many([self.__url_key, *list(self.__url_variations_key.values())])

def duplicate(self, upload_to: str = "", **fields) -> None | Self:
with suppress(ResourceNotFoundError):
file_path = self.file.name.split("/")
Expand All @@ -271,6 +323,10 @@ def duplicate(self, upload_to: str = "", **fields) -> None | Self:
return super().duplicate(_upload_to=_upload_to, file=new_file, **fields)
return None

def save(self, *ar, **kw):
self.clear_cache_urls()
return super().save(*ar, **kw)


class Image(BaseImage, HasOwner, ProjectRelated, OrganizationRelated):
name = models.CharField(max_length=255)
Expand Down
55 changes: 5 additions & 50 deletions apps/files/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,54 +40,6 @@
)


# From https://github.com/glemmaPaul/django-stdimage-serializer (however the repo is not maintained anymore)
class StdImageField(serializers.ImageField):
"""
Get all the variations of the StdImageField
"""

def to_native(self, obj):
return self.get_variations_urls(obj)

def to_representation(self, obj):
return self.get_variations_urls(obj)

def get_variations_urls(self, obj):
"""
Get all the logo urls.
"""

# Initiate return object
return_object = {}

# Get the field of the object
field = obj.field

# A lot of ifs going araound, first check if it has the field variations
if hasattr(field, "variations"):
# Get the variations
variations = field.variations
# Go through the variations dict
for key in variations.keys():
# Just to be sure if the stdimage object has it stored in the obj
if hasattr(obj, key):
# get the by stdimage properties
field_obj = getattr(obj, key, None)
if field_obj and hasattr(field_obj, "url"):
# store it, with the name of the variation type into our return object
return_object[key] = super(
StdImageField, self
).to_representation(field_obj)

# Also include the original (if possible)
if hasattr(obj, "url"):
return_object["original"] = super(StdImageField, self).to_representation(
obj
)

return return_object


class AbstractAttachmentLink(metaclass=serializers.SerializerMetaclass):
preview_image_url = serializers.URLField(max_length=2048, read_only=True)
site_name = serializers.CharField(max_length=255, read_only=True)
Expand Down Expand Up @@ -386,8 +338,8 @@ def get_related_project(self) -> Optional["Project"]:

class ImageSerializer(serializers.ModelSerializer):
url = serializers.SerializerMethodField()
variations = serializers.SerializerMethodField()
file = serializers.ImageField(write_only=True)
variations = StdImageField(source="file", read_only=True)

class Meta:
model = Image
Expand All @@ -407,6 +359,9 @@ class Meta:
"variations",
]

def get_variations(self, file):
return file.variations

def validate_file(self, file):
limit = settings.MAX_FILE_SIZE * 1024 * 1024
if file.size > limit:
Expand All @@ -415,7 +370,7 @@ def validate_file(self, file):

def get_url(self, image: Image) -> str | None:
try:
url = image.file.url
url = image.url
except AttributeError:
return None
request = self.context.get("request")
Expand Down
4 changes: 1 addition & 3 deletions apps/files/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,7 @@ def get_permissions(self):
return super().get_permissions()

def get_queryset(self):
modules_manager = self.people_group.get_related_module()
modules = modules_manager(self.people_group, self.request.user)
return modules.gallery()
return self.people_group.modules_by_user(self.request.user).gallery()

def update(self, request, *ar, **kw):
request.data["people_group"] = self.people_group.id
Expand Down
60 changes: 39 additions & 21 deletions apps/modules/group.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
from django.db.models import Case, Prefetch, Q, QuerySet, Value, When
from django.db.models import (
Case,
CharField,
IntegerField,
Q,
QuerySet,
Value,
When,
)

from apps.accounts.models import PeopleGroup, PeopleGroupLocation, ProjectUser
from apps.commons.models import GroupData
from apps.files.models import PeopleGroupImage
from apps.modules.base import AbstractModules, register_module
from apps.newsfeed.models import Event, EventLocation, NewsLocation
from apps.projects.models import Location, Project
from apps.skills.models import Skill
from services.crisalid.models import Document, DocumentTypeCentralized


Expand All @@ -15,33 +22,44 @@ class PeopleGroupModules(AbstractModules):
instance: PeopleGroup

def members(self) -> QuerySet[ProjectUser]:
skills_prefetch = Prefetch(
"skills", queryset=Skill.objects.select_related("tag")
)

leaders = self.instance.leaders.all()
managers = self.instance.managers.all()
members = self.instance.members.all()

all_members = leaders | managers | members
return (
all_members.distinct()
.filter(pk__in=self.user.get_user_queryset())
self.user.get_user_queryset()
.filter(
groups__data__role__in=(
GroupData.Role.LEADERS,
GroupData.Role.MANAGERS,
GroupData.Role.MEMBERS,
),
groups__people_groups=self.instance,
)
.annotate(
role=Case(
When(pk__in=leaders, then=Value(GroupData.Role.LEADERS)),
When(pk__in=managers, then=Value(GroupData.Role.MANAGERS)),
When(pk__in=members, then=Value(GroupData.Role.MEMBERS)),
When(
groups__data__role=GroupData.Role.LEADERS,
then=Value(GroupData.Role.LEADERS.value),
),
When(
groups__data__role=GroupData.Role.MANAGERS,
then=Value(GroupData.Role.MANAGERS.value),
),
When(
groups__data__role=GroupData.Role.MEMBERS,
then=Value(GroupData.Role.MEMBERS.value),
),
output_field=CharField(),
),
# add sort order priority (first leader, manager and members)
priority_role_order=Case(
When(pk__in=leaders, then=1),
When(pk__in=managers, then=2),
When(pk__in=members, then=3),
When(groups__data__role=GroupData.Role.LEADERS, then=Value(1)),
When(groups__data__role=GroupData.Role.MANAGERS, then=Value(2)),
When(
groups__data__role=GroupData.Role.MEMBERS,
then=Value(3),
),
output_field=IntegerField(),
),
)
.order_by("priority_role_order")
.prefetch_related(skills_prefetch, "groups")
.distinct()
)

def featured_projects(self) -> QuerySet[Project]:
Expand Down
Loading
Loading