Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70100a97e7 | ||
|
|
05f26ef4ce | ||
|
|
83af541f11 | ||
|
|
66673279d1 | ||
|
|
389ee74ff5 |
@@ -13,7 +13,6 @@ from .user import (
|
||||
from .workspace import (
|
||||
WorkSpaceSerializer,
|
||||
WorkSpaceMemberSerializer,
|
||||
TeamSerializer,
|
||||
WorkSpaceMemberInviteSerializer,
|
||||
WorkspaceLiteSerializer,
|
||||
WorkspaceThemeSerializer,
|
||||
|
||||
@@ -9,8 +9,6 @@ from plane.db.models import (
|
||||
User,
|
||||
Workspace,
|
||||
WorkspaceMember,
|
||||
Team,
|
||||
TeamMember,
|
||||
WorkspaceMemberInvite,
|
||||
WorkspaceTheme,
|
||||
WorkspaceUserProperties,
|
||||
@@ -99,57 +97,6 @@ class WorkSpaceMemberInviteSerializer(BaseSerializer):
|
||||
"updated_at",
|
||||
]
|
||||
|
||||
|
||||
class TeamSerializer(BaseSerializer):
|
||||
members_detail = UserLiteSerializer(
|
||||
read_only=True, source="members", many=True
|
||||
)
|
||||
members = serializers.ListField(
|
||||
child=serializers.PrimaryKeyRelatedField(queryset=User.objects.all()),
|
||||
write_only=True,
|
||||
required=False,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Team
|
||||
fields = "__all__"
|
||||
read_only_fields = [
|
||||
"workspace",
|
||||
"created_by",
|
||||
"updated_by",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
]
|
||||
|
||||
def create(self, validated_data, **kwargs):
|
||||
if "members" in validated_data:
|
||||
members = validated_data.pop("members")
|
||||
workspace = self.context["workspace"]
|
||||
team = Team.objects.create(**validated_data, workspace=workspace)
|
||||
team_members = [
|
||||
TeamMember(member=member, team=team, workspace=workspace)
|
||||
for member in members
|
||||
]
|
||||
TeamMember.objects.bulk_create(team_members, batch_size=10)
|
||||
return team
|
||||
team = Team.objects.create(**validated_data)
|
||||
return team
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
if "members" in validated_data:
|
||||
members = validated_data.pop("members")
|
||||
TeamMember.objects.filter(team=instance).delete()
|
||||
team_members = [
|
||||
TeamMember(
|
||||
member=member, team=instance, workspace=instance.workspace
|
||||
)
|
||||
for member in members
|
||||
]
|
||||
TeamMember.objects.bulk_create(team_members, batch_size=10)
|
||||
return super().update(instance, validated_data)
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
class WorkspaceThemeSerializer(BaseSerializer):
|
||||
class Meta:
|
||||
model = WorkspaceTheme
|
||||
|
||||
@@ -7,7 +7,6 @@ from plane.app.views import (
|
||||
ProjectMemberViewSet,
|
||||
ProjectMemberUserEndpoint,
|
||||
ProjectJoinEndpoint,
|
||||
AddTeamToProjectEndpoint,
|
||||
ProjectUserViewsEndpoint,
|
||||
ProjectIdentifierEndpoint,
|
||||
ProjectFavoritesViewSet,
|
||||
@@ -116,11 +115,6 @@ urlpatterns = [
|
||||
),
|
||||
name="project-member",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/team-invite/",
|
||||
AddTeamToProjectEndpoint.as_view(),
|
||||
name="projects",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/project-views/",
|
||||
ProjectUserViewsEndpoint.as_view(),
|
||||
|
||||
@@ -10,7 +10,6 @@ from plane.app.views import (
|
||||
WorkspaceMemberUserEndpoint,
|
||||
WorkspaceMemberUserViewsEndpoint,
|
||||
WorkSpaceAvailabilityCheckEndpoint,
|
||||
TeamMemberViewSet,
|
||||
UserLastProjectWithWorkspaceEndpoint,
|
||||
WorkspaceThemeViewSet,
|
||||
WorkspaceUserProfileStatsEndpoint,
|
||||
@@ -127,28 +126,6 @@ urlpatterns = [
|
||||
),
|
||||
name="leave-workspace-members",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/teams/",
|
||||
TeamMemberViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
"post": "create",
|
||||
}
|
||||
),
|
||||
name="workspace-team-members",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/teams/<uuid:pk>/",
|
||||
TeamMemberViewSet.as_view(
|
||||
{
|
||||
"put": "update",
|
||||
"patch": "partial_update",
|
||||
"delete": "destroy",
|
||||
"get": "retrieve",
|
||||
}
|
||||
),
|
||||
name="workspace-team-members",
|
||||
),
|
||||
path(
|
||||
"users/last-visited-workspace/",
|
||||
UserLastProjectWithWorkspaceEndpoint.as_view(),
|
||||
|
||||
@@ -16,7 +16,6 @@ from .project.invite import (
|
||||
|
||||
from .project.member import (
|
||||
ProjectMemberViewSet,
|
||||
AddTeamToProjectEndpoint,
|
||||
ProjectMemberUserEndpoint,
|
||||
UserProjectRolesEndpoint,
|
||||
)
|
||||
@@ -49,7 +48,6 @@ from .workspace.favorite import (
|
||||
|
||||
from .workspace.member import (
|
||||
WorkSpaceMemberViewSet,
|
||||
TeamMemberViewSet,
|
||||
WorkspaceMemberUserEndpoint,
|
||||
WorkspaceProjectMemberEndpoint,
|
||||
WorkspaceMemberUserViewsEndpoint,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# Python imports
|
||||
import json
|
||||
import base64
|
||||
|
||||
# Django imports
|
||||
from django.contrib.postgres.aggregates import ArrayAgg
|
||||
@@ -481,7 +480,9 @@ class IssueViewSet(BaseViewSet):
|
||||
project = Project.objects.get(pk=project_id, workspace__slug=slug)
|
||||
|
||||
issue = (
|
||||
Issue.objects.filter(project_id=self.kwargs.get("project_id"))
|
||||
Issue.objects.filter(
|
||||
project_id=self.kwargs.get("project_id")
|
||||
)
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.select_related("workspace", "project", "state", "parent")
|
||||
.prefetch_related("assignees", "labels", "issue_module__module")
|
||||
@@ -516,7 +517,7 @@ class IssueViewSet(BaseViewSet):
|
||||
.order_by()
|
||||
.annotate(count=Func(F("id"), function="Count"))
|
||||
.values("count")
|
||||
)
|
||||
)
|
||||
.filter(pk=pk)
|
||||
.annotate(
|
||||
label_ids=Coalesce(
|
||||
@@ -851,21 +852,9 @@ class IssuePaginatedViewSet(BaseViewSet):
|
||||
)
|
||||
).distinct()
|
||||
|
||||
def process_paginated_result(
|
||||
self, fields, results, timezone, description_binary_required=False
|
||||
):
|
||||
def process_paginated_result(self, fields, results, timezone):
|
||||
paginated_data = results.values(*fields)
|
||||
|
||||
# handling the description binary field
|
||||
if description_binary_required:
|
||||
for item in paginated_data:
|
||||
if item["description_binary"]:
|
||||
item["description_binary"] = base64.b64encode(
|
||||
item["description_binary"]
|
||||
).decode("utf-8")
|
||||
else:
|
||||
item["description_binary"] = None
|
||||
|
||||
# converting the datetime fields in paginated data
|
||||
datetime_fields = ["created_at", "updated_at"]
|
||||
paginated_data = user_timezone_converter(
|
||||
@@ -878,9 +867,6 @@ class IssuePaginatedViewSet(BaseViewSet):
|
||||
def list(self, request, slug, project_id):
|
||||
cursor = request.GET.get("cursor", None)
|
||||
is_description_required = request.GET.get("description", "false")
|
||||
is_description_binary_required = request.GET.get(
|
||||
"description_binary", "false"
|
||||
)
|
||||
updated_at = request.GET.get("updated_at__gt", None)
|
||||
|
||||
# required fields
|
||||
@@ -916,9 +902,6 @@ class IssuePaginatedViewSet(BaseViewSet):
|
||||
if str(is_description_required).lower() == "true":
|
||||
required_fields.append("description_html")
|
||||
|
||||
if str(is_description_binary_required).lower() == "true":
|
||||
required_fields.append("description_binary")
|
||||
|
||||
# querying issues
|
||||
base_queryset = Issue.issue_objects.filter(
|
||||
workspace__slug=slug, project_id=project_id
|
||||
@@ -983,19 +966,12 @@ class IssuePaginatedViewSet(BaseViewSet):
|
||||
),
|
||||
)
|
||||
|
||||
is_description_binary_required = False
|
||||
if required_fields.__contains__("description_binary"):
|
||||
is_description_binary_required = True
|
||||
|
||||
paginated_data = paginate(
|
||||
base_queryset=base_queryset,
|
||||
queryset=queryset,
|
||||
cursor=cursor,
|
||||
on_result=lambda results: self.process_paginated_result(
|
||||
required_fields,
|
||||
results,
|
||||
request.user.user_timezone,
|
||||
is_description_binary_required,
|
||||
required_fields, results, request.user.user_timezone
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1101,6 +1077,7 @@ class IssueDetailEndpoint(BaseAPIView):
|
||||
|
||||
|
||||
class IssueBulkUpdateDateEndpoint(BaseAPIView):
|
||||
|
||||
def validate_dates(
|
||||
self, current_start, current_target, new_start, new_target
|
||||
):
|
||||
@@ -1116,6 +1093,7 @@ class IssueBulkUpdateDateEndpoint(BaseAPIView):
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
|
||||
def post(self, request, slug, project_id):
|
||||
|
||||
updates = request.data.get("updates", [])
|
||||
|
||||
issue_ids = [update["id"] for update in updates]
|
||||
|
||||
@@ -21,7 +21,6 @@ from plane.db.models import (
|
||||
Project,
|
||||
ProjectMember,
|
||||
Workspace,
|
||||
TeamMember,
|
||||
IssueUserProperty,
|
||||
WorkspaceMember,
|
||||
)
|
||||
@@ -342,54 +341,6 @@ class ProjectMemberViewSet(BaseViewSet):
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class AddTeamToProjectEndpoint(BaseAPIView):
|
||||
permission_classes = [
|
||||
ProjectBasePermission,
|
||||
]
|
||||
|
||||
def post(self, request, slug, project_id):
|
||||
team_members = TeamMember.objects.filter(
|
||||
workspace__slug=slug, team__in=request.data.get("teams", [])
|
||||
).values_list("member", flat=True)
|
||||
|
||||
if len(team_members) == 0:
|
||||
return Response(
|
||||
{"error": "No such team exists"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
workspace = Workspace.objects.get(slug=slug)
|
||||
|
||||
project_members = []
|
||||
issue_props = []
|
||||
for member in team_members:
|
||||
project_members.append(
|
||||
ProjectMember(
|
||||
project_id=project_id,
|
||||
member_id=member,
|
||||
workspace=workspace,
|
||||
created_by=request.user,
|
||||
)
|
||||
)
|
||||
issue_props.append(
|
||||
IssueUserProperty(
|
||||
project_id=project_id,
|
||||
user_id=member,
|
||||
workspace=workspace,
|
||||
created_by=request.user,
|
||||
)
|
||||
)
|
||||
|
||||
ProjectMember.objects.bulk_create(
|
||||
project_members, batch_size=10, ignore_conflicts=True
|
||||
)
|
||||
|
||||
_ = IssueUserProperty.objects.bulk_create(
|
||||
issue_props, batch_size=10, ignore_conflicts=True
|
||||
)
|
||||
|
||||
serializer = ProjectMemberSerializer(project_members, many=True)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class ProjectMemberUserEndpoint(BaseAPIView):
|
||||
|
||||
@@ -24,7 +24,6 @@ from plane.app.permissions import (
|
||||
# Module imports
|
||||
from plane.app.serializers import (
|
||||
ProjectMemberRoleSerializer,
|
||||
TeamSerializer,
|
||||
UserLiteSerializer,
|
||||
WorkspaceMemberAdminSerializer,
|
||||
WorkspaceMemberMeSerializer,
|
||||
@@ -34,7 +33,6 @@ from plane.app.views.base import BaseAPIView
|
||||
from plane.db.models import (
|
||||
Project,
|
||||
ProjectMember,
|
||||
Team,
|
||||
User,
|
||||
Workspace,
|
||||
WorkspaceMember,
|
||||
@@ -351,63 +349,4 @@ class WorkspaceProjectMemberEndpoint(BaseAPIView):
|
||||
project_members_dict[str(project_id)] = []
|
||||
project_members_dict[str(project_id)].append(project_member)
|
||||
|
||||
return Response(project_members_dict, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class TeamMemberViewSet(BaseViewSet):
|
||||
serializer_class = TeamSerializer
|
||||
model = Team
|
||||
permission_classes = [
|
||||
WorkSpaceAdminPermission,
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
"member__display_name",
|
||||
"member__first_name",
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
return self.filter_queryset(
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(workspace__slug=self.kwargs.get("slug"))
|
||||
.select_related("workspace", "workspace__owner")
|
||||
.prefetch_related("members")
|
||||
)
|
||||
|
||||
def create(self, request, slug):
|
||||
members = list(
|
||||
WorkspaceMember.objects.filter(
|
||||
workspace__slug=slug,
|
||||
member__id__in=request.data.get("members", []),
|
||||
is_active=True,
|
||||
)
|
||||
.annotate(member_str_id=Cast("member", output_field=CharField()))
|
||||
.distinct()
|
||||
.values_list("member_str_id", flat=True)
|
||||
)
|
||||
|
||||
if len(members) != len(request.data.get("members", [])):
|
||||
users = list(
|
||||
set(request.data.get("members", [])).difference(members)
|
||||
)
|
||||
users = User.objects.filter(pk__in=users)
|
||||
|
||||
serializer = UserLiteSerializer(users, many=True)
|
||||
return Response(
|
||||
{
|
||||
"error": f"{len(users)} of the member(s) are not a part of the workspace",
|
||||
"members": serializer.data,
|
||||
},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
workspace = Workspace.objects.get(slug=slug)
|
||||
|
||||
serializer = TeamSerializer(
|
||||
data=request.data, context={"workspace": workspace}
|
||||
)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(project_members_dict, status=status.HTTP_200_OK)
|
||||
@@ -0,0 +1,74 @@
|
||||
# Generated by Django 4.2.15 on 2024-11-08 14:24
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0085_intake_intakeissue_remove_inboxissue_created_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='teammember',
|
||||
unique_together=None,
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teammember',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teammember',
|
||||
name='member',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teammember',
|
||||
name='team',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teammember',
|
||||
name='updated_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teammember',
|
||||
name='workspace',
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='teampage',
|
||||
unique_together=None,
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teampage',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teampage',
|
||||
name='page',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teampage',
|
||||
name='team',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teampage',
|
||||
name='updated_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='teampage',
|
||||
name='workspace',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='page',
|
||||
name='teams',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Team',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='TeamMember',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='TeamPage',
|
||||
),
|
||||
]
|
||||
@@ -77,8 +77,6 @@ from .user import Account, Profile, User
|
||||
from .view import IssueView
|
||||
from .webhook import Webhook, WebhookLog
|
||||
from .workspace import (
|
||||
Team,
|
||||
TeamMember,
|
||||
Workspace,
|
||||
WorkspaceBaseModel,
|
||||
WorkspaceMember,
|
||||
|
||||
@@ -52,9 +52,6 @@ class Page(BaseModel):
|
||||
projects = models.ManyToManyField(
|
||||
"db.Project", related_name="pages", through="db.ProjectPage"
|
||||
)
|
||||
teams = models.ManyToManyField(
|
||||
"db.Team", related_name="pages", through="db.TeamPage"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Page"
|
||||
@@ -169,33 +166,6 @@ class ProjectPage(BaseModel):
|
||||
def __str__(self):
|
||||
return f"{self.project.name} {self.page.name}"
|
||||
|
||||
|
||||
class TeamPage(BaseModel):
|
||||
team = models.ForeignKey(
|
||||
"db.Team", on_delete=models.CASCADE, related_name="team_pages"
|
||||
)
|
||||
page = models.ForeignKey(
|
||||
"db.Page", on_delete=models.CASCADE, related_name="team_pages"
|
||||
)
|
||||
workspace = models.ForeignKey(
|
||||
"db.Workspace", on_delete=models.CASCADE, related_name="team_pages"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = ["team", "page", "deleted_at"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["team", "page"],
|
||||
condition=models.Q(deleted_at__isnull=True),
|
||||
name="team_page_unique_team_page_when_deleted_at_null",
|
||||
)
|
||||
]
|
||||
verbose_name = "Team Page"
|
||||
verbose_name_plural = "Team Pages"
|
||||
db_table = "team_pages"
|
||||
ordering = ("-created_at",)
|
||||
|
||||
|
||||
class PageVersion(BaseModel):
|
||||
workspace = models.ForeignKey(
|
||||
"db.Workspace",
|
||||
|
||||
@@ -259,71 +259,6 @@ class WorkspaceMemberInvite(BaseModel):
|
||||
return f"{self.workspace.name} {self.email} {self.accepted}"
|
||||
|
||||
|
||||
class Team(BaseModel):
|
||||
name = models.CharField(max_length=255, verbose_name="Team Name")
|
||||
description = models.TextField(verbose_name="Team Description", blank=True)
|
||||
members = models.ManyToManyField(
|
||||
settings.AUTH_USER_MODEL,
|
||||
blank=True,
|
||||
related_name="members",
|
||||
through="TeamMember",
|
||||
through_fields=("team", "member"),
|
||||
)
|
||||
workspace = models.ForeignKey(
|
||||
Workspace, on_delete=models.CASCADE, related_name="workspace_team"
|
||||
)
|
||||
logo_props = models.JSONField(default=dict)
|
||||
|
||||
def __str__(self):
|
||||
"""Return name of the team"""
|
||||
return f"{self.name} <{self.workspace.name}>"
|
||||
|
||||
class Meta:
|
||||
unique_together = ["name", "workspace", "deleted_at"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["name", "workspace"],
|
||||
condition=models.Q(deleted_at__isnull=True),
|
||||
name="team_unique_name_workspace_when_deleted_at_null",
|
||||
)
|
||||
]
|
||||
verbose_name = "Team"
|
||||
verbose_name_plural = "Teams"
|
||||
db_table = "teams"
|
||||
ordering = ("-created_at",)
|
||||
|
||||
|
||||
class TeamMember(BaseModel):
|
||||
workspace = models.ForeignKey(
|
||||
Workspace, on_delete=models.CASCADE, related_name="team_member"
|
||||
)
|
||||
team = models.ForeignKey(
|
||||
Team, on_delete=models.CASCADE, related_name="team_member"
|
||||
)
|
||||
member = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="team_member",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.team.name
|
||||
|
||||
class Meta:
|
||||
unique_together = ["team", "member", "deleted_at"]
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["team", "member"],
|
||||
condition=models.Q(deleted_at__isnull=True),
|
||||
name="team_member_unique_team_member_when_deleted_at_null",
|
||||
)
|
||||
]
|
||||
verbose_name = "Team Member"
|
||||
verbose_name_plural = "Team Members"
|
||||
db_table = "team_members"
|
||||
ordering = ("-created_at",)
|
||||
|
||||
|
||||
class WorkspaceTheme(BaseModel):
|
||||
workspace = models.ForeignKey(
|
||||
"db.Workspace", on_delete=models.CASCADE, related_name="themes"
|
||||
|
||||
@@ -101,19 +101,6 @@
|
||||
--color-sidebar-shadow-2xl: var(--color-shadow-2xl);
|
||||
--color-sidebar-shadow-3xl: var(--color-shadow-3xl);
|
||||
--color-sidebar-shadow-4xl: var(--color-shadow-4xl);
|
||||
|
||||
/* pi */
|
||||
--color-pi-50: var(--color-background-90);
|
||||
--color-pi-100: var(--color-background-90);
|
||||
--color-pi-200: var(--color-primary-200);
|
||||
--color-pi-300: var(--color-primary-200);
|
||||
--color-pi-400: var(--color-primary-200);
|
||||
--color-pi-500: var(--color-primary-200);
|
||||
--color-pi-600: 151, 150, 246;
|
||||
--color-pi-700: var(--color-primary-100);
|
||||
--color-pi-800: 57, 56, 149;
|
||||
--color-pi-900: 30, 29, 78;
|
||||
--color-pi-950: 14, 14, 37;
|
||||
}
|
||||
|
||||
[data-theme="light"],
|
||||
@@ -123,19 +110,6 @@
|
||||
--color-background-100: 255, 255, 255; /* primary bg */
|
||||
--color-background-90: 247, 247, 247; /* secondary bg */
|
||||
--color-background-80: 232, 232, 232; /* tertiary bg */
|
||||
|
||||
/* pi */
|
||||
--color-pi-50: var(--color-background-90);
|
||||
--color-pi-100: var(--color-background-90);
|
||||
--color-pi-200: var(--color-primary-200);
|
||||
--color-pi-300: var(--color-primary-200);
|
||||
--color-pi-400: var(--color-primary-200);
|
||||
--color-pi-500: var(--color-primary-200);
|
||||
--color-pi-600: 151, 150, 246;
|
||||
--color-pi-700: var(--color-primary-100);
|
||||
--color-pi-800: 57, 56, 149;
|
||||
--color-pi-900: 30, 29, 78;
|
||||
--color-pi-950: 14, 14, 37;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
@@ -226,18 +200,6 @@
|
||||
--color-shadow-xl: 0px 0px 14px 0px rgba(0, 0, 0, 0.25), 0px 6px 10px 0px rgba(0, 0, 0, 0.55);
|
||||
--color-shadow-2xl: 0px 0px 18px 0px rgba(0, 0, 0, 0.25), 0px 8px 12px 0px rgba(0, 0, 0, 0.6);
|
||||
--color-shadow-3xl: 0px 4px 24px 0px rgba(0, 0, 0, 0.3), 0px 12px 40px 0px rgba(0, 0, 0, 0.65);
|
||||
/* pi */
|
||||
--color-pi-50: var(--color-background-90);
|
||||
--color-pi-100: var(--color-background-90);
|
||||
--color-pi-200: var(--color-primary-200);
|
||||
--color-pi-300: var(--color-primary-200);
|
||||
--color-pi-400: var(--color-primary-200);
|
||||
--color-pi-500: var(--color-primary-200);
|
||||
--color-pi-600: 151, 150, 246;
|
||||
--color-pi-700: var(--color-primary-100);
|
||||
--color-pi-800: 57, 56, 149;
|
||||
--color-pi-900: 30, 29, 78;
|
||||
--color-pi-950: 14, 14, 37;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
|
||||
@@ -286,7 +286,7 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
|
||||
{shouldRenderDuplicateModal && (
|
||||
<div
|
||||
ref={modalContainerRef}
|
||||
className="relative flex flex-col gap-2.5 px-3 py-4 rounded-lg shadow-xl bg-pi-50"
|
||||
className="relative flex flex-col gap-2.5 h-full px-3 py-4 rounded-lg shadow-xl bg-pi-50"
|
||||
style={{ maxHeight: formRef?.current?.offsetHeight ? `${formRef.current.offsetHeight}px` : "436px" }}
|
||||
>
|
||||
<DuplicateModalRoot
|
||||
|
||||
@@ -11,7 +11,7 @@ import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { IssueCommentCreate } from "@/components/issues";
|
||||
import { IssueActivityCommentRoot } from "@/components/issues/issue-detail";
|
||||
// hooks
|
||||
import { useIssueDetail, useProject, useUser, useUserPermissions } from "@/hooks/store";
|
||||
import { useIssueDetail, useProject, useUserPermissions } from "@/hooks/store";
|
||||
// plane web components
|
||||
import { ActivityFilterRoot, IssueActivityWorklogCreateButton } from "@/plane-web/components/issues/worklog";
|
||||
// plane web constants
|
||||
@@ -38,25 +38,15 @@ export type TActivityOperations = {
|
||||
|
||||
export const IssueActivity: FC<TIssueActivity> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, isIntakeIssue = false } = props;
|
||||
// state
|
||||
const [selectedFilters, setSelectedFilters] = useState<TActivityFilters[]>(defaultActivityFilters);
|
||||
// hooks
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
createComment,
|
||||
updateComment,
|
||||
removeComment,
|
||||
} = useIssueDetail();
|
||||
const { createComment, updateComment, removeComment } = useIssueDetail();
|
||||
const { projectPermissionsByWorkspaceSlugAndProjectId } = useUserPermissions();
|
||||
const { getProjectById } = useProject();
|
||||
const { data: currentUser } = useUser();
|
||||
//derived values
|
||||
const issue = issueId ? getIssueById(issueId) : undefined;
|
||||
const currentUserProjectRole = projectPermissionsByWorkspaceSlugAndProjectId(workspaceSlug, projectId);
|
||||
const isAdmin = (currentUserProjectRole ?? EUserPermissions.GUEST) === EUserPermissions.ADMIN;
|
||||
const isGuest = (currentUserProjectRole ?? EUserPermissions.GUEST) === EUserPermissions.GUEST;
|
||||
const isAssigned = issue?.assignee_ids && currentUser?.id ? issue?.assignee_ids.includes(currentUser?.id) : false;
|
||||
const isWorklogButtonEnabled = !isIntakeIssue && !isGuest && (isAdmin || isAssigned);
|
||||
const isGuest = (projectPermissionsByWorkspaceSlugAndProjectId(workspaceSlug, projectId) ?? EUserPermissions.GUEST) === EUserPermissions.GUEST;
|
||||
const isWorklogButtonEnabled = !isIntakeIssue && !isGuest;
|
||||
// state
|
||||
const [selectedFilters, setSelectedFilters] = useState<TActivityFilters[]>(defaultActivityFilters);
|
||||
// toggle filter
|
||||
const toggleFilter = (filter: TActivityFilters) => {
|
||||
setSelectedFilters((prevFilters) => {
|
||||
|
||||
@@ -513,7 +513,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
{shouldRenderDuplicateModal && (
|
||||
<div
|
||||
ref={modalContainerRef}
|
||||
className="relative flex flex-col gap-2.5 px-3 py-4 rounded-lg shadow-xl bg-pi-50"
|
||||
className="relative flex flex-col gap-2.5 h-full px-3 py-4 rounded-lg shadow-xl bg-pi-50"
|
||||
style={{ maxHeight: formRef?.current?.offsetHeight ? `${formRef.current.offsetHeight}px` : "436px" }}
|
||||
>
|
||||
<DuplicateModalRoot
|
||||
|
||||
@@ -120,19 +120,6 @@
|
||||
--color-sidebar-shadow-2xl: var(--color-shadow-2xl);
|
||||
--color-sidebar-shadow-3xl: var(--color-shadow-3xl);
|
||||
--color-sidebar-shadow-4xl: var(--color-shadow-4xl);
|
||||
|
||||
/* pi */
|
||||
--color-pi-50: var(--color-background-90);
|
||||
--color-pi-100: var(--color-background-90);
|
||||
--color-pi-200: var(--color-primary-200);
|
||||
--color-pi-300: var(--color-primary-200);
|
||||
--color-pi-400: var(--color-primary-200);
|
||||
--color-pi-500: var(--color-primary-200);
|
||||
--color-pi-600: 151, 150, 246;
|
||||
--color-pi-700: var(--color-primary-100);
|
||||
--color-pi-800: 57, 56, 149;
|
||||
--color-pi-900: 30, 29, 78;
|
||||
--color-pi-950: 14, 14, 37;
|
||||
}
|
||||
|
||||
[data-theme="light"],
|
||||
@@ -142,19 +129,6 @@
|
||||
--color-background-100: 255, 255, 255; /* primary bg */
|
||||
--color-background-90: 247, 247, 247; /* secondary bg */
|
||||
--color-background-80: 232, 232, 232; /* tertiary bg */
|
||||
|
||||
/* pi */
|
||||
--color-pi-50: var(--color-background-90);
|
||||
--color-pi-100: var(--color-background-90);
|
||||
--color-pi-200: var(--color-primary-200);
|
||||
--color-pi-300: var(--color-primary-200);
|
||||
--color-pi-400: var(--color-primary-200);
|
||||
--color-pi-500: var(--color-primary-200);
|
||||
--color-pi-600: 151, 150, 246;
|
||||
--color-pi-700: var(--color-primary-100);
|
||||
--color-pi-800: 57, 56, 149;
|
||||
--color-pi-900: 30, 29, 78;
|
||||
--color-pi-950: 14, 14, 37;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
@@ -256,19 +230,6 @@
|
||||
--color-shadow-xl: 0px 0px 14px 0px rgba(0, 0, 0, 0.25), 0px 6px 10px 0px rgba(0, 0, 0, 0.55);
|
||||
--color-shadow-2xl: 0px 0px 18px 0px rgba(0, 0, 0, 0.25), 0px 8px 12px 0px rgba(0, 0, 0, 0.6);
|
||||
--color-shadow-3xl: 0px 4px 24px 0px rgba(0, 0, 0, 0.3), 0px 12px 40px 0px rgba(0, 0, 0, 0.65);
|
||||
|
||||
/* pi */
|
||||
--color-pi-50: var(--color-background-90);
|
||||
--color-pi-100: var(--color-background-90);
|
||||
--color-pi-200: var(--color-primary-200);
|
||||
--color-pi-300: var(--color-primary-200);
|
||||
--color-pi-400: var(--color-primary-200);
|
||||
--color-pi-500: var(--color-primary-200);
|
||||
--color-pi-600: 151, 150, 246;
|
||||
--color-pi-700: var(--color-primary-100);
|
||||
--color-pi-800: 57, 56, 149;
|
||||
--color-pi-900: 30, 29, 78;
|
||||
--color-pi-950: 14, 14, 37;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
|
||||
Reference in New Issue
Block a user