Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-1132] fix: display datetime fields in user time zone format #4323

Merged
merged 2 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion apiserver/plane/api/views/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
LabelSerializer,
)
from plane.app.permissions import (
WorkspaceEntityPermission,
ProjectEntityPermission,
ProjectLitePermission,
ProjectMemberPermission,
Expand Down
7 changes: 6 additions & 1 deletion apiserver/plane/app/views/cycle/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.issue_filters import issue_filters

from plane.utils.user_timezone_converter import user_timezone_converter

class CycleIssueViewSet(WebhookMixin, BaseViewSet):
serializer_class = CycleIssueSerializer
Expand Down Expand Up @@ -191,6 +191,11 @@ def list(self, request, slug, project_id, cycle_id):
"is_draft",
"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)

def create(self, request, slug, project_id, cycle_id):
Expand Down
7 changes: 6 additions & 1 deletion apiserver/plane/app/views/issue/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.issue_filters import issue_filters

from plane.utils.user_timezone_converter import user_timezone_converter

class IssueArchiveViewSet(BaseViewSet):
permission_classes = [
Expand Down Expand Up @@ -239,6 +239,11 @@
"is_draft",
"archived_at",
)
datetime_fields = ["created_at", "updated_at"]
issues = user_timezone_converter(
issue_queryset, datetime_fields, request.user.user_timezone
)

Check notice on line 246 in apiserver/plane/app/views/issue/archive.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apiserver/plane/app/views/issue/archive.py#L246

Trailing whitespace
return Response(issues, status=status.HTTP_200_OK)

def retrieve(self, request, slug, project_id, pk=None):
Expand Down
13 changes: 13 additions & 0 deletions apiserver/plane/app/views/issue/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
Project,
)
from plane.utils.issue_filters import issue_filters
from plane.utils.user_timezone_converter import user_timezone_converter

# Module imports
from .. import BaseAPIView, BaseViewSet, WebhookMixin
Expand Down Expand Up @@ -241,6 +242,10 @@ def get(self, request, slug, project_id):
"is_draft",
"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)


Expand Down Expand Up @@ -440,6 +445,10 @@ def list(self, request, slug, project_id):
"is_draft",
"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)

def create(self, request, slug, project_id):
Expand Down Expand Up @@ -503,6 +512,10 @@ def create(self, request, slug, project_id):
)
.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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Expand Down
5 changes: 5 additions & 0 deletions apiserver/plane/app/views/issue/draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
Project,
)
from plane.utils.issue_filters import issue_filters
from plane.utils.user_timezone_converter import user_timezone_converter

# Module imports
from .. import BaseViewSet
Expand Down Expand Up @@ -229,6 +230,10 @@ def list(self, request, slug, project_id):
"is_draft",
"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)

def create(self, request, slug, project_id):
Expand Down
5 changes: 5 additions & 0 deletions apiserver/plane/app/views/issue/sub_issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
IssueAttachment,
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.user_timezone_converter import user_timezone_converter
from collections import defaultdict


Expand Down Expand Up @@ -132,6 +133,10 @@ def get(self, request, slug, project_id, issue_id):
"is_draft",
"archived_at",
)
datetime_fields = ["created_at", "updated_at"]
sub_issues = user_timezone_converter(
sub_issues, datetime_fields, request.user.user_timezone
)
return Response(
{
"sub_issues": sub_issues,
Expand Down
6 changes: 6 additions & 0 deletions apiserver/plane/app/views/module/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
ModuleLink,
)
from plane.utils.analytics_plot import burndown_plot
from plane.utils.user_timezone_converter import user_timezone_converter


# Module imports
from .. import BaseAPIView
Expand Down Expand Up @@ -199,6 +201,10 @@ def get(self, request, slug, project_id, pk=None):
"updated_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)
else:
queryset = (
Expand Down
14 changes: 14 additions & 0 deletions apiserver/plane/app/views/module/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
Project,
)
from plane.utils.analytics_plot import burndown_plot
from plane.utils.user_timezone_converter import user_timezone_converter


# Module imports
from .. import BaseAPIView, BaseViewSet, WebhookMixin
Expand Down Expand Up @@ -236,6 +238,10 @@ def create(self, request, slug, project_id):
"updated_at",
)
).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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Expand Down Expand Up @@ -277,6 +283,10 @@ def list(self, request, slug, project_id):
"created_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)

def retrieve(self, request, slug, project_id, pk):
Expand Down Expand Up @@ -454,6 +464,10 @@ def partial_update(self, request, slug, project_id, pk):
"created_at",
"updated_at",
).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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Expand Down
7 changes: 6 additions & 1 deletion apiserver/plane/app/views/module/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.issue_filters import issue_filters

from plane.utils.user_timezone_converter import user_timezone_converter

class ModuleIssueViewSet(WebhookMixin, BaseViewSet):
serializer_class = ModuleIssueSerializer
Expand Down Expand Up @@ -150,6 +150,11 @@ def list(self, request, slug, project_id, module_id):
"is_draft",
"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)

# create multiple issues inside a module
Expand Down
6 changes: 5 additions & 1 deletion apiserver/plane/app/views/view/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
IssueAttachment,
)
from plane.utils.issue_filters import issue_filters

from plane.utils.user_timezone_converter import user_timezone_converter

class GlobalViewViewSet(BaseViewSet):
serializer_class = IssueViewSerializer
Expand Down Expand Up @@ -255,6 +255,10 @@ def list(self, request, slug):
"is_draft",
"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)


Expand Down
25 changes: 25 additions & 0 deletions apiserver/plane/utils/user_timezone_converter.py
Original file line number Diff line number Diff line change
@@ -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