dev: migrations (#4489)

* dev: estimates and pages migrations

* dev: favorite and user migrations

* chore: workspace base model

* chore: workspace user properties

* chore: removed unused variables

* chore: favorite view set changes

* chore: default sequence id

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
Nikhil 2024-05-17 15:59:55 +05:30 committed by GitHub
parent 38f5ecbdf2
commit 85b54d2490
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 338 additions and 154 deletions

View File

@ -28,7 +28,6 @@ from .project import (
ProjectMemberSerializer,
ProjectMemberInviteSerializer,
ProjectIdentifierSerializer,
ProjectFavoriteSerializer,
ProjectLiteSerializer,
ProjectMemberLiteSerializer,
ProjectDeployBoardSerializer,
@ -40,12 +39,10 @@ from .state import StateSerializer, StateLiteSerializer
from .view import (
GlobalViewSerializer,
IssueViewSerializer,
IssueViewFavoriteSerializer,
)
from .cycle import (
CycleSerializer,
CycleIssueSerializer,
CycleFavoriteSerializer,
CycleWriteSerializer,
CycleUserPropertiesSerializer,
)
@ -83,7 +80,6 @@ from .module import (
ModuleSerializer,
ModuleIssueSerializer,
ModuleLinkSerializer,
ModuleFavoriteSerializer,
ModuleUserPropertiesSerializer,
)
@ -96,7 +92,6 @@ from .page import (
PageLogSerializer,
SubPageSerializer,
PageDetailSerializer,
PageFavoriteSerializer,
)
from .estimate import (

View File

@ -7,7 +7,6 @@ from .issue import IssueStateSerializer
from plane.db.models import (
Cycle,
CycleIssue,
CycleFavorite,
CycleUserProperties,
)
@ -93,20 +92,6 @@ class CycleIssueSerializer(BaseSerializer):
"cycle",
]
class CycleFavoriteSerializer(BaseSerializer):
cycle_detail = CycleSerializer(source="cycle", read_only=True)
class Meta:
model = CycleFavorite
fields = "__all__"
read_only_fields = [
"workspace",
"project",
"user",
]
class CycleUserPropertiesSerializer(BaseSerializer):
class Meta:
model = CycleUserProperties

View File

@ -11,7 +11,6 @@ from plane.db.models import (
ModuleMember,
ModuleIssue,
ModuleLink,
ModuleFavorite,
ModuleUserProperties,
)
@ -223,19 +222,6 @@ class ModuleDetailSerializer(ModuleSerializer):
fields = ModuleSerializer.Meta.fields + ["link_module", "sub_issues"]
class ModuleFavoriteSerializer(BaseSerializer):
module_detail = ModuleFlatSerializer(source="module", read_only=True)
class Meta:
model = ModuleFavorite
fields = "__all__"
read_only_fields = [
"workspace",
"project",
"user",
]
class ModuleUserPropertiesSerializer(BaseSerializer):
class Meta:
model = ModuleUserProperties

View File

@ -6,7 +6,6 @@ from .base import BaseSerializer
from plane.db.models import (
Page,
PageLog,
PageFavorite,
PageLabel,
Label,
)
@ -141,17 +140,4 @@ class PageLogSerializer(BaseSerializer):
"workspace",
"project",
"page",
]
class PageFavoriteSerializer(BaseSerializer):
page_detail = PageSerializer(source="page", read_only=True)
class Meta:
model = PageFavorite
fields = "__all__"
read_only_fields = [
"workspace",
"project",
"user",
]
]

View File

@ -13,7 +13,6 @@ from plane.db.models import (
ProjectMember,
ProjectMemberInvite,
ProjectIdentifier,
ProjectFavorite,
ProjectDeployBoard,
ProjectPublicMember,
)
@ -197,16 +196,6 @@ class ProjectIdentifierSerializer(BaseSerializer):
fields = "__all__"
class ProjectFavoriteSerializer(BaseSerializer):
class Meta:
model = ProjectFavorite
fields = "__all__"
read_only_fields = [
"workspace",
"user",
]
class ProjectMemberLiteSerializer(BaseSerializer):
member = UserLiteSerializer(read_only=True)
is_subscribed = serializers.BooleanField(read_only=True)

