forked from github/plane
feat: workspace themes
This commit is contained in:
parent
33ea1cb9d3
commit
b6c911f484
@ -11,6 +11,7 @@ from .workspace import (
|
|||||||
TeamSerializer,
|
TeamSerializer,
|
||||||
WorkSpaceMemberInviteSerializer,
|
WorkSpaceMemberInviteSerializer,
|
||||||
WorkspaceLiteSerializer,
|
WorkspaceLiteSerializer,
|
||||||
|
WorkspaceThemeSerializer,
|
||||||
)
|
)
|
||||||
from .project import (
|
from .project import (
|
||||||
ProjectSerializer,
|
ProjectSerializer,
|
||||||
|
@ -5,8 +5,15 @@ from rest_framework import serializers
|
|||||||
from .base import BaseSerializer
|
from .base import BaseSerializer
|
||||||
from .user import UserLiteSerializer
|
from .user import UserLiteSerializer
|
||||||
|
|
||||||
from plane.db.models import User, Workspace, WorkspaceMember, Team, TeamMember
|
from plane.db.models import (
|
||||||
from plane.db.models import Workspace, WorkspaceMember, Team, WorkspaceMemberInvite
|
User,
|
||||||
|
Workspace,
|
||||||
|
WorkspaceMember,
|
||||||
|
Team,
|
||||||
|
TeamMember,
|
||||||
|
WorkspaceMemberInvite,
|
||||||
|
WorkspaceTheme,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class WorkSpaceSerializer(BaseSerializer):
|
class WorkSpaceSerializer(BaseSerializer):
|
||||||
@ -100,3 +107,13 @@ class WorkspaceLiteSerializer(BaseSerializer):
|
|||||||
"id",
|
"id",
|
||||||
]
|
]
|
||||||
read_only_fields = fields
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
class WorkspaceThemeSerializer(BaseSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = WorkspaceTheme
|
||||||
|
fields = "__all__"
|
||||||
|
read_only_fields = [
|
||||||
|
"workspace",
|
||||||
|
"actor",
|
||||||
|
]
|
||||||
|
@ -42,6 +42,8 @@ from plane.api.views import (
|
|||||||
UserActivityGraphEndpoint,
|
UserActivityGraphEndpoint,
|
||||||
UserIssueCompletedGraphEndpoint,
|
UserIssueCompletedGraphEndpoint,
|
||||||
UserWorkspaceDashboardEndpoint,
|
UserWorkspaceDashboardEndpoint,
|
||||||
|
WorkspaceThemeViewSet,
|
||||||
|
UserWorkspaceThemeEndpoint,
|
||||||
## End Workspaces
|
## End Workspaces
|
||||||
# File Assets
|
# File Assets
|
||||||
FileAssetEndpoint,
|
FileAssetEndpoint,
|
||||||
@ -350,6 +352,32 @@ urlpatterns = [
|
|||||||
WorkspaceMemberUserViewsEndpoint.as_view(),
|
WorkspaceMemberUserViewsEndpoint.as_view(),
|
||||||
name="workspace-member-details",
|
name="workspace-member-details",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/<str:slug>/workspace-themes/",
|
||||||
|
WorkspaceThemeViewSet.as_view(
|
||||||
|
{
|
||||||
|
"get": "list",
|
||||||
|
"post": "create",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
name="workspace-themes",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/<str:slug>/workspace-themes/<uuid:pk>/",
|
||||||
|
WorkspaceThemeViewSet.as_view(
|
||||||
|
{
|
||||||
|
"get": "retrieve",
|
||||||
|
"patch": "partial_update",
|
||||||
|
"delete": "destroy",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
name="workspace-themes",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"users/me/workspaces/<str:slug>/workspace-themes/",
|
||||||
|
UserWorkspaceThemeEndpoint.as_view(),
|
||||||
|
name="user-workspace-themes",
|
||||||
|
),
|
||||||
## End Workspaces ##
|
## End Workspaces ##
|
||||||
# Projects
|
# Projects
|
||||||
path(
|
path(
|
||||||
|
@ -40,6 +40,8 @@ from .workspace import (
|
|||||||
UserActivityGraphEndpoint,
|
UserActivityGraphEndpoint,
|
||||||
UserIssueCompletedGraphEndpoint,
|
UserIssueCompletedGraphEndpoint,
|
||||||
UserWorkspaceDashboardEndpoint,
|
UserWorkspaceDashboardEndpoint,
|
||||||
|
WorkspaceThemeViewSet,
|
||||||
|
UserWorkspaceThemeEndpoint,
|
||||||
)
|
)
|
||||||
from .state import StateViewSet
|
from .state import StateViewSet
|
||||||
from .shortcut import ShortCutViewSet
|
from .shortcut import ShortCutViewSet
|
||||||
|
@ -36,6 +36,7 @@ from plane.api.serializers import (
|
|||||||
WorkSpaceMemberInviteSerializer,
|
WorkSpaceMemberInviteSerializer,
|
||||||
UserLiteSerializer,
|
UserLiteSerializer,
|
||||||
ProjectMemberSerializer,
|
ProjectMemberSerializer,
|
||||||
|
WorkspaceThemeSerializer,
|
||||||
)
|
)
|
||||||
from plane.api.views.base import BaseAPIView
|
from plane.api.views.base import BaseAPIView
|
||||||
from . import BaseViewSet
|
from . import BaseViewSet
|
||||||
@ -48,6 +49,7 @@ from plane.db.models import (
|
|||||||
ProjectMember,
|
ProjectMember,
|
||||||
IssueActivity,
|
IssueActivity,
|
||||||
Issue,
|
Issue,
|
||||||
|
WorkspaceTheme,
|
||||||
)
|
)
|
||||||
from plane.api.permissions import WorkSpaceBasePermission, WorkSpaceAdminPermission
|
from plane.api.permissions import WorkSpaceBasePermission, WorkSpaceAdminPermission
|
||||||
from plane.bgtasks.workspace_invitation_task import workspace_invitation
|
from plane.bgtasks.workspace_invitation_task import workspace_invitation
|
||||||
@ -752,3 +754,65 @@ class UserWorkspaceDashboardEndpoint(BaseAPIView):
|
|||||||
{"error": "Something went wrong please try again later"},
|
{"error": "Something went wrong please try again later"},
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkspaceThemeViewSet(BaseViewSet):
|
||||||
|
permission_classes = [
|
||||||
|
WorkSpaceAdminPermission,
|
||||||
|
]
|
||||||
|
model = WorkspaceTheme
|
||||||
|
serializer_class = WorkspaceThemeSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().filter(workspace__slug=self.kwargs.get("slug"))
|
||||||
|
|
||||||
|
def create(self, request, slug):
|
||||||
|
try:
|
||||||
|
workspace = Workspace.objects.get(slug=slug)
|
||||||
|
serializer = WorkspaceThemeSerializer(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save(workspace=workspace, actor=request.user)
|
||||||
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
except Workspace.DoesNotExist:
|
||||||
|
return Response(
|
||||||
|
{"error": "Workspace does not exist"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return Response(
|
||||||
|
{"error": "Something went wrong please try again later"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserWorkspaceThemeEndpoint(BaseAPIView):
|
||||||
|
def post(self, request, slug):
|
||||||
|
try:
|
||||||
|
workspace_theme_id = request.data.get("workspace_theme_id", False)
|
||||||
|
|
||||||
|
if not workspace_theme_id:
|
||||||
|
return Response(
|
||||||
|
{"error": "Workspace Theme ID is required"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
|
||||||
|
workspace_theme = WorkspaceTheme.objects.get(
|
||||||
|
workspace__slug=slug, pk=workspace_theme_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update at member level
|
||||||
|
workspace_member = WorkspaceMember.objects.get(
|
||||||
|
workspace__slug=slug, member=request.user
|
||||||
|
)
|
||||||
|
workspace_member.workspace_theme = workspace_theme
|
||||||
|
workspace_member.save()
|
||||||
|
serializer = WorkSpaceMemberSerializer(workspace_member)
|
||||||
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
|
except Exception as e:
|
||||||
|
capture_exception(e)
|
||||||
|
return Response(
|
||||||
|
{"error": "Something went wrong please try again later"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
@ -8,6 +8,7 @@ from .workspace import (
|
|||||||
Team,
|
Team,
|
||||||
WorkspaceMemberInvite,
|
WorkspaceMemberInvite,
|
||||||
TeamMember,
|
TeamMember,
|
||||||
|
WorkspaceTheme,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .project import (
|
from .project import (
|
||||||
|
@ -36,7 +36,6 @@ class Workspace(BaseModel):
|
|||||||
ordering = ("-created_at",)
|
ordering = ("-created_at",)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceMember(BaseModel):
|
class WorkspaceMember(BaseModel):
|
||||||
workspace = models.ForeignKey(
|
workspace = models.ForeignKey(
|
||||||
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_member"
|
"db.Workspace", on_delete=models.CASCADE, related_name="workspace_member"
|
||||||
@ -49,6 +48,9 @@ class WorkspaceMember(BaseModel):
|
|||||||
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, default=10)
|
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, default=10)
|
||||||
company_role = models.TextField(null=True, blank=True)
|
company_role = models.TextField(null=True, blank=True)
|
||||||
view_props = models.JSONField(null=True, blank=True)
|
view_props = models.JSONField(null=True, blank=True)
|
||||||
|
workspace_theme = models.ForeignKey(
|
||||||
|
"db.WorkspaceTheme", on_delete=models.SET_NULL, related_name="theme", null=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ["workspace", "member"]
|
unique_together = ["workspace", "member"]
|
||||||
@ -111,7 +113,6 @@ class Team(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class TeamMember(BaseModel):
|
class TeamMember(BaseModel):
|
||||||
|
|
||||||
workspace = models.ForeignKey(
|
workspace = models.ForeignKey(
|
||||||
Workspace, on_delete=models.CASCADE, related_name="team_member"
|
Workspace, on_delete=models.CASCADE, related_name="team_member"
|
||||||
)
|
)
|
||||||
@ -129,3 +130,24 @@ class TeamMember(BaseModel):
|
|||||||
verbose_name_plural = "Team Members"
|
verbose_name_plural = "Team Members"
|
||||||
db_table = "team_members"
|
db_table = "team_members"
|
||||||
ordering = ("-created_at",)
|
ordering = ("-created_at",)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkspaceTheme(BaseModel):
|
||||||
|
workspace = models.ForeignKey(
|
||||||
|
"db.Workspace", on_delete=models.CASCADE, related_name="themes"
|
||||||
|
)
|
||||||
|
name = models.CharField(max_length=300)
|
||||||
|
actor = models.ForeignKey(
|
||||||
|
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="themes"
|
||||||
|
)
|
||||||
|
colors = models.JSONField(default=dict)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.name) + str(self.actor.email)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ["workspace", "name"]
|
||||||
|
verbose_name = "Workspace Theme"
|
||||||
|
verbose_name_plural = "Workspace Themes"
|
||||||
|
db_table = "workspace_themes"
|
||||||
|
ordering = ("-created_at",)
|
||||||
|
Loading…
Reference in New Issue
Block a user