mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: storing and streaming binary response
This commit is contained in:
parent
65fd124864
commit
1573db24c5
@ -4,6 +4,7 @@ from django.urls import path
|
|||||||
from plane.app.views import (
|
from plane.app.views import (
|
||||||
InboxViewSet,
|
InboxViewSet,
|
||||||
InboxIssueViewSet,
|
InboxIssueViewSet,
|
||||||
|
InboxIssueDescriptionViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -50,4 +51,14 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="inbox-issue",
|
name="inbox-issue",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/<str:slug>/projects/<uuid:project_id>/inbox-issues/<uuid:issue_id>/description/",
|
||||||
|
InboxIssueDescriptionViewSet.as_view(
|
||||||
|
{
|
||||||
|
"get": "retrieve",
|
||||||
|
"patch": "partial_update",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
name="inbox-issue-description",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -19,6 +19,7 @@ from plane.app.views import (
|
|||||||
IssueUserDisplayPropertyEndpoint,
|
IssueUserDisplayPropertyEndpoint,
|
||||||
IssueViewSet,
|
IssueViewSet,
|
||||||
LabelViewSet,
|
LabelViewSet,
|
||||||
|
IssueDescriptionViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@ -49,6 +50,16 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="project-issue",
|
name="project-issue",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:pk>/description/",
|
||||||
|
IssueDescriptionViewSet.as_view(
|
||||||
|
{
|
||||||
|
"get": "retrieve",
|
||||||
|
"patch": "partial_update",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
name="issue-description",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-labels/",
|
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-labels/",
|
||||||
LabelViewSet.as_view(
|
LabelViewSet.as_view(
|
||||||
|
@ -106,6 +106,7 @@ from .issue.base import (
|
|||||||
IssueListEndpoint,
|
IssueListEndpoint,
|
||||||
IssueViewSet,
|
IssueViewSet,
|
||||||
IssueUserDisplayPropertyEndpoint,
|
IssueUserDisplayPropertyEndpoint,
|
||||||
|
IssueDescriptionViewSet,
|
||||||
BulkDeleteIssuesEndpoint,
|
BulkDeleteIssuesEndpoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -192,7 +193,11 @@ from .estimate.base import (
|
|||||||
BulkEstimatePointEndpoint,
|
BulkEstimatePointEndpoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .inbox.base import InboxViewSet, InboxIssueViewSet
|
from .inbox.base import (
|
||||||
|
InboxViewSet,
|
||||||
|
InboxIssueViewSet,
|
||||||
|
InboxIssueDescriptionViewSet,
|
||||||
|
)
|
||||||
|
|
||||||
from .analytic.base import (
|
from .analytic.base import (
|
||||||
AnalyticsEndpoint,
|
AnalyticsEndpoint,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import json
|
import json
|
||||||
|
import base64
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@ -9,6 +10,7 @@ from django.contrib.postgres.aggregates import ArrayAgg
|
|||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.db.models import Value, UUIDField
|
from django.db.models import Value, UUIDField
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
|
from django.http import StreamingHttpResponse
|
||||||
|
|
||||||
# Third party imports
|
# Third party imports
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
@ -578,3 +580,48 @@ class InboxIssueViewSet(BaseViewSet):
|
|||||||
|
|
||||||
inbox_issue.delete()
|
inbox_issue.delete()
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
|
||||||
|
class InboxIssueDescriptionViewSet(BaseViewSet):
|
||||||
|
permission_classes = [
|
||||||
|
ProjectLitePermission,
|
||||||
|
]
|
||||||
|
|
||||||
|
def retrieve(self, request, slug, project_id, pk):
|
||||||
|
issue = Issue.objects.get(
|
||||||
|
pk=pk, workspace__slug=slug, project_id=project_id
|
||||||
|
)
|
||||||
|
binary_data = issue.description_binary
|
||||||
|
|
||||||
|
def stream_data():
|
||||||
|
if binary_data:
|
||||||
|
yield binary_data
|
||||||
|
else:
|
||||||
|
yield b""
|
||||||
|
|
||||||
|
response = StreamingHttpResponse(
|
||||||
|
stream_data(), content_type="application/octet-stream"
|
||||||
|
)
|
||||||
|
response["Content-Disposition"] = (
|
||||||
|
'attachment; filename="issue_description.bin"'
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def partial_update(self, request, slug, project_id, pk):
|
||||||
|
issue = Issue.objects.get(
|
||||||
|
pk=pk, workspace__slug=slug, project_id=project_id
|
||||||
|
)
|
||||||
|
|
||||||
|
base64_data = request.data.get("description_binary")
|
||||||
|
|
||||||
|
if base64_data:
|
||||||
|
# Decode the base64 data to bytes
|
||||||
|
new_binary_data = base64.b64decode(base64_data)
|
||||||
|
|
||||||
|
# Store the updated binary data
|
||||||
|
issue.description_binary = new_binary_data
|
||||||
|
issue.description_html = request.data.get("description_html")
|
||||||
|
issue.save()
|
||||||
|
return Response({"message": "Updated successfully"})
|
||||||
|
else:
|
||||||
|
return Response({"error": "No binary data provided"})
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import json
|
import json
|
||||||
|
import base64
|
||||||
|
|
||||||
|
# Django imports
|
||||||
from django.contrib.postgres.aggregates import ArrayAgg
|
from django.contrib.postgres.aggregates import ArrayAgg
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
@ -19,16 +21,14 @@ from django.db.models import (
|
|||||||
When,
|
When,
|
||||||
)
|
)
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
|
from django.http import StreamingHttpResponse
|
||||||
# Django imports
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views.decorators.gzip import gzip_page
|
from django.views.decorators.gzip import gzip_page
|
||||||
from rest_framework import status
|
|
||||||
|
|
||||||
# Third Party imports
|
# Third Party imports
|
||||||
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from plane.app.permissions import (
|
from plane.app.permissions import (
|
||||||
ProjectEntityPermission,
|
ProjectEntityPermission,
|
||||||
ProjectLitePermission,
|
ProjectLitePermission,
|
||||||
@ -674,3 +674,48 @@ class BulkDeleteIssuesEndpoint(BaseAPIView):
|
|||||||
{"message": f"{total_issues} issues were deleted"},
|
{"message": f"{total_issues} issues were deleted"},
|
||||||
status=status.HTTP_200_OK,
|
status=status.HTTP_200_OK,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class IssueDescriptionViewSet(BaseViewSet):
|
||||||
|
permission_classes = [
|
||||||
|
ProjectEntityPermission,
|
||||||
|
]
|
||||||
|
|
||||||
|
def retrieve(self, request, slug, project_id, pk):
|
||||||
|
issue = Issue.objects.get(
|
||||||
|
pk=pk, workspace__slug=slug, project_id=project_id
|
||||||
|
)
|
||||||
|
binary_data = issue.description_binary
|
||||||
|
|
||||||
|
def stream_data():
|
||||||
|
if binary_data:
|
||||||
|
yield binary_data
|
||||||
|
else:
|
||||||
|
yield b""
|
||||||
|
|
||||||
|
response = StreamingHttpResponse(
|
||||||
|
stream_data(), content_type="application/octet-stream"
|
||||||
|
)
|
||||||
|
response["Content-Disposition"] = (
|
||||||
|
'attachment; filename="issue_description.bin"'
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def partial_update(self, request, slug, project_id, pk):
|
||||||
|
issue = Issue.objects.get(
|
||||||
|
pk=pk, workspace__slug=slug, project_id=project_id
|
||||||
|
)
|
||||||
|
|
||||||
|
base64_data = request.data.get("description_binary")
|
||||||
|
|
||||||
|
if base64_data:
|
||||||
|
# Decode the base64 data to bytes
|
||||||
|
new_binary_data = base64.b64decode(base64_data)
|
||||||
|
|
||||||
|
# Store the updated binary data
|
||||||
|
issue.description_binary = new_binary_data
|
||||||
|
issue.description_html = request.data.get("description_html")
|
||||||
|
issue.save()
|
||||||
|
return Response({"message": "Updated successfully"})
|
||||||
|
else:
|
||||||
|
return Response({"error": "No binary data provided"})
|
||||||
|
Loading…
Reference in New Issue
Block a user