feat(media): add client and project thumbnails
This commit is contained in:
@@ -6,6 +6,19 @@ from apps.projects.models import Project
|
||||
from apps.workspaces.models import PriceUnit
|
||||
|
||||
|
||||
def validate_thumbnail(value):
|
||||
if value is None:
|
||||
return value
|
||||
max_bytes = 2 * 1024 * 1024
|
||||
if getattr(value, "size", 0) > max_bytes:
|
||||
raise serializers.ValidationError("Image size must be 2MB or less.")
|
||||
content_type = (getattr(value, "content_type", "") or "").lower()
|
||||
allowed_types = {"image/jpeg", "image/png", "image/webp"}
|
||||
if content_type and content_type not in allowed_types:
|
||||
raise serializers.ValidationError("Unsupported image type. Use JPG, PNG, or WebP.")
|
||||
return value
|
||||
|
||||
|
||||
class ProjectSerializer(BaseModelSerializer):
|
||||
class Meta:
|
||||
model = Project
|
||||
@@ -14,6 +27,7 @@ class ProjectSerializer(BaseModelSerializer):
|
||||
"name",
|
||||
"client",
|
||||
"description",
|
||||
"thumbnail",
|
||||
"is_archived",
|
||||
"color",
|
||||
)
|
||||
@@ -21,12 +35,25 @@ class ProjectSerializer(BaseModelSerializer):
|
||||
|
||||
def to_representation(self, instance):
|
||||
representation = super().to_representation(instance)
|
||||
request = self.context.get("request")
|
||||
if instance.thumbnail:
|
||||
thumbnail_url = instance.thumbnail.url
|
||||
representation["thumbnail"] = request.build_absolute_uri(thumbnail_url) if request else thumbnail_url
|
||||
else:
|
||||
representation["thumbnail"] = None
|
||||
if instance.client:
|
||||
representation['client'] = {
|
||||
'id': instance.client.id,
|
||||
'name': instance.client.name
|
||||
}
|
||||
return representation
|
||||
'id': instance.client.id,
|
||||
'name': instance.client.name,
|
||||
'thumbnail': (
|
||||
request.build_absolute_uri(instance.client.thumbnail.url)
|
||||
if request and instance.client.thumbnail
|
||||
else instance.client.thumbnail.url
|
||||
if instance.client.thumbnail
|
||||
else None
|
||||
),
|
||||
}
|
||||
return representation
|
||||
|
||||
|
||||
class ProjectCreateSerializer(serializers.Serializer):
|
||||
@@ -34,16 +61,25 @@ class ProjectCreateSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=255)
|
||||
client = serializers.UUIDField(required=False, allow_null=True)
|
||||
description = serializers.CharField(required=False, allow_blank=True, default="")
|
||||
thumbnail = serializers.ImageField(required=False, allow_null=True)
|
||||
color = serializers.CharField(max_length=7, required=False, allow_blank=True, default="")
|
||||
|
||||
def validate_thumbnail(self, value):
|
||||
return validate_thumbnail(value)
|
||||
|
||||
|
||||
class ProjectUpdateSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=255, required=False)
|
||||
client = serializers.UUIDField(required=False, allow_null=True)
|
||||
description = serializers.CharField(required=False, allow_blank=True)
|
||||
thumbnail = serializers.ImageField(required=False, allow_null=True)
|
||||
clear_thumbnail = serializers.BooleanField(required=False, default=False)
|
||||
color = serializers.CharField(max_length=7, required=False, allow_blank=True)
|
||||
is_archived = serializers.BooleanField(required=False)
|
||||
|
||||
def validate_thumbnail(self, value):
|
||||
return validate_thumbnail(value)
|
||||
|
||||
|
||||
class ProjectAccessQuerySerializer(serializers.Serializer):
|
||||
workspace = serializers.UUIDField()
|
||||
|
||||
@@ -89,6 +89,9 @@ class ProjectViewSet(ModelViewSet):
|
||||
if client_ids:
|
||||
queryset = queryset.filter(client_id__in=client_ids)
|
||||
|
||||
if "is_archived" not in self.request.query_params:
|
||||
queryset = queryset.filter(is_archived=False)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_serializer_class(self):
|
||||
@@ -120,13 +123,14 @@ class ProjectViewSet(ModelViewSet):
|
||||
project = create_project(
|
||||
user=request.user,
|
||||
workspace=workspace,
|
||||
name=serializer.validated_data["name"],
|
||||
client=client,
|
||||
name=serializer.validated_data["name"],
|
||||
client=client,
|
||||
description=serializer.validated_data.get("description", ""),
|
||||
color=serializer.validated_data.get("color", "")
|
||||
color=serializer.validated_data.get("color", ""),
|
||||
thumbnail=serializer.validated_data.get("thumbnail"),
|
||||
)
|
||||
|
||||
output_serializer = ProjectSerializer(project)
|
||||
output_serializer = ProjectSerializer(project, context={"request": request})
|
||||
return Response(output_serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
@@ -144,7 +148,7 @@ class ProjectViewSet(ModelViewSet):
|
||||
**serializer.validated_data
|
||||
)
|
||||
|
||||
output_serializer = ProjectSerializer(updated_project)
|
||||
output_serializer = ProjectSerializer(updated_project, context={"request": request})
|
||||
return Response(output_serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
@@ -169,7 +173,7 @@ class ProjectViewSet(ModelViewSet):
|
||||
project = self.get_object()
|
||||
updated_project = toggle_project_archive(project)
|
||||
|
||||
output_serializer = ProjectSerializer(updated_project)
|
||||
output_serializer = ProjectSerializer(updated_project, context={"request": request})
|
||||
return Response(output_serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
@action(detail=False, methods=["get"], url_path="access")
|
||||
|
||||
Reference in New Issue
Block a user