Skip to content

Commit 6ff258c

Browse files
gurusainathsainath
andauthored
chore: Add fields to issue_version and profile tables, and create new sticky table (#6198)
* chore: added fields in issue_version and profile tables and created a new sticky table * chore: removed point in issue version * chore: add imports in init --------- Co-authored-by: sainath <sainath@sainaths-MacBook-Pro.local>
1 parent a8140a5 commit 6ff258c

File tree

5 files changed

+246
-36
lines changed

5 files changed

+246
-36
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Generated by Django 4.2.17 on 2024-12-13 10:09
2+
3+
from django.conf import settings
4+
import django.core.validators
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
import django.utils.timezone
8+
import plane.db.models.user
9+
import uuid
10+
11+
12+
class Migration(migrations.Migration):
13+
14+
dependencies = [
15+
('db', '0086_issueversion_alter_teampage_unique_together_and_more'),
16+
]
17+
18+
operations = [
19+
migrations.RemoveField(
20+
model_name='issueversion',
21+
name='description',
22+
),
23+
migrations.RemoveField(
24+
model_name='issueversion',
25+
name='description_binary',
26+
),
27+
migrations.RemoveField(
28+
model_name='issueversion',
29+
name='description_html',
30+
),
31+
migrations.RemoveField(
32+
model_name='issueversion',
33+
name='description_stripped',
34+
),
35+
migrations.AddField(
36+
model_name='issueversion',
37+
name='activity',
38+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='versions', to='db.issueactivity'),
39+
),
40+
migrations.AddField(
41+
model_name='profile',
42+
name='is_mobile_onboarded',
43+
field=models.BooleanField(default=False),
44+
),
45+
migrations.AddField(
46+
model_name='profile',
47+
name='mobile_onboarding_step',
48+
field=models.JSONField(default=plane.db.models.user.get_mobile_default_onboarding),
49+
),
50+
migrations.AddField(
51+
model_name='profile',
52+
name='mobile_timezone_auto_set',
53+
field=models.BooleanField(default=False),
54+
),
55+
migrations.AlterField(
56+
model_name='issueversion',
57+
name='owned_by',
58+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issue_versions', to=settings.AUTH_USER_MODEL),
59+
),
60+
migrations.CreateModel(
61+
name='Sticky',
62+
fields=[
63+
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
64+
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')),
65+
('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='Deleted At')),
66+
('id', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
67+
('name', models.TextField()),
68+
('description', models.JSONField(blank=True, default=dict)),
69+
('description_html', models.TextField(blank=True, default='<p></p>')),
70+
('description_stripped', models.TextField(blank=True, null=True)),
71+
('description_binary', models.BinaryField(null=True)),
72+
('logo_props', models.JSONField(default=dict)),
73+
('color', models.CharField(blank=True, max_length=255, null=True)),
74+
('background_color', models.CharField(blank=True, max_length=255, null=True)),
75+
('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')),
76+
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stickies', to=settings.AUTH_USER_MODEL)),
77+
('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')),
78+
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stickies', to='db.workspace')),
79+
],
80+
options={
81+
'verbose_name': 'Sticky',
82+
'verbose_name_plural': 'Stickies',
83+
'db_table': 'stickies',
84+
'ordering': ('-created_at',),
85+
},
86+
),
87+
migrations.CreateModel(
88+
name='IssueDescriptionVersion',
89+
fields=[
90+
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
91+
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')),
92+
('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='Deleted At')),
93+
('id', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
94+
('description_binary', models.BinaryField(null=True)),
95+
('description_html', models.TextField(blank=True, default='<p></p>')),
96+
('description_stripped', models.TextField(blank=True, null=True)),
97+
('description_json', models.JSONField(blank=True, default=dict)),
98+
('last_saved_at', models.DateTimeField(default=django.utils.timezone.now)),
99+
('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')),
100+
('issue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='description_versions', to='db.issue')),
101+
('owned_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issue_description_versions', to=settings.AUTH_USER_MODEL)),
102+
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_%(class)s', to='db.project')),
103+
('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')),
104+
('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='workspace_%(class)s', to='db.workspace')),
105+
],
106+
options={
107+
'verbose_name': 'Issue Description Version',
108+
'verbose_name_plural': 'Issue Description Versions',
109+
'db_table': 'issue_description_versions',
110+
},
111+
),
112+
]

apiserver/plane/db/models/__init__.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
IssueSequence,
4242
IssueSubscriber,
4343
IssueVote,
44+
IssueVersion,
45+
IssueDescriptionVersion,
4446
)
4547
from .module import Module, ModuleIssue, ModuleLink, ModuleMember, ModuleUserProperties
4648
from .notification import EmailNotificationLog, Notification, UserNotificationPreference
@@ -68,15 +70,6 @@
6870
WorkspaceUserProperties,
6971
)
7072

