fix: migration and optimisation

This commit is contained in:
NarayanBavisetti 2023-11-13 19:12:55 +05:30
parent 598c22f91d
commit 73c2416055
9 changed files with 324 additions and 311 deletions

View File

@ -85,7 +85,7 @@ from .integration import (
from .importer import ImporterSerializer from .importer import ImporterSerializer
from .page import PageSerializer, PageTransactionSerializer, SubPageSerializer, PageFavoriteSerializer from .page import PageSerializer, PageLogSerializer, SubPageSerializer, PageFavoriteSerializer
from .estimate import ( from .estimate import (
EstimateSerializer, EstimateSerializer,

View File

@ -6,7 +6,7 @@ from .base import BaseSerializer
from .issue import IssueFlatSerializer, LabelLiteSerializer from .issue import IssueFlatSerializer, LabelLiteSerializer
from .workspace import WorkspaceLiteSerializer from .workspace import WorkspaceLiteSerializer
from .project import ProjectLiteSerializer from .project import ProjectLiteSerializer
from plane.db.models import Page, PageTransaction, PageFavorite, PageLabel, Label, Issue, Module from plane.db.models import Page, PageLog, PageFavorite, PageLabel, Label, Issue, Module
class PageSerializer(BaseSerializer): class PageSerializer(BaseSerializer):
@ -84,7 +84,7 @@ class SubPageSerializer(BaseSerializer):
entity_details = serializers.SerializerMethodField() entity_details = serializers.SerializerMethodField()
class Meta: class Meta:
model = PageTransaction model = PageLog
fields = "__all__" fields = "__all__"
read_only_fields = [ read_only_fields = [
"workspace", "workspace",
@ -103,10 +103,10 @@ class SubPageSerializer(BaseSerializer):
return None return None
class PageTransactionSerializer(BaseSerializer): class PageLogSerializer(BaseSerializer):
class Meta: class Meta:
model = PageTransaction model = PageLog
fields = "__all__" fields = "__all__"
read_only_fields = [ read_only_fields = [
"workspace", "workspace",

View File

@ -3,9 +3,9 @@ from django.urls import path
from plane.api.views import ( from plane.api.views import (
PageViewSet, PageViewSet,
PageBlockViewSet,
PageFavoriteViewSet, PageFavoriteViewSet,
CreateIssueFromPageBlockEndpoint, PageLogEndpoint,
SubPagesEndpoint,
) )
@ -31,27 +31,6 @@ urlpatterns = [
), ),
name="project-pages", name="project-pages",
), ),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/page-blocks/",
PageBlockViewSet.as_view(
{
"get": "list",
"post": "create",
}
),
name="project-page-blocks",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/page-blocks/<uuid:pk>/",
PageBlockViewSet.as_view(
{
"get": "retrieve",
"patch": "partial_update",
"delete": "destroy",
}
),
name="project-page-blocks",
),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-pages/", "workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-pages/",
PageFavoriteViewSet.as_view( PageFavoriteViewSet.as_view(
@ -72,8 +51,83 @@ urlpatterns = [
name="user-favorite-pages", name="user-favorite-pages",
), ),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/page-blocks/<uuid:page_block_id>/issues/", "workspaces/<str:slug>/projects/<uuid:project_id>/pages/",
CreateIssueFromPageBlockEndpoint.as_view(), PageViewSet.as_view(
name="page-block-issues", {
"get": "list",
"post": "create",
}
),
name="project-pages",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/",
PageViewSet.as_view(
{
"get": "retrieve",
"patch": "partial_update",
"delete": "destroy",
}
),
name="project-pages",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/archive/",
PageViewSet.as_view(
{
"post": "archive",
}
),
name="project-page-archive",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/unarchive/",
PageViewSet.as_view(
{
"post": "unarchive",
}
),
name="project-page-unarchive",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-pages/",
PageViewSet.as_view(
{
"get": "archive_list",
}
),
name="project-pages",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/lock/",
PageViewSet.as_view(
{
"post": "lock",
}
),
name="project-pages",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/unlock/",
PageViewSet.as_view(
{
"post": "unlock",
}
),
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/transactions/",
PageLogEndpoint.as_view(),
name="page-transactions",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/transactions/<uuid:transaction>/",
PageLogEndpoint.as_view(),
name="page-transactions",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/sub-pages/",
SubPagesEndpoint.as_view(),
name="sub-page",
), ),
] ]