View File

@ -5,7 +5,7 @@ from rest_framework import serializers
from .base import BaseSerializer, DynamicBaseSerializer
from .workspace import WorkspaceLiteSerializer
from .project import ProjectLiteSerializer
from plane.db.models import GlobalView, IssueView, IssueViewFavorite
from plane.db.models import GlobalView, IssueView
from plane.utils.issue_filters import issue_filters
@ -72,16 +72,3 @@ class IssueViewSerializer(DynamicBaseSerializer):
validated_data["query"] = {}
validated_data["query"] = issue_filters(query_params, "PATCH")
return super().update(instance, validated_data)
class IssueViewFavoriteSerializer(BaseSerializer):
view_detail = IssueViewSerializer(source="issue_view", read_only=True)
class Meta:
model = IssueViewFavorite
fields = "__all__"
read_only_fields = [
"workspace",
"project",
"user",
]

View File

@ -24,7 +24,7 @@ from rest_framework.response import Response
from plane.app.permissions import ProjectEntityPermission
from plane.db.models import (
Cycle,
CycleFavorite,
UserFavorite,
Issue,
Label,
User,
@ -42,9 +42,10 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
]
def get_queryset(self):
favorite_subquery = CycleFavorite.objects.filter(
favorite_subquery = UserFavorite.objects.filter(
user=self.request.user,
cycle_id=OuterRef("pk"),
entity_type="cycle",
entity_identifier=OuterRef("pk"),
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
)

View File

@ -30,7 +30,6 @@ from plane.app.permissions import (
ProjectLitePermission,
)
from plane.app.serializers import (
CycleFavoriteSerializer,
CycleSerializer,
CycleUserPropertiesSerializer,
CycleWriteSerializer,
@ -38,8 +37,8 @@ from plane.app.serializers import (
from plane.bgtasks.issue_activites_task import issue_activity
from plane.db.models import (
Cycle,
CycleFavorite,
CycleIssue,
UserFavorite,
CycleUserProperties,
Issue,
Label,
@ -67,9 +66,10 @@ class CycleViewSet(BaseViewSet):
)
def get_queryset(self):
favorite_subquery = CycleFavorite.objects.filter(
favorite_subquery = UserFavorite.objects.filter(
user=self.request.user,
cycle_id=OuterRef("pk"),
entity_identifier=OuterRef("pk"),
entity_type="cycle",
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
)
@ -241,7 +241,7 @@ class CycleViewSet(BaseViewSet):
"backlog_issues",
"assignee_ids",
"status",
"created_by"
"created_by",
)
if data:
@ -754,8 +754,7 @@ class CycleDateCheckEndpoint(BaseAPIView):
class CycleFavoriteViewSet(BaseViewSet):
serializer_class = CycleFavoriteSerializer
model = CycleFavorite
model = UserFavorite
def get_queryset(self):
return self.filter_queryset(
@ -767,18 +766,21 @@ class CycleFavoriteViewSet(BaseViewSet):
)
def create(self, request, slug, project_id):
serializer = CycleFavoriteSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user, project_id=project_id)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
_ = UserFavorite.objects.create(
project_id=project_id,
user=request.user,
entity_type="cycle",
entity_identifier=request.data.get("cycle"),
)
return Response(status=status.HTTP_204_NO_CONTENT)
def destroy(self, request, slug, project_id, cycle_id):
cycle_favorite = CycleFavorite.objects.get(
cycle_favorite = UserFavorite.objects.get(
project=project_id,
entity_type="cycle",
user=request.user,
workspace__slug=slug,
cycle_id=cycle_id,
entity_identifier=cycle_id,
)
cycle_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

View File

@ -25,12 +25,7 @@ from plane.app.permissions import (
from plane.app.serializers import (
ModuleDetailSerializer,
)
from plane.db.models import (
Issue,
Module,
ModuleFavorite,
ModuleLink,
)
from plane.db.models import Issue, Module, ModuleLink, UserFavorite
from plane.utils.analytics_plot import burndown_plot
from plane.utils.user_timezone_converter import user_timezone_converter
@ -46,9 +41,10 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
]
def get_queryset(self):
favorite_subquery = ModuleFavorite.objects.filter(
favorite_subquery = UserFavorite.objects.filter(
user=self.request.user,
module_id=OuterRef("pk"),
entity_identifier=OuterRef("pk"),
entity_type="module",
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
)

View File

@ -32,7 +32,6 @@ from plane.app.permissions import (
)
from plane.app.serializers import (
ModuleDetailSerializer,
ModuleFavoriteSerializer,
ModuleLinkSerializer,
ModuleSerializer,
ModuleUserPropertiesSerializer,
@ -42,7 +41,7 @@ from plane.bgtasks.issue_activites_task import issue_activity
from plane.db.models import (
Issue,
Module,
ModuleFavorite,
UserFavorite,
ModuleIssue,
ModuleLink,
ModuleUserProperties,
@ -69,9 +68,10 @@ class ModuleViewSet(BaseViewSet):
)
def get_queryset(self):
favorite_subquery = ModuleFavorite.objects.filter(
favorite_subquery = UserFavorite.objects.filter(
user=self.request.user,
module_id=OuterRef("pk"),
entity_type="module",
entity_identifier=OuterRef("pk"),
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
)
@ -554,8 +554,7 @@ class ModuleLinkViewSet(BaseViewSet):
class ModuleFavoriteViewSet(BaseViewSet):
serializer_class = ModuleFavoriteSerializer
model = ModuleFavorite
model = UserFavorite
def get_queryset(self):
return self.filter_queryset(
@ -567,18 +566,21 @@ class ModuleFavoriteViewSet(BaseViewSet):
)
def create(self, request, slug, project_id):
serializer = ModuleFavoriteSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user, project_id=project_id)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
_ = UserFavorite.objects.create(
project_id=project_id,
user=request.user,
entity_type="module",
entity_identifier=request.data.get("module"),
)
return Response(status=status.HTTP_204_NO_CONTENT)
def destroy(self, request, slug, project_id, module_id):
module_favorite = ModuleFavorite.objects.get(
project=project_id,
module_favorite = UserFavorite.objects.get(
project_id=project_id,
user=request.user,
workspace__slug=slug,
module_id=module_id,
entity_type="module",
entity_identifier=module_id,
)
module_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

View File

@ -15,7 +15,6 @@ from rest_framework.response import Response
from plane.app.permissions import ProjectEntityPermission
from plane.app.serializers import (
PageFavoriteSerializer,
PageLogSerializer,
PageSerializer,
SubPageSerializer,
@ -23,8 +22,8 @@ from plane.app.serializers import (
)
from plane.db.models import (
Page,
PageFavorite,
PageLog,
UserFavorite,
ProjectMember,
)
@ -61,9 +60,10 @@ class PageViewSet(BaseViewSet):
]
def get_queryset(self):
subquery = PageFavorite.objects.filter(
subquery = UserFavorite.objects.filter(
user=self.request.user,
page_id=OuterRef("pk"),
entity_type="page",
entity_identifier=OuterRef("pk"),
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
)
@ -303,23 +303,24 @@ class PageFavoriteViewSet(BaseViewSet):
ProjectEntityPermission,
]
serializer_class = PageFavoriteSerializer
model = PageFavorite
model = UserFavorite
def create(self, request, slug, project_id, pk):
_ = PageFavorite.objects.create(
_ = UserFavorite.objects.create(
project_id=project_id,
page_id=pk,
entity_identifier=pk,
entity_type="page",
user=request.user,
)
return Response(status=status.HTTP_204_NO_CONTENT)
def destroy(self, request, slug, project_id, pk):
page_favorite = PageFavorite.objects.get(
page_favorite = UserFavorite.objects.get(
project=project_id,
user=request.user,
workspace__slug=slug,
page_id=pk,
entity_identifier=pk,
entity_type="page",
)
page_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

View File

@ -28,7 +28,6 @@ from plane.app.views.base import BaseViewSet, BaseAPIView
from plane.app.serializers import (
ProjectSerializer,
ProjectListSerializer,
ProjectFavoriteSerializer,
ProjectDeployBoardSerializer,
)
@ -42,7 +41,7 @@ from plane.db.models import (
ProjectMember,
Workspace,
State,
ProjectFavorite,
UserFavorite,
ProjectIdentifier,
Module,
Cycle,
@ -90,10 +89,11 @@ class ProjectViewSet(BaseViewSet):
)
.annotate(
is_favorite=Exists(
ProjectFavorite.objects.filter(
UserFavorite.objects.filter(
user=self.request.user,
entity_identifier=OuterRef("pk"),
entity_type="project",
project_id=OuterRef("pk"),
workspace__slug=self.kwargs.get("slug"),
)
)
)
@ -560,8 +560,7 @@ class ProjectUserViewsEndpoint(BaseAPIView):
class ProjectFavoritesViewSet(BaseViewSet):
serializer_class = ProjectFavoriteSerializer
model = ProjectFavorite
model = UserFavorite
def get_queryset(self):
return self.filter_queryset(
@ -579,15 +578,21 @@ class ProjectFavoritesViewSet(BaseViewSet):
serializer.save(user=self.request.user)
def create(self, request, slug):
serializer = ProjectFavoriteSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
_ = UserFavorite.objects.create(
user=request.user,
entity_type="project",
entity_identifier=request.data.get("project"),
project_id=request.data.get("project"),
)
return Response(status=status.HTTP_204_NO_CONTENT)
def destroy(self, request, slug, project_id):
project_favorite = ProjectFavorite.objects.get(
project=project_id, user=request.user, workspace__slug=slug
project_favorite = UserFavorite.objects.get(
entity_identifier=project_id,
entity_type="project",
project=project_id,
user=request.user,
workspace__slug=slug,
)
project_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

View File

@ -27,7 +27,6 @@ from .. import BaseViewSet
from plane.app.serializers import (
IssueViewSerializer,
IssueSerializer,
IssueViewFavoriteSerializer,
)
from plane.app.permissions import (
WorkspaceEntityPermission,
@ -37,7 +36,7 @@ from plane.db.models import (
Workspace,
IssueView,
Issue,
IssueViewFavorite,
UserFavorite,
IssueLink,
IssueAttachment,
)
@ -273,9 +272,10 @@ class IssueViewViewSet(BaseViewSet):
serializer.save(project_id=self.kwargs.get("project_id"))
def get_queryset(self):
subquery = IssueViewFavorite.objects.filter(
subquery = UserFavorite.objects.filter(
user=self.request.user,
view_id=OuterRef("pk"),
entity_identifier=OuterRef("pk"),
entity_type="view",
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
)
@ -310,8 +310,7 @@ class IssueViewViewSet(BaseViewSet):
class IssueViewFavoriteViewSet(BaseViewSet):
serializer_class = IssueViewFavoriteSerializer
model = IssueViewFavorite
model = UserFavorite
def get_queryset(self):
return self.filter_queryset(
@ -323,18 +322,21 @@ class IssueViewFavoriteViewSet(BaseViewSet):
)
def create(self, request, slug, project_id):
serializer = IssueViewFavoriteSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user, project_id=project_id)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
_ = UserFavorite.objects.create(
user=request.user,
entity_identifier=request.data.get("view"),
entity_type="view",
project_id=project_id,
)
return Response(status=status.HTTP_204_NO_CONTENT)
def destroy(self, request, slug, project_id, view_id):
view_favorite = IssueViewFavorite.objects.get(
view_favorite = UserFavorite.objects.get(
project=project_id,
user=request.user,
workspace__slug=slug,
view_id=view_id,
entity_type="view",
entity_identifier=view_id,
)
view_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

View File

@ -7,7 +7,6 @@ from zxcvbn import zxcvbn
## Module imports
from plane.app.serializers import (
ChangePasswordSerializer,
UserSerializer,
)
from plane.authentication.utils.login import user_login

View File

@ -45,6 +45,51 @@ def migrate_user_profile(apps, schema_editor):
)
def user_favorite_migration(apps, schema_editor):
# Import the models
CycleFavorite = apps.get_model("db", "CycleFavorite")
ModuleFavorite = apps.get_model("db", "ModuleFavorite")
ProjectFavorite = apps.get_model("db", "ProjectFavorite")
PageFavorite = apps.get_model("db", "PageFavorite")
IssueViewFavorite = apps.get_model("db", "IssueViewFavorite")
UserFavorite = apps.get_model("db", "UserFavorite")
# List of source models
source_models = [
CycleFavorite,
ModuleFavorite,
ProjectFavorite,
PageFavorite,
IssueViewFavorite,
]
entity_mapper = {
"CycleFavorite": "cycle",
"ModuleFavorite": "module",
"ProjectFavorite": "project",
"PageFavorite": "page",
"IssueViewFavorite": "view",
}
for source_model in source_models:
entity_type = entity_mapper[source_model.__name__]
UserFavorite.objects.bulk_create(
[
UserFavorite(
user_id=obj.user_id,
entity_type=entity_type,
entity_identifier=str(getattr(obj, entity_type).id),
project_id=obj.project_id,
workspace_id=obj.workspace_id,
created_by_id=obj.created_by_id,
updated_by_id=obj.updated_by_id,
)
for obj in source_model.objects.all().iterator()
],
batch_size=1000,
)
class Migration(migrations.Migration):
dependencies = [
@ -262,9 +307,156 @@ class Migration(migrations.Migration):
name="logo_props",
field=models.JSONField(default=dict),
),
# Pages
migrations.AddField(
model_name="page",
name="logo_props",
field=models.JSONField(default=dict),
),
migrations.AddField(
model_name="page",
name="description_binary",
field=models.BinaryField(null=True),
),
migrations.AlterField(
model_name="page",
name="name",
field=models.CharField(blank=True, max_length=255),
),
# Estimates
migrations.AddField(
model_name="estimate",
name="type",
field=models.CharField(default="Categories", max_length=255),
),
migrations.AlterField(
model_name="estimatepoint",
name="key",
field=models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(12),
],
),
),
migrations.AlterField(
model_name="issue",
name="estimate_point",
field=models.IntegerField(
blank=True,
null=True,
validators=[
django.core.validators.MinValueValidator(0),
django.core.validators.MaxValueValidator(12),
],
),
),
# workspace user properties
migrations.AlterModelTable(
name="workspaceuserproperties",
table="workspace_user_properties",
),
# Favorites
migrations.CreateModel(
name="UserFavorite",
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,
),
),
("entity_type", models.CharField(max_length=100)),
("entity_identifier", models.UUIDField(blank=True, null=True)),
(
"name",
models.CharField(blank=True, max_length=255, null=True),
),
("is_folder", models.BooleanField(default=False)),
("sequence", models.IntegerField(default=65535)),
(
"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",
),
),
(
"parent",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="parent_folder",
to="db.userfavorite",
),
),
(
"project",
models.ForeignKey(
null=True,
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",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="favorites",
to=settings.AUTH_USER_MODEL,
),
),
(
"workspace",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="workspace_%(class)s",
to="db.workspace",
),
),
],
options={
"verbose_name": "User Favorite",
"verbose_name_plural": "User Favorites",
"db_table": "user_favorites",
"ordering": ("-created_at",),
"unique_together": {
("entity_type", "user", "entity_identifier")
},
},
),
migrations.RunPython(user_favorite_migration),
]

View File

@ -98,3 +98,5 @@ from .exporter import ExporterHistory
from .webhook import Webhook, WebhookLog
from .dashboard import Dashboard, DashboardWidget, Widget
from .favorite import UserFavorite

View File

@ -11,6 +11,7 @@ class Estimate(ProjectBaseModel):
description = models.TextField(
verbose_name="Estimate Description", blank=True
)
type = models.CharField(max_length=255, default="Categories")
def __str__(self):
"""Return name of the estimate"""
@ -31,7 +32,7 @@ class EstimatePoint(ProjectBaseModel):
related_name="points",
)
key = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(7)]
default=0, validators=[MinValueValidator(0), MaxValueValidator(12)]
)
description = models.TextField(blank=True)
value = models.CharField(max_length=20)

View File

@ -0,0 +1,52 @@
from django.conf import settings
# Django imports
from django.db import models
# Module imports
from .workspace import WorkspaceBaseModel
class UserFavorite(WorkspaceBaseModel):
"""_summary_
UserFavorite (model): To store all the favorites of the user
"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="favorites",
)
entity_type = models.CharField(max_length=100)
entity_identifier = models.UUIDField(null=True, blank=True)
name = models.CharField(max_length=255, blank=True, null=True)
is_folder = models.BooleanField(default=False)
sequence = models.IntegerField(default=65535)
parent = models.ForeignKey(
"self",
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="parent_folder",
)
class Meta:
unique_together = ["entity_type", "user", "entity_identifier"]
verbose_name = "User Favorite"
verbose_name_plural = "User Favorites"
db_table = "user_favorites"
ordering = ("-created_at",)
def save(self, *args, **kwargs):
if self._state.adding:
largest_sort_order = UserFavorite.objects.filter(
workspace=self.workspace
).aggregate(largest=models.Max("sort_order"))["largest"]
if largest_sort_order is not None:
self.sort_order = largest_sort_order + 10000
super(UserFavorite, self).save(*args, **kwargs)
def __str__(self):
"""Return user and the entity type"""
return f"{self.user.email} <{self.entity_type}>"

View File

@ -120,7 +120,7 @@ class Issue(ProjectBaseModel):
related_name="state_issue",
)
estimate_point = models.IntegerField(
validators=[MinValueValidator(0), MaxValueValidator(7)],
validators=[MinValueValidator(0), MaxValueValidator(12)],
null=True,
blank=True,
)

View File

@ -16,7 +16,7 @@ def get_view_props():
class Page(ProjectBaseModel):
name = models.CharField(max_length=255)
name = models.CharField(max_length=255, blank=True)
description = models.JSONField(default=dict, blank=True)
description_html = models.TextField(blank=True, default="<p></p>")
description_stripped = models.TextField(blank=True, null=True)
@ -43,6 +43,7 @@ class Page(ProjectBaseModel):
is_locked = models.BooleanField(default=False)
view_props = models.JSONField(default=get_view_props)
logo_props = models.JSONField(default=dict)
description_binary = models.BinaryField(null=True)
class Meta:
verbose_name = "Page"

View File

@ -325,7 +325,7 @@ class WorkspaceUserProperties(BaseModel):
unique_together = ["workspace", "user"]
verbose_name = "Workspace User Property"
verbose_name_plural = "Workspace User Property"
db_table = "Workspace_user_properties"
db_table = "workspace_user_properties"
ordering = ("-created_at",)
def __str__(self):