mirror of
https://github.com/makeplane/plane.git
synced 2026-07-13 14:01:45 +02:00
[MOBIL-766] fix: convert created_at and updated_at to user timezone in response (#2334)
* fix: conveted the created-at and updated_at based on the user timezone in the response * chore: created_at and updated_at user timezone converter
This commit is contained in:
@@ -9,6 +9,7 @@ import strawberry_django
|
||||
from strawberry.scalars import JSON
|
||||
|
||||
# module imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import FileAsset
|
||||
|
||||
|
||||
@@ -83,6 +84,24 @@ class FileAssetType:
|
||||
# model properties
|
||||
asset_url: Optional[str]
|
||||
|
||||
@strawberry.field
|
||||
def created_by(self) -> Optional[strawberry.ID]:
|
||||
return self.created_by_id
|
||||
|
||||
@strawberry.field
|
||||
def updated_by(self) -> Optional[strawberry.ID]:
|
||||
return self.updated_by_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
|
||||
@strawberry.type
|
||||
class AssetPresignedUrlResponseType:
|
||||
|
||||
@@ -36,8 +36,8 @@ class CycleType:
|
||||
workspace: strawberry.ID
|
||||
created_by: Optional[strawberry.ID]
|
||||
updated_by: Optional[strawberry.ID]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
total_issues: int
|
||||
completed_issues: int
|
||||
is_favorite: bool
|
||||
|
||||
@@ -12,6 +12,7 @@ from strawberry.scalars import JSON
|
||||
from strawberry.types import Info
|
||||
|
||||
# Module Imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import (
|
||||
Issue,
|
||||
IssueLabel,
|
||||
@@ -64,8 +65,8 @@ class IssuesType:
|
||||
external_id: Optional[str]
|
||||
created_by: Optional[strawberry.ID]
|
||||
updated_by: Optional[strawberry.ID]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
cycle: Optional[strawberry.ID]
|
||||
modules: Optional[list[strawberry.ID]]
|
||||
type: Optional[strawberry.ID]
|
||||
@@ -169,6 +170,24 @@ class IssuesType:
|
||||
def parent_project_identifier(self) -> Optional[str]:
|
||||
return self.parent.project.identifier if self.parent else None
|
||||
|
||||
@strawberry.field
|
||||
def created_by(self) -> Optional[strawberry.ID]:
|
||||
return self.created_by_id
|
||||
|
||||
@strawberry.field
|
||||
def updated_by(self) -> Optional[strawberry.ID]:
|
||||
return self.updated_by_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
|
||||
@strawberry_django.type(IssueUserProperty)
|
||||
class IssueUserPropertyType:
|
||||
@@ -210,8 +229,8 @@ class IssuePropertyActivityType:
|
||||
epoch: float
|
||||
workspace: strawberry.ID
|
||||
project: strawberry.ID
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
|
||||
@strawberry.field
|
||||
def workspace(self) -> int:
|
||||
@@ -233,6 +252,16 @@ class IssuePropertyActivityType:
|
||||
def issue(self) -> int:
|
||||
return self.issue_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
|
||||
@strawberry_django.type(IssueComment)
|
||||
class IssueCommentActivityType:
|
||||
@@ -248,8 +277,8 @@ class IssueCommentActivityType:
|
||||
external_id: Optional[str]
|
||||
workspace: strawberry.ID
|
||||
project: strawberry.ID
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
|
||||
@strawberry.field
|
||||
def workspace(self) -> int:
|
||||
@@ -267,6 +296,24 @@ class IssueCommentActivityType:
|
||||
def issue(self) -> int:
|
||||
return self.issue_id
|
||||
|
||||
@strawberry.field
|
||||
def created_by(self) -> Optional[strawberry.ID]:
|
||||
return self.created_by_id
|
||||
|
||||
@strawberry.field
|
||||
def updated_by(self) -> Optional[strawberry.ID]:
|
||||
return self.updated_by_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
|
||||
@strawberry_django.type(Issue)
|
||||
class IssueLiteType:
|
||||
|
||||
@@ -7,6 +7,7 @@ import strawberry
|
||||
import strawberry_django
|
||||
|
||||
# Module Imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import IssueLink
|
||||
|
||||
|
||||
@@ -15,8 +16,8 @@ class IssueLinkType:
|
||||
id: strawberry.ID
|
||||
title: str
|
||||
url: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
|
||||
@strawberry.field
|
||||
def workspace(self) -> strawberry.ID:
|
||||
@@ -37,3 +38,13 @@ class IssueLinkType:
|
||||
@strawberry.field
|
||||
def updated_by(self) -> Optional[strawberry.ID]:
|
||||
return self.updated_by_id if self.created_by_id else None
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
@@ -9,6 +9,7 @@ from strawberry.types import Info
|
||||
from strawberry.scalars import JSON
|
||||
|
||||
# Module Imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import Module, Issue, ModuleUserProperties
|
||||
from plane.graphql.types.users import UserType
|
||||
|
||||
@@ -25,8 +26,8 @@ class ModuleType:
|
||||
workspace: strawberry.ID
|
||||
created_by: Optional[strawberry.ID]
|
||||
updated_by: Optional[strawberry.ID]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
description: Optional[str]
|
||||
description_text: Optional[str]
|
||||
description_html: Optional[str]
|
||||
@@ -86,6 +87,24 @@ class ModuleType:
|
||||
)()
|
||||
return issue_assignees_count
|
||||
|
||||
@strawberry.field
|
||||
def created_by(self) -> Optional[strawberry.ID]:
|
||||
return self.created_by_id
|
||||
|
||||
@strawberry.field
|
||||
def updated_by(self) -> Optional[strawberry.ID]:
|
||||
return self.updated_by_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
|
||||
@strawberry_django.type(Module)
|
||||
class ModuleLiteType:
|
||||
|
||||
@@ -8,6 +8,7 @@ import strawberry_django
|
||||
from strawberry.scalars import JSON
|
||||
|
||||
# Module imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import Notification
|
||||
from plane.graphql.types.users import UserType
|
||||
from plane.graphql.types.project import ProjectType
|
||||
@@ -31,8 +32,8 @@ class NotificationType:
|
||||
data: JSON
|
||||
workspace: strawberry.ID
|
||||
project: Optional[ProjectType]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
|
||||
@strawberry.field
|
||||
def workspace(self) -> int:
|
||||
@@ -41,3 +42,13 @@ class NotificationType:
|
||||
@strawberry.field
|
||||
def receiver(self) -> int:
|
||||
return self.receiver_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
@@ -11,6 +11,7 @@ import strawberry_django
|
||||
from strawberry.scalars import JSON
|
||||
|
||||
# Module imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import Page
|
||||
from plane.graphql.types.project import ProjectLiteType
|
||||
|
||||
@@ -35,8 +36,8 @@ class PageType:
|
||||
logo_props: JSON
|
||||
is_global: bool
|
||||
is_favorite: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
projects: list[strawberry.ID]
|
||||
# teams: list[strawberry.ID]
|
||||
# labels: list[strawberry.ID]
|
||||
@@ -62,6 +63,16 @@ class PageType:
|
||||
projects = await sync_to_async(list)(self.projects.all())
|
||||
return [project.id for project in projects]
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
# @strawberry.field
|
||||
# async def labels(self) -> list[strawberry.ID]:
|
||||
# labels = await sync_to_async(list)(self.labels.all())
|
||||
|
||||
@@ -10,6 +10,7 @@ from strawberry.types import Info
|
||||
from strawberry.scalars import JSON
|
||||
|
||||
# Module imports
|
||||
from plane.graphql.utils.timezone import user_timezone_converter
|
||||
from plane.db.models import (
|
||||
User,
|
||||
Profile,
|
||||
@@ -119,8 +120,8 @@ class UserFavoriteType:
|
||||
is_folder: bool
|
||||
sequence: float
|
||||
parent: Optional[strawberry.ID]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
created_at: Optional[datetime]
|
||||
updated_at: Optional[datetime]
|
||||
deleted_at: Optional[datetime]
|
||||
project: Optional[strawberry.ID]
|
||||
|
||||
@@ -128,6 +129,16 @@ class UserFavoriteType:
|
||||
def project(self) -> int:
|
||||
return self.project_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
async def entity_data(self) -> Optional[UserFavoriteEntityData]:
|
||||
# where entity_identifier is project_id and entity_type is project
|
||||
@@ -216,6 +227,16 @@ class UserRecentVisitType:
|
||||
def user(self) -> int:
|
||||
return self.user_id
|
||||
|
||||
@strawberry.field
|
||||
def created_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.created_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
def updated_at(self, info) -> Optional[datetime]:
|
||||
converted_date = user_timezone_converter(info.context.user, self.updated_at)
|
||||
return converted_date
|
||||
|
||||
@strawberry.field
|
||||
async def entity_data(self) -> Optional[UserFavoriteEntityData]:
|
||||
# where entity_identifier is project_id and entity_name is project
|
||||
|
||||
1
apiserver/plane/graphql/utils/timezone/__init__.py
Normal file
1
apiserver/plane/graphql/utils/timezone/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .user import user_timezone_converter
|
||||
36
apiserver/plane/graphql/utils/timezone/user.py
Normal file
36
apiserver/plane/graphql/utils/timezone/user.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Python imports
|
||||
import pytz
|
||||
from datetime import datetime, date
|
||||
|
||||
# Third-party imports
|
||||
from asgiref.sync import sync_to_async
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
# Module imports
|
||||
from plane.db.models import User
|
||||
|
||||
|
||||
async def user_timezone_converter(user, input_date=None):
|
||||
if user is None or input_date is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
current_user = await sync_to_async(User.objects.get)(id=user.id)
|
||||
except ObjectDoesNotExist:
|
||||
return input_date
|
||||
|
||||
user_timezone = current_user.user_timezone
|
||||
if not user_timezone:
|
||||
return input_date
|
||||
|
||||
try:
|
||||
tz = pytz.timezone(user_timezone)
|
||||
except pytz.UnknownTimeZoneError:
|
||||
return input_date
|
||||
|
||||
if isinstance(input_date, datetime):
|
||||
return input_date.astimezone(tz)
|
||||
elif isinstance(input_date, date):
|
||||
return datetime.combine(input_date, datetime.min.time()).astimezone(tz)
|
||||
else:
|
||||
return input_date
|
||||
Reference in New Issue
Block a user