View File

@ -124,7 +124,7 @@ from plane.api.views import (
## End Modules ## End Modules
# Pages # Pages
PageViewSet, PageViewSet,
PageTransactionEndpoint, PageLogEndpoint,
SubPagesEndpoint, SubPagesEndpoint,
PageFavoriteViewSet, PageFavoriteViewSet,
CreateIssueFromBlockEndpoint, CreateIssueFromBlockEndpoint,
@ -1268,11 +1268,11 @@ urlpatterns = [
), ),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/transactions/", "workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/transactions/",
PageTransactionEndpoint.as_view(), name="page-transactions" PageLogEndpoint.as_view(), name="page-transactions"
), ),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/transactions/<uuid:transaction>/", "workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/transactions/<uuid:transaction>/",
PageTransactionEndpoint.as_view(), name="page-transactions" PageLogEndpoint.as_view(), name="page-transactions"
), ),
path( path(
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/sub-pages/", "workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/sub-pages/",

View File

@ -145,7 +145,7 @@ from .importer import (
from .page import ( from .page import (
PageViewSet, PageViewSet,
PageFavoriteViewSet, PageFavoriteViewSet,
PageTransactionEndpoint, PageLogEndpoint,
SubPagesEndpoint, SubPagesEndpoint,
CreateIssueFromBlockEndpoint, CreateIssueFromBlockEndpoint,
) )

View File

@ -1,5 +1,5 @@
# Python imports # Python imports
from datetime import timedelta, date from datetime import timedelta, date, datetime
# Django imports # Django imports
from django.db import connection from django.db import connection
@ -29,12 +29,12 @@ from plane.db.models import (
Issue, Issue,
IssueAssignee, IssueAssignee,
IssueActivity, IssueActivity,
PageTransaction, PageLog,
) )
from plane.api.serializers import ( from plane.api.serializers import (
PageSerializer, PageSerializer,
PageFavoriteSerializer, PageFavoriteSerializer,
PageTransactionSerializer, PageLogSerializer,
IssueLiteSerializer, IssueLiteSerializer,
SubPageSerializer, SubPageSerializer,
) )
@ -161,7 +161,6 @@ class PageViewSet(BaseViewSet):
) )
def lock(self, request, slug, project_id, pk): def lock(self, request, slug, project_id, pk):
try:
page = Page.objects.filter( page = Page.objects.filter(
pk=pk, workspace__slug=slug, project_id=project_id pk=pk, workspace__slug=slug, project_id=project_id
) )
@ -174,12 +173,9 @@ class PageViewSet(BaseViewSet):
page.is_locked = True page.is_locked = True
page.save() page.save()
except Exception as e: return Response(status=status.HTTP_204_NO_CONTENT)
capture_exception(e)
return Response({"error": "Something went wrong please try again later"})
def unlock(self, request, slug, project_id, pk): def unlock(self, request, slug, project_id, pk):
try:
page = Page.objects.get(pk=pk, workspace__slug=slug, project_id=project_id) page = Page.objects.get(pk=pk, workspace__slug=slug, project_id=project_id)
# only the owner can unlock the page # only the owner can unlock the page
@ -192,15 +188,8 @@ class PageViewSet(BaseViewSet):
page.save() page.save()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
def list(self, request, slug, project_id): def list(self, request, slug, project_id):
try:
queryset = self.get_queryset().filter(archived_at__isnull=True) queryset = self.get_queryset().filter(archived_at__isnull=True)
page_view = request.GET.get("page_view", False) page_view = request.GET.get("page_view", False)
@ -263,15 +252,8 @@ class PageViewSet(BaseViewSet):
return Response( return Response(
{"error": "No matching view found"}, status=status.HTTP_400_BAD_REQUEST {"error": "No matching view found"}, status=status.HTTP_400_BAD_REQUEST
) )
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
def archive(self, request, slug, project_id, page_id): def archive(self, request, slug, project_id, page_id):
try:
_ = Page.objects.get( _ = Page.objects.get(
project_id=project_id, project_id=project_id,
owned_by_id=request.user.id, owned_by_id=request.user.id,
@ -282,20 +264,8 @@ class PageViewSet(BaseViewSet):
unarchive_archive_page_and_descendants(page_id, datetime.now()) unarchive_archive_page_and_descendants(page_id, datetime.now())
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
except Page.DoesNotExist:
return Response(
{"error": "Page does not exist"},
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
def unarchive(self, request, slug, project_id, page_id): def unarchive(self, request, slug, project_id, page_id):
try:
page = Page.objects.get( page = Page.objects.get(
project_id=project_id, project_id=project_id,
owned_by_id=request.user.id, owned_by_id=request.user.id,
@ -309,20 +279,8 @@ class PageViewSet(BaseViewSet):
unarchive_archive_page_and_descendants(page_id, None) unarchive_archive_page_and_descendants(page_id, None)
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
except Page.DoesNotExist:
return Response(
{"error": "Page does not exist"},
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
def archive_list(self, request, slug, project_id): def archive_list(self, request, slug, project_id):
try:
pages = ( pages = (
Page.objects.filter( Page.objects.filter(
project_id=project_id, project_id=project_id,
@ -341,12 +299,6 @@ class PageViewSet(BaseViewSet):
PageSerializer(pages, many=True).data, status=status.HTTP_200_OK PageSerializer(pages, many=True).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,
)
class PageFavoriteViewSet(BaseViewSet): class PageFavoriteViewSet(BaseViewSet):
@ -384,58 +336,38 @@ class PageFavoriteViewSet(BaseViewSet):
page_favorite.delete() page_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
class PageTransactionEndpoint(BaseAPIView): class PageLogEndpoint(BaseAPIView):
permission_classes = [ permission_classes = [
ProjectEntityPermission, ProjectEntityPermission,
] ]
serializer_class = PageTransactionSerializer serializer_class = PageLogSerializer
model = PageTransaction model = PageLog
def post(self, request, slug, project_id, page_id): def post(self, request, slug, project_id, page_id):
try: serializer = PageLogSerializer(data=request.data)
serializer = PageTransactionSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save(project_id=project_id, page_id=page_id) serializer.save(project_id=project_id, page_id=page_id)
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later", "er": str(e)},
status=status.HTTP_400_BAD_REQUEST,
)
def patch(self, request, slug, project_id, page_id, transaction): def patch(self, request, slug, project_id, page_id, transaction):
try: page_transaction = PageLog.objects.get(
page_transaction = PageTransaction.objects.get(
workspace__slug=slug, workspace__slug=slug,
project_id=project_id, project_id=project_id,
page_id=page_id, page_id=page_id,
transaction=transaction, transaction=transaction,
) )
serializer = PageTransactionSerializer( serializer = PageLogSerializer(
page_transaction, data=request.data, partial=True page_transaction, data=request.data, partial=True
) )
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except PageTransaction.DoesNotExist:
return Response(
{"error": "Transaction Does not exists"},
status=status.HTTP_404_NOT_FOUND,
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
def delete(self, request, slug, project_id, page_id, transaction): def delete(self, request, slug, project_id, page_id, transaction):
try: transaction = PageLog.objects.get(
transaction = PageTransaction.objects.get(
workspace__slug=slug, workspace__slug=slug,
project_id=project_id, project_id=project_id,
page_id=page_id, page_id=page_id,
@ -444,16 +376,6 @@ class PageTransactionEndpoint(BaseAPIView):
# Delete the transaction object # Delete the transaction object
transaction.delete() transaction.delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
except transaction.DoesNotExist:
return Response(
{"error": "Transaction doesn't exist"}, status=status.HTTP_404_NOT_FOUND
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
class CreateIssueFromBlockEndpoint(BaseAPIView): class CreateIssueFromBlockEndpoint(BaseAPIView):
@ -462,7 +384,6 @@ class CreateIssueFromBlockEndpoint(BaseAPIView):
] ]
def post(self, request, slug, project_id, page_id): def post(self, request, slug, project_id, page_id):
try:
page = Page.objects.get( page = Page.objects.get(
workspace__slug=slug, workspace__slug=slug,
project_id=project_id, project_id=project_id,
@ -485,16 +406,6 @@ class CreateIssueFromBlockEndpoint(BaseAPIView):
) )
return Response(IssueLiteSerializer(issue).data, status=status.HTTP_200_OK) return Response(IssueLiteSerializer(issue).data, status=status.HTTP_200_OK)
except Page.DoesNotExist:
return Response(
{"error": "Page Block does not exist"}, status=status.HTTP_404_NOT_FOUND
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
class SubPagesEndpoint(BaseAPIView): class SubPagesEndpoint(BaseAPIView):
@ -504,9 +415,8 @@ class SubPagesEndpoint(BaseAPIView):
@method_decorator(gzip_page) @method_decorator(gzip_page)
def get(self, request, slug, project_id, page_id): def get(self, request, slug, project_id, page_id):
try:
pages = ( pages = (
PageTransaction.objects.filter( PageLog.objects.filter(
page_id=page_id, page_id=page_id,
project_id=project_id, project_id=project_id,
workspace__slug=slug, workspace__slug=slug,
@ -519,9 +429,4 @@ class SubPagesEndpoint(BaseAPIView):
return Response( return Response(
SubPageSerializer(pages, many=True).data, status=status.HTTP_200_OK SubPageSerializer(pages, many=True).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,
)

View File

@ -0,0 +1,54 @@
# Generated by Django 4.2.5 on 2023-11-13 12:53
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('db', '0046_alter_analyticview_created_by_and_more'),
]
operations = [
migrations.CreateModel(
name='PageLog',
fields=[
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')),
('id', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
('transaction', models.UUIDField(null=True)),
('entity_identifier', models.UUIDField(null=True)),
('entity_name', models.CharField(choices=[('to_do', 'To Do'), ('issue', 'issue'), ('image', 'Image'), ('video', 'Video'), ('file', 'File'), ('link', 'Link'), ('cycle', 'Cycle'), ('module', 'Module'), ('back_link', 'Back Link'), ('forward_link', 'Forward Link'), ('mention', 'Mention')], default='to_do', max_length=30, verbose_name='Transaction Type')),
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created_by', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='page_log', to='db.page')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_%(class)s', to='db.project')),
('updated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated_by', to=settings.AUTH_USER_MODEL, verbose_name='Last Modified By')),
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='workspace_%(class)s', to='db.workspace')),
],
options={
'verbose_name': 'Page Log',
'verbose_name_plural': 'Page Logs',
'db_table': 'page_logs',
'ordering': ('-created_at',),
'unique_together': {('page', 'transaction')}
},
),
migrations.AddField(
model_name='page',
name='archived_at',
field=models.DateField(null=True),
),
migrations.AddField(
model_name='page',
name='is_locked',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='page',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_page', to='db.page'),
),
]

View File

@ -68,7 +68,7 @@ from .integration import (
from .importer import Importer from .importer import Importer
from .page import Page, PageTransaction, PageFavorite, PageLabel from .page import Page, PageLog, PageFavorite, PageLabel
from .estimate import Estimate, EstimatePoint from .estimate import Estimate, EstimatePoint

View File

@ -43,7 +43,7 @@ class Page(ProjectBaseModel):
return f"{self.owned_by.email} <{self.name}>" return f"{self.owned_by.email} <{self.name}>"
class PageTransaction(ProjectBaseModel): class PageLog(ProjectBaseModel):
TYPE_CHOICES = ( TYPE_CHOICES = (
("to_do", "To Do"), ("to_do", "To Do"),
("issue", "issue"), ("issue", "issue"),
@ -59,7 +59,7 @@ class PageTransaction(ProjectBaseModel):
) )
transaction = models.UUIDField(null=True) transaction = models.UUIDField(null=True)
page = models.ForeignKey( page = models.ForeignKey(
Page, related_name="page_relation", on_delete=models.CASCADE Page, related_name="page_log", on_delete=models.CASCADE
) )
entity_identifier = models.UUIDField(null=True) entity_identifier = models.UUIDField(null=True)
entity_name = models.CharField( entity_name = models.CharField(
@ -71,9 +71,9 @@ class PageTransaction(ProjectBaseModel):
class Meta: class Meta:
unique_together = ["page", "transaction"] unique_together = ["page", "transaction"]
verbose_name = "Page Transaction" verbose_name = "Page Log"
verbose_name_plural = "Page Transactions" verbose_name_plural = "Page Logs"
db_table = "page_transactions" db_table = "page_logs"
ordering = ("-created_at",) ordering = ("-created_at",)
def __str__(self): def __str__(self):