diff --git a/apiserver/plane/app/serializers/__init__.py b/apiserver/plane/app/serializers/__init__.py index 2e2c91baa1f..6c9e1fed17a 100644 --- a/apiserver/plane/app/serializers/__init__.py +++ b/apiserver/plane/app/serializers/__init__.py @@ -13,7 +13,6 @@ from .workspace import ( WorkSpaceSerializer, WorkSpaceMemberSerializer, - TeamSerializer, WorkSpaceMemberInviteSerializer, WorkspaceLiteSerializer, WorkspaceThemeSerializer, diff --git a/apiserver/plane/app/serializers/workspace.py b/apiserver/plane/app/serializers/workspace.py index 1a2b89bba61..ce1c75dbf53 100644 --- a/apiserver/plane/app/serializers/workspace.py +++ b/apiserver/plane/app/serializers/workspace.py @@ -9,8 +9,6 @@ User, Workspace, WorkspaceMember, - Team, - TeamMember, WorkspaceMemberInvite, WorkspaceTheme, WorkspaceUserProperties, @@ -99,57 +97,6 @@ class Meta: "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 diff --git a/apiserver/plane/app/urls/project.py b/apiserver/plane/app/urls/project.py index 0807c7616a2..4ea4522494d 100644 --- a/apiserver/plane/app/urls/project.py +++ b/apiserver/plane/app/urls/project.py @@ -7,7 +7,6 @@ ProjectMemberViewSet, ProjectMemberUserEndpoint, ProjectJoinEndpoint, - AddTeamToProjectEndpoint, ProjectUserViewsEndpoint, ProjectIdentifierEndpoint, ProjectFavoritesViewSet, @@ -116,11 +115,6 @@ ), name="project-member", ), - path( - "workspaces//projects//team-invite/", - AddTeamToProjectEndpoint.as_view(), - name="projects", - ), path( "workspaces//projects//project-views/", ProjectUserViewsEndpoint.as_view(), diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py index fb6f4c13acc..6bee2523883 100644 --- a/apiserver/plane/app/urls/workspace.py +++ b/apiserver/plane/app/urls/workspace.py @@ -10,7 +10,6 @@ WorkspaceMemberUserEndpoint, WorkspaceMemberUserViewsEndpoint, WorkSpaceAvailabilityCheckEndpoint, - TeamMemberViewSet, UserLastProjectWithWorkspaceEndpoint, WorkspaceThemeViewSet, WorkspaceUserProfileStatsEndpoint, @@ -127,28 +126,6 @@ ), name="leave-workspace-members", ), - path( - "workspaces//teams/", - TeamMemberViewSet.as_view( - { - "get": "list", - "post": "create", - } - ), - name="workspace-team-members", - ), - path( - "workspaces//teams//", - TeamMemberViewSet.as_view( - { - "put": "update", - "patch": "partial_update", - "delete": "destroy", - "get": "retrieve", - } - ), - name="workspace-team-members", - ), path( "users/last-visited-workspace/", UserLastProjectWithWorkspaceEndpoint.as_view(), diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py index 159686fa3ac..e67b9d2efb7 100644 --- a/apiserver/plane/app/views/__init__.py +++ b/apiserver/plane/app/views/__init__.py @@ -16,7 +16,6 @@ from .project.member import ( ProjectMemberViewSet, - AddTeamToProjectEndpoint, ProjectMemberUserEndpoint, UserProjectRolesEndpoint, ) @@ -49,7 +48,6 @@ from .workspace.member import ( WorkSpaceMemberViewSet, - TeamMemberViewSet, WorkspaceMemberUserEndpoint, WorkspaceProjectMemberEndpoint, WorkspaceMemberUserViewsEndpoint, diff --git a/apiserver/plane/app/views/project/member.py b/apiserver/plane/app/views/project/member.py index ccb5e75216e..36b2d3076c2 100644 --- a/apiserver/plane/app/views/project/member.py +++ b/apiserver/plane/app/views/project/member.py @@ -21,7 +21,6 @@ Project, ProjectMember, Workspace, - TeamMember, IssueUserProperty, WorkspaceMember, ) @@ -342,54 +341,6 @@ def leave(self, request, slug, project_id): 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): diff --git a/apiserver/plane/app/views/workspace/member.py b/apiserver/plane/app/views/workspace/member.py index c71df21ac4d..c41441a8566 100644 --- a/apiserver/plane/app/views/workspace/member.py +++ b/apiserver/plane/app/views/workspace/member.py @@ -24,7 +24,6 @@ # Module imports from plane.app.serializers import ( ProjectMemberRoleSerializer, - TeamSerializer, UserLiteSerializer, WorkspaceMemberAdminSerializer, WorkspaceMemberMeSerializer, @@ -34,7 +33,6 @@ from plane.db.models import ( Project, ProjectMember, - Team, User, Workspace, WorkspaceMember, @@ -351,63 +349,4 @@ def get(self, request, slug): 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) \ No newline at end of file diff --git a/apiserver/plane/db/migrations/0085_alter_teammember_unique_together_and_more.py b/apiserver/plane/db/migrations/0085_alter_teammember_unique_together_and_more.py new file mode 100644 index 00000000000..eabe7af4a21 --- /dev/null +++ b/apiserver/plane/db/migrations/0085_alter_teammember_unique_together_and_more.py @@ -0,0 +1,74 @@ +# Generated by Django 4.2.15 on 2024-11-08 13:30 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0084_remove_label_label_unique_name_project_when_deleted_at_null_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', + ), + ] diff --git a/apiserver/plane/db/models/__init__.py b/apiserver/plane/db/models/__init__.py index ff930447ac9..577435599d9 100644 --- a/apiserver/plane/db/models/__init__.py +++ b/apiserver/plane/db/models/__init__.py @@ -77,8 +77,6 @@ from .view import IssueView from .webhook import Webhook, WebhookLog from .workspace import ( - Team, - TeamMember, Workspace, WorkspaceBaseModel, WorkspaceMember, diff --git a/apiserver/plane/db/models/page.py b/apiserver/plane/db/models/page.py index 433e74a12dc..d0157414aa1 100644 --- a/apiserver/plane/db/models/page.py +++ b/apiserver/plane/db/models/page.py @@ -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 Meta: 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", diff --git a/apiserver/plane/db/models/workspace.py b/apiserver/plane/db/models/workspace.py index 8dd4d44f09d..a8d53812005 100644 --- a/apiserver/plane/db/models/workspace.py +++ b/apiserver/plane/db/models/workspace.py @@ -259,71 +259,6 @@ def __str__(self): 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" diff --git a/web/core/components/editor/rich-text-editor/rich-text-editor.tsx b/web/core/components/editor/rich-text-editor/rich-text-editor.tsx index 5e7eb80d67f..fb734bc8d12 100644 --- a/web/core/components/editor/rich-text-editor/rich-text-editor.tsx +++ b/web/core/components/editor/rich-text-editor/rich-text-editor.tsx @@ -54,7 +54,7 @@ export const RichTextEditor = forwardRef ); });