71-
72-
73-
74-
75-
76-
77-
78-
79-
8073
from .favorite import UserFavorite
8174

8275
from .issue_type import IssueType
@@ -86,3 +79,5 @@
8679
from .label import Label
8780

8881
from .device import Device, DeviceSession
82+
83+
from .sticky import Sticky

apiserver/plane/db/models/issue.py

Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from plane.utils.html_processor import strip_tags
1616
from plane.db.mixins import SoftDeletionManager
1717
from plane.utils.exception_logger import log_exception
18+
from .base import BaseModel
1819
from .project import ProjectBaseModel
1920

2021

@@ -660,24 +661,18 @@ def __str__(self):
660661

661662

662663
class IssueVersion(ProjectBaseModel):
663-
issue = models.ForeignKey(
664-
"db.Issue", on_delete=models.CASCADE, related_name="versions"
665-
)
666664
PRIORITY_CHOICES = (
667665
("urgent", "Urgent"),
668666
("high", "High"),
669667
("medium", "Medium"),
670668
("low", "Low"),
671669
("none", "None"),
672670
)
671+
673672
parent = models.UUIDField(blank=True, null=True)
674673
state = models.UUIDField(blank=True, null=True)
675674
estimate_point = models.UUIDField(blank=True, null=True)
676675
name = models.CharField(max_length=255, verbose_name="Issue Name")
677-
description = models.JSONField(blank=True, default=dict)
678-
description_html = models.TextField(blank=True, default="<p></p>")
679-
description_stripped = models.TextField(blank=True, null=True)
680-
description_binary = models.BinaryField(null=True)
681676
priority = models.CharField(
682677
max_length=30,
683678
choices=PRIORITY_CHOICES,
@@ -686,22 +681,36 @@ class IssueVersion(ProjectBaseModel):
686681
)
687682
start_date = models.DateField(null=True, blank=True)
688683
target_date = models.DateField(null=True, blank=True)
684+
assignees = ArrayField(models.UUIDField(), blank=True, default=list)
689685
sequence_id = models.IntegerField(default=1, verbose_name="Issue Sequence ID")
686+
labels = ArrayField(models.UUIDField(), blank=True, default=list)
690687
sort_order = models.FloatField(default=65535)
691688
completed_at = models.DateTimeField(null=True)
692689
archived_at = models.DateField(null=True)
693690
is_draft = models.BooleanField(default=False)
694691
external_source = models.CharField(max_length=255, null=True, blank=True)
695692
external_id = models.CharField(max_length=255, blank=True, null=True)
696693
type = models.UUIDField(blank=True, null=True)
697-
last_saved_at = models.DateTimeField(default=timezone.now)
698-
owned_by = models.UUIDField()
699-
assignees = ArrayField(models.UUIDField(), blank=True, default=list)
700-
labels = ArrayField(models.UUIDField(), blank=True, default=list)
701694
cycle = models.UUIDField(null=True, blank=True)
702695
modules = ArrayField(models.UUIDField(), blank=True, default=list)
703-
properties = models.JSONField(default=dict)
704-
meta = models.JSONField(default=dict)
696+
properties = models.JSONField(default=dict) # issue properties
697+
meta = models.JSONField(default=dict) # issue meta
698+
last_saved_at = models.DateTimeField(default=timezone.now)
699+
700+
issue = models.ForeignKey(
701+
"db.Issue", on_delete=models.CASCADE, related_name="versions"
702+
)
703+
activity = models.ForeignKey(
704+
"db.IssueActivity",
705+
on_delete=models.SET_NULL,
706+
null=True,
707+
related_name="versions",
708+
)
709+
owned_by = models.ForeignKey(
710+
settings.AUTH_USER_MODEL,
711+
on_delete=models.CASCADE,
712+
related_name="issue_versions",
713+
)
705714

706715
class Meta:
707716
verbose_name = "Issue Version"
@@ -721,36 +730,86 @@ def log_issue_version(cls, issue, user):
721730

722731
Module = apps.get_model("db.Module")
723732
CycleIssue = apps.get_model("db.CycleIssue")
733+
IssueAssignee = apps.get_model("db.IssueAssignee")
734+
IssueLabel = apps.get_model("db.IssueLabel")
724735

725736
cycle_issue = CycleIssue.objects.filter(issue=issue).first()
726737

727738
cls.objects.create(
728739
issue=issue,
729-
parent=issue.parent,
730-
state=issue.state,
731-
point=issue.point,
732-
estimate_point=issue.estimate_point,
740+
parent=issue.parent_id,
741+
state=issue.state_id,
742+
estimate_point=issue.estimate_point_id,
733743
name=issue.name,
734-
description=issue.description,
735-
description_html=issue.description_html,
736-
description_stripped=issue.description_stripped,
737-
description_binary=issue.description_binary,
738744
priority=issue.priority,
739745
start_date=issue.start_date,
740746
target_date=issue.target_date,
747+
assignees=list(
748+
IssueAssignee.objects.filter(issue=issue).values_list(
749+
"assignee_id", flat=True
750+
)
751+
),
741752
sequence_id=issue.sequence_id,
753+
labels=list(
754+
IssueLabel.objects.filter(issue=issue).values_list(
755+
"label_id", flat=True
756+
)
757+
),
742758
sort_order=issue.sort_order,
743759
completed_at=issue.completed_at,
744760
archived_at=issue.archived_at,
745761
is_draft=issue.is_draft,
746762
external_source=issue.external_source,
747763
external_id=issue.external_id,
748-
type=issue.type,
749-
last_saved_at=issue.last_saved_at,
750-
assignees=issue.assignees,
751-
labels=issue.labels,
752-
cycle=cycle_issue.cycle if cycle_issue else None,
753-
modules=Module.objects.filter(issue=issue).values_list("id", flat=True),
764+
type=issue.type_id,
765+
cycle=cycle_issue.cycle_id if cycle_issue else None,
766+
modules=list(
767+
Module.objects.filter(issue=issue).values_list("id", flat=True)
768+
),
769+
properties={},
770+
meta={},
771+
last_saved_at=timezone.now(),
772+
owned_by=user,
773+
)
774+
return True
775+
except Exception as e:
776+
log_exception(e)
777+
return False
778+
779+
780+
class IssueDescriptionVersion(ProjectBaseModel):
781+
issue = models.ForeignKey(
782+
"db.Issue", on_delete=models.CASCADE, related_name="description_versions"
783+
)
784+
description_binary = models.BinaryField(null=True)
785+
description_html = models.TextField(blank=True, default="<p></p>")
786+
description_stripped = models.TextField(blank=True, null=True)
787+
description_json = models.JSONField(default=dict, blank=True)
788+
last_saved_at = models.DateTimeField(default=timezone.now)
789+
owned_by = models.ForeignKey(
790+
settings.AUTH_USER_MODEL,
791+
on_delete=models.CASCADE,
792+
related_name="issue_description_versions",
793+
)
794+
795+
class Meta:
796+
verbose_name = "Issue Description Version"
797+
verbose_name_plural = "Issue Description Versions"
798+
db_table = "issue_description_versions"
799+
800+
@classmethod
801+
def log_issue_description_version(cls, issue, user):
802+
try:
803+
"""
804+
Log the issue description version
805+
"""
806+
cls.objects.create(
807+
issue=issue,
808+
description_binary=issue.description_binary,
809+
description_html=issue.description_html,
810+
description_stripped=issue.description_stripped,
811+
description_json=issue.description,
812+
last_saved_at=timezone.now(),
754813
owned_by=user,
755814
)
756815
return True
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Django imports
2+
from django.conf import settings
3+
from django.db import models
4+
5+
# Module imports
6+
from .base import BaseModel
7+
8+
9+
class Sticky(BaseModel):
10+
name = models.TextField()
11+
12+
description = models.JSONField(blank=True, default=dict)
13+
description_html = models.TextField(blank=True, default="<p></p>")
14+
description_stripped = models.TextField(blank=True, null=True)
15+
description_binary = models.BinaryField(null=True)
16+
17+
logo_props = models.JSONField(default=dict)
18+
color = models.CharField(max_length=255, blank=True, null=True)
19+
background_color = models.CharField(max_length=255, blank=True, null=True)
20+
21+
workspace = models.ForeignKey(
22+
"db.Workspace", on_delete=models.CASCADE, related_name="stickies"
23+
)
24+
owner = models.ForeignKey(
25+
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="stickies"
26+
)
27+
28+
class Meta:
29+
verbose_name = "Sticky"
30+
verbose_name_plural = "Stickies"
31+
db_table = "stickies"
32+
ordering = ("-created_at",)

apiserver/plane/db/models/user.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ def get_default_onboarding():
2626
}
2727

2828

29+
def get_mobile_default_onboarding():
30+
return {
31+
"profile_complete": False,
32+
"workspace_create": False,
33+
"workspace_join": False,
34+
}
35+
36+
2937
class User(AbstractBaseUser, PermissionsMixin):
3038
id = models.UUIDField(
3139
default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
@@ -178,6 +186,10 @@ class Profile(TimeAuditModel):
178186
billing_address = models.JSONField(null=True)
179187
has_billing_address = models.BooleanField(default=False)
180188
company_name = models.CharField(max_length=255, blank=True)
189+
# mobile
190+
is_mobile_onboarded = models.BooleanField(default=False)
191+
mobile_onboarding_step = models.JSONField(default=get_mobile_default_onboarding)
192+
mobile_timezone_auto_set = models.BooleanField(default=False)
181193

182194
class Meta:
183195
verbose_name = "Profile"

0 commit comments

Comments
 (0)