forked from github/plane
[WEB-1132] fix: display datetime fields in user time zone format (#4323)
* fix: user timezone response * chore: removed unused variables
This commit is contained in:
parent
ed4a0518fc
commit
d69f025b9a
@ -32,7 +32,6 @@ from plane.api.serializers import (
|
|||||||
LabelSerializer,
|
LabelSerializer,
|
||||||
)
|
)
|
||||||
from plane.app.permissions import (
|
from plane.app.permissions import (
|
||||||
WorkspaceEntityPermission,
|
|
||||||
ProjectEntityPermission,
|
ProjectEntityPermission,
|
||||||
ProjectLitePermission,
|
ProjectLitePermission,
|
||||||
ProjectMemberPermission,
|
ProjectMemberPermission,
|
||||||
|
@ -38,7 +38,7 @@ from plane.db.models import (
|
|||||||
)
|
)
|
||||||
from plane.bgtasks.issue_activites_task import issue_activity
|
from plane.bgtasks.issue_activites_task import issue_activity
|
||||||
from plane.utils.issue_filters import issue_filters
|
from plane.utils.issue_filters import issue_filters
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||||
serializer_class = CycleIssueSerializer
|
serializer_class = CycleIssueSerializer
|
||||||
@ -191,6 +191,11 @@ class CycleIssueViewSet(WebhookMixin, BaseViewSet):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issues, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
|
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def create(self, request, slug, project_id, cycle_id):
|
def create(self, request, slug, project_id, cycle_id):
|
||||||
|
@ -47,7 +47,7 @@ from plane.db.models import (
|
|||||||
)
|
)
|
||||||
from plane.bgtasks.issue_activites_task import issue_activity
|
from plane.bgtasks.issue_activites_task import issue_activity
|
||||||
from plane.utils.issue_filters import issue_filters
|
from plane.utils.issue_filters import issue_filters
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
class IssueArchiveViewSet(BaseViewSet):
|
class IssueArchiveViewSet(BaseViewSet):
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
@ -239,6 +239,11 @@ class IssueArchiveViewSet(BaseViewSet):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issue_queryset, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
|
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def retrieve(self, request, slug, project_id, pk=None):
|
def retrieve(self, request, slug, project_id, pk=None):
|
||||||
|
@ -50,6 +50,7 @@ from plane.db.models import (
|
|||||||
Project,
|
Project,
|
||||||
)
|
)
|
||||||
from plane.utils.issue_filters import issue_filters
|
from plane.utils.issue_filters import issue_filters
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from .. import BaseAPIView, BaseViewSet, WebhookMixin
|
from .. import BaseAPIView, BaseViewSet, WebhookMixin
|
||||||
@ -241,6 +242,10 @@ class IssueListEndpoint(BaseAPIView):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issues, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
@ -440,6 +445,10 @@ class IssueViewSet(WebhookMixin, BaseViewSet):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issue_queryset, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def create(self, request, slug, project_id):
|
def create(self, request, slug, project_id):
|
||||||
@ -503,6 +512,10 @@ class IssueViewSet(WebhookMixin, BaseViewSet):
|
|||||||
)
|
)
|
||||||
.first()
|
.first()
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issue = user_timezone_converter(
|
||||||
|
issue, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(issue, status=status.HTTP_201_CREATED)
|
return Response(issue, status=status.HTTP_201_CREATED)
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ from plane.db.models import (
|
|||||||
Project,
|
Project,
|
||||||
)
|
)
|
||||||
from plane.utils.issue_filters import issue_filters
|
from plane.utils.issue_filters import issue_filters
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from .. import BaseViewSet
|
from .. import BaseViewSet
|
||||||
@ -229,6 +230,10 @@ class IssueDraftViewSet(BaseViewSet):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issue_queryset, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def create(self, request, slug, project_id):
|
def create(self, request, slug, project_id):
|
||||||
|
@ -31,6 +31,7 @@ from plane.db.models import (
|
|||||||
IssueAttachment,
|
IssueAttachment,
|
||||||
)
|
)
|
||||||
from plane.bgtasks.issue_activites_task import issue_activity
|
from plane.bgtasks.issue_activites_task import issue_activity
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +133,10 @@ class SubIssuesEndpoint(BaseAPIView):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
sub_issues = user_timezone_converter(
|
||||||
|
sub_issues, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
"sub_issues": sub_issues,
|
"sub_issues": sub_issues,
|
||||||
|
@ -32,6 +32,8 @@ from plane.db.models import (
|
|||||||
ModuleLink,
|
ModuleLink,
|
||||||
)
|
)
|
||||||
from plane.utils.analytics_plot import burndown_plot
|
from plane.utils.analytics_plot import burndown_plot
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from .. import BaseAPIView
|
from .. import BaseAPIView
|
||||||
@ -199,6 +201,10 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
|
|||||||
"updated_at",
|
"updated_at",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
modules = user_timezone_converter(
|
||||||
|
modules, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(modules, status=status.HTTP_200_OK)
|
return Response(modules, status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
queryset = (
|
queryset = (
|
||||||
|
@ -48,6 +48,8 @@ from plane.db.models import (
|
|||||||
Project,
|
Project,
|
||||||
)
|
)
|
||||||
from plane.utils.analytics_plot import burndown_plot
|
from plane.utils.analytics_plot import burndown_plot
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
|
|
||||||
# Module imports
|
# Module imports
|
||||||
from .. import BaseAPIView, BaseViewSet, WebhookMixin
|
from .. import BaseAPIView, BaseViewSet, WebhookMixin
|
||||||
@ -236,6 +238,10 @@ class ModuleViewSet(WebhookMixin, BaseViewSet):
|
|||||||
"updated_at",
|
"updated_at",
|
||||||
)
|
)
|
||||||
).first()
|
).first()
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
module = user_timezone_converter(
|
||||||
|
module, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(module, status=status.HTTP_201_CREATED)
|
return Response(module, status=status.HTTP_201_CREATED)
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@ -277,6 +283,10 @@ class ModuleViewSet(WebhookMixin, BaseViewSet):
|
|||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
modules = user_timezone_converter(
|
||||||
|
modules, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(modules, status=status.HTTP_200_OK)
|
return Response(modules, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def retrieve(self, request, slug, project_id, pk):
|
def retrieve(self, request, slug, project_id, pk):
|
||||||
@ -454,6 +464,10 @@ class ModuleViewSet(WebhookMixin, BaseViewSet):
|
|||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
).first()
|
).first()
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
module = user_timezone_converter(
|
||||||
|
module, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(module, status=status.HTTP_200_OK)
|
return Response(module, status=status.HTTP_200_OK)
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ from plane.db.models import (
|
|||||||
)
|
)
|
||||||
from plane.bgtasks.issue_activites_task import issue_activity
|
from plane.bgtasks.issue_activites_task import issue_activity
|
||||||
from plane.utils.issue_filters import issue_filters
|
from plane.utils.issue_filters import issue_filters
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
|
class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
|
||||||
serializer_class = ModuleIssueSerializer
|
serializer_class = ModuleIssueSerializer
|
||||||
@ -150,6 +150,11 @@ class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issues, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
|
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
# create multiple issues inside a module
|
# create multiple issues inside a module
|
||||||
|
@ -42,7 +42,7 @@ from plane.db.models import (
|
|||||||
IssueAttachment,
|
IssueAttachment,
|
||||||
)
|
)
|
||||||
from plane.utils.issue_filters import issue_filters
|
from plane.utils.issue_filters import issue_filters
|
||||||
|
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||||
|
|
||||||
class GlobalViewViewSet(BaseViewSet):
|
class GlobalViewViewSet(BaseViewSet):
|
||||||
serializer_class = IssueViewSerializer
|
serializer_class = IssueViewSerializer
|
||||||
@ -255,6 +255,10 @@ class GlobalViewIssuesViewSet(BaseViewSet):
|
|||||||
"is_draft",
|
"is_draft",
|
||||||
"archived_at",
|
"archived_at",
|
||||||
)
|
)
|
||||||
|
datetime_fields = ["created_at", "updated_at"]
|
||||||
|
issues = user_timezone_converter(
|
||||||
|
issues, datetime_fields, request.user.user_timezone
|
||||||
|
)
|
||||||
return Response(issues, status=status.HTTP_200_OK)
|
return Response(issues, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
25
apiserver/plane/utils/user_timezone_converter.py
Normal file
25
apiserver/plane/utils/user_timezone_converter.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import pytz
|
||||||
|
|
||||||
|
def user_timezone_converter(queryset, datetime_fields, user_timezone):
|
||||||
|
# Create a timezone object for the user's timezone
|
||||||
|
user_tz = pytz.timezone(user_timezone)
|
||||||
|
|
||||||
|
# Check if queryset is a dictionary (single item) or a list of dictionaries
|
||||||
|
if isinstance(queryset, dict):
|
||||||
|
queryset_values = [queryset]
|
||||||
|
else:
|
||||||
|
queryset_values = list(queryset.values())
|
||||||
|
|
||||||
|
# Iterate over the dictionaries in the list
|
||||||
|
for item in queryset_values:
|
||||||
|
# Iterate over the datetime fields
|
||||||
|
for field in datetime_fields:
|
||||||
|
# Convert the datetime field to the user's timezone
|
||||||
|
if item[field]:
|
||||||
|
item[field] = item[field].astimezone(user_tz)
|
||||||
|
|
||||||
|
# If queryset was a single item, return a single item
|
||||||
|
if isinstance(queryset, dict):
|
||||||
|
return queryset_values[0]
|
||||||
|
else:
|
||||||
|
return queryset_values
|
Loading…
Reference in New Issue
Block